/*
 * One knob for the whole fixture block. Every length in this file and in
 * match-row.css is a token multiplied by this, so the list scales as a unit and
 * the tokens stay the source of truth — retune the density here rather than
 * across a dozen rules. Declared on the group too, so a competition rendered
 * outside the list still resolves it.
 */
.match-list,
.league {
  --fixture-scale: 0.84;
}

/*
 * Each group is a card: rows of black type sitting bare on the page read as
 * unfinished next to the bordered chrome above them, so the group carries the
 * same card the header bar and date strip wear — on the white page it is the
 * hairline and --shadow-card that draw the edge — and the gap between cards
 * is what separates competitions, smaller than the old bare-page gap since
 * the card edge is doing the grouping work the whitespace alone used to.
 */
.match-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.league {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  /* Rounds the row press-fills and the top row's corners into the card edge. */
  overflow: clip;

  /* The panel below animates grid-template-rows, which reflows on every
     frame — layout containment scopes that reflow to this group alone, so
     collapsing one competition doesn't force the browser to re-check every
     other one in the list. Without it, a long list is what turns a single
     accordion's collapse choppy on device. */
  contain: layout paint;

  /* A full day is several hundred fixtures, and the browser was laying out and
     painting every one of them whether or not it was anywhere near the screen.
     This skips that work for groups that are off screen and does it as they
     approach, which is where the rest of the scrolling cost went — and it also
     holds back the crests inside them, since an image in a skipped subtree
     doesn't start loading. Lazy loading gets stricter for free.

     The estimate keeps the scrollbar honest before a group has ever rendered:
     `auto` means the browser replaces it with the real height the first time
     it does, so a wrong guess is a one-time correction rather than permanent
     drift — but it is worth guessing well, because until a group has been on
     screen once the guess is the whole scrollbar. 46 and 55 are the measured
     header and row at --fixture-scale; --league-rows is the match count, set
     in LeagueAccordion.js.

     Safe to drop this rule and the collapsed one below if they ever fight
     Lenis — everything above stands without them. */
  content-visibility: auto;
  contain-intrinsic-size: auto calc(46px + var(--league-rows, 6) * 55px);
}

/*
 * Most competitions start collapsed, and a collapsed group is its header and
 * nothing else — the panel is at 0fr. Estimating those at full height was
 * doubling the length of the list before any of it had rendered, so the
 * scrollbar shrank under the thumb as groups came into view. Keyed off the same
 * attribute that drives the collapse, so it stays true when one is toggled.
 */
.league[data-collapsed="true"] {
  contain-intrinsic-size: auto 46px;
}

.league__header {
  display: flex;
  align-items: center;
  gap: calc(var(--space-2) * var(--fixture-scale));
  width: 100%;
  /* A step more inline breathing room than the rows get on their own: the
     card edge is right there now, and type flush against a border reads
     cramped where type flush against open page never did. */
  padding: calc(var(--space-2) * var(--fixture-scale))
    calc(var(--space-3) * var(--fixture-scale));
  text-align: left;
}

.league__identity {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.league__name {
  font-size: calc(var(--text-md) * var(--fixture-scale));
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

/*
 * Country, round, qualification stage — whatever the feed actually knows. The
 * element is absent rather than empty when it knows nothing (see
 * LeagueAccordion.js), so this never reserves a line it has no use for.
 */
.league__subtitle {
  color: var(--text-muted);
  font-size: calc(var(--text-xs) * var(--fixture-scale));
}

/*
 * Bare, no disc. The whole header row is the toggle and the row itself is the
 * affordance — the glyph only has to report which way it is pointing, and a
 * filled chip here would compete with the crest beside it for weight.
 *
 * Down while collapsed, up while open — the slip accordion's own reading,
 * rather than the sideways chevron this used to turn to.
 */
.league__chevron {
  display: grid;
  place-items: center;
  width: calc(27px * var(--fixture-scale));
  height: calc(27px * var(--fixture-scale));
  color: var(--text-muted);
  transform: rotate(180deg);
  transition: transform var(--duration) var(--easing);
}

.league[data-collapsed="true"] .league__chevron {
  transform: none;
}

/* 0fr -> 1fr gives an animated collapse without measuring heights. */
.league__panel {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows var(--duration) var(--easing);
}

.league[data-collapsed="true"] .league__panel {
  grid-template-rows: 0fr;
}

.league__panel-inner {
  min-height: 0;
  overflow: hidden;
}

/*
 * The hairline under the header, and the only border the group draws. It is a
 * separator between the header row and its fixtures, not an edge around them —
 * there is nothing to the left or right of it to close.
 */
.league__matches {
  border-top: 1px solid var(--border);
}
