/*
 * The fixture page — favourite button, score header, tab bar and the panels
 * behind it. Every tab has a panel now, each in its own stylesheet
 * (`fixture-preview.css`, `fixture-predictions.css`, `fixture-facts.css`,
 * `match-lineup.css`, `fixture-statistics.css`, `fixture-commentary.css`);
 * `.fixture-details__panel-empty` below is kept for the next tab that lands
 * before its panel does.
 *
 * Constrained to the shell width rather than the window, same as the search
 * overlay and the story viewer: on a phone that is genuinely full-bleed, and on
 * desktop it keeps the mini app inside its own frame instead of taking over the
 * browser tab.
 *
 * Two layers, and they stay apart because they animate different properties:
 *
 *   .fixture-details          the fade. Also the ground, so nothing of the page
 *                             behind shows through mid-transition.
 *   .fixture-details__sheet   the travel — a short rise on entry.
 */

.fixture-details {
  /* Distance the sheet rises through on entry. Small on purpose: the page is
     arriving, not being thrown. */
  --enter-y: calc(12px * var(--scale));

  position: fixed;
  inset: 0;
  /*
   * Under the search overlay's 90 and the story viewer's 100. This page is
   * opened *from* the fixtures list, and both of those cover that list
   * entirely — so neither can be up at the same time as this, and if that ever
   * changes, the surface opened from this one has to win.
   */
  z-index: 80;
  display: flex;
  max-width: var(--app-max-width);
  margin-inline: auto;
  background: var(--bg);
  opacity: 0;
  transition: opacity var(--duration) var(--easing);
}

/* A class beats the UA [hidden] rule, so display has to be turned off by hand. */
.fixture-details[hidden] {
  display: none;
}

.fixture-details[data-open="true"] {
  --enter-y: 0px;

  opacity: 1;
}

.fixture-details__sheet {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Safe-area clearance only, no extra `--space-2` on top of it: this sits
     above the scrolling body, so the sticky tab row (tab-bar.css) sticks
     flush against whatever's left here — any padding beyond the notch/status
     bar itself reads as a gap above it once stuck. `.fixture-details__bar`'s
     own margin-top is what gives the back button its breathing room at
     rest instead. */
  padding-top: var(--safe-top);
  transform: translateY(var(--enter-y));
  transition: transform var(--duration) var(--easing);
}

/* --- Bar ------------------------------------------------------------------ */

/*
 * Leave on the left, act on the right — and no title between them. The header
 * stack below is the page's title; a second one spelling the fixture out in
 * words would say twice what two crests and a scoreline already say once, at
 * the top of a screen the score block is the whole point of.
 */
.fixture-details__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  /* Carries the top spacing `.fixture-details__body` used to reserve for
     every child — moved here, onto the one child that actually scrolls
     away, so the sticky tab row (tab-bar.css) isn't measured against it too
     and left sitting a `--space-4` gap below the top once stuck. */
  margin-top: var(--space-4);
  padding-inline: var(--space-3);
}

.fixture-details__spacer {
  flex: 1;
}

/*
 * .icon-btn is a grey chip built to lift off the white page, which is exactly
 * what all three of these are doing — so unlike the app bar's copy they keep
 * their fill. Only the size comes down, to the 34px the header row already uses.
 */
.fixture-details__back,
.fixture-details__action {
  width: calc(34px * var(--scale));
  height: calc(34px * var(--scale));
}

/*
 * Following fills the bell and tints its chip. --accent-soft is the token
 * tokens.css reserves for exactly this, and the accent is what "this one is
 * active" means everywhere else in the app — so a followed match needs no
 * further explanation than the colour it shares with every other selection.
 */
.fixture-details__follow {
  transition:
    background-color var(--duration) var(--easing),
    border-color var(--duration) var(--easing),
    color var(--duration) var(--easing);
}

.fixture-details__follow[aria-pressed="true"] {
  background: var(--accent-soft);
  /* Transparent rather than removed: a border that disappeared would resize the
     chip by two pixels on every toggle. */
  border-color: transparent;
  color: var(--accent);
}

/* --- Body ----------------------------------------------------------------- */

.fixture-details__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  overflow-y: auto;
  /* The page behind is already scroll-locked; this stops a flick at either end
     from handing the gesture back to it anyway. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* No top value — see the comment on `.fixture-details__bar`'s own
     margin-top, which carries that spacing instead. */
  padding: 0 0 var(--space-6);
}

/* With the slip tray's pill docked over the page at the nav row's height,
   the last card's Add to slip can scroll clear of it: the row's footprint
   on top of the page's own bottom space. */
body[data-slip-tray="true"] .fixture-details__body {
  padding-bottom: calc(var(--space-6) + var(--nav-height) + var(--space-5) + max(var(--safe-bottom), var(--tg-chrome-inset, 0px)));
}

/* --- Panels ---------------------------------------------------------------- */

/*
 * The tab row's panels. Almost no rules of its own beyond being the box they
 * sit in: each panel owns its own padding and its own cross-fade (see
 * `.fixture-predictions`), the same arrangement the club and league pages'
 * panel containers have.
 *
 * The exception is the density below.
 */

/*
 * The panels ran at `zoom: 0.9` on a phone until 19 Sep 2026 — one
 * instruction to the whole subtree, and the reason every tab here read a
 * tenth smaller than the same cards on the club and competition pages. They
 * are on the universal scale now (tokens.css); a panel that wants to read
 * denser picks smaller steps.
 */

/*
 * The tab row's stand-in while the page asks which sections the fixture has
 * (`decideSections` in FixtureDetails.js). The row's own box — its borders
 * and vertical padding are `.tab-bar`'s and `.tab-bar__tab`'s, kept in step
 * by hand — with four label-shaped pulses on it, so the header sits on the
 * same line it will once the tabs land and nothing below it moves when they
 * do. Sets its own `display`, so it also has to honour `hidden` itself.
 */
.fixture-details__tabs-skeleton {
  display: flex;
  gap: var(--space-5);
  padding: var(--space-2) var(--space-4) var(--space-3);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.fixture-details__tabs-skeleton[hidden] {
  display: none;
}

.fixture-details__tabs-skeleton .skeleton {
  height: calc(var(--text-sm) * 1.5);
  width: calc(64px * var(--scale));
  border-radius: var(--radius-full);
}

.fixture-details__tabs-skeleton .skeleton:nth-child(2) {
  width: calc(84px * var(--scale));
}

.fixture-details__tabs-skeleton .skeleton:nth-child(4) {
  width: calc(92px * var(--scale));
}

/*
 * The stand-in behind the five tabs with nothing written for them yet. A plain
 * centred line, deliberately plain: it says a section is coming rather than
 * dressing an empty box up as content, and it is one `PANELS` entry away from
 * being replaced (FixtureDetails.js).
 */
.fixture-details__panel-empty {
  padding: var(--space-8) var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
  opacity: 1;
  transition: opacity var(--duration) var(--easing);
}

/* A class beats the UA [hidden] rule — same note as `.fixture-details[hidden]`
   above. This one only needs it because the rule above sets `padding`, not
   `display`, but the pair has to stay explicit either way. */
.fixture-details__panel-empty[hidden] {
  display: none;
}

.fixture-details__panel-empty[data-open="false"] {
  opacity: 0;
}

/* --- Score header ---------------------------------------------------------- */

/*
 * Home, score, away. The two team columns share a width and the centre takes
 * what is left, so the scoreline is centred on the page rather than on whatever
 * the longer club name happens to be — and a long name on one side cannot push
 * the score off the middle.
 *
 * BADGE_SIZE in FixtureDetails.js names the same mark step as --badge-size
 * below — `Logo()` writes that box as an inline style — so the two are kept
 * in step by naming the step, not by copying a number.
 */
.fixture-score {
  /* One value for the crest and everything measured against it: the star's
     box is the crest's height, so the two are centred on each other by
     construction rather than by a hand-tuned offset. */
  --badge-size: var(--mark-3xl);
  /*
   * How far the star is pulled in from the column's outer edge, towards the
   * crest it belongs to. It has a ceiling: the crest is centred in a 1fr column
   * whose width depends on how wide the scoreline is, so a bigger inset walks
   * the star towards the mark and eventually under it. --space-2 leaves
   * clearance at every scoreline this feed produces.
   */
  --star-inset: var(--space-2);

  display: grid;
  /*
   * Two rows sharing three columns: crests and scoreline above, scorers below.
   * One grid rather than two stacked ones is what makes the lists line up with
   * the teams they belong to — a separate block underneath would be a second set
   * of tracks that agrees with these at one viewport width and drifts at every
   * other. The row is `auto`, so a fixture with no goals collapses it to nothing.
   */
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  column-gap: var(--space-2);
  row-gap: var(--space-3);
  padding-inline: var(--space-4);
}

/*
 * When the match is: "18 Sep 2026 • 20:00", one pill across the top of the
 * score grid, centred over the scoreline. `--surface-inverse` rather than
 * --accent for the same reason the commentary's VAR chip picks it: accent
 * means "active" across the app, and a date is a fact, not a selection. The
 * dark chip is the one fill that carries a small line of white type without
 * claiming anything.
 */
.fixture-when {
  grid-column: 1 / -1;
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-snug);
  white-space: nowrap;
}

.fixture-when__dot {
  opacity: 0.6;
}

.fixture-team {
  position: relative;
  min-width: 0;
}

/*
 * The star sits in the column's outer corner, level with the crest — its box is
 * exactly the crest's height, so `place-items: center` puts the glyph on the
 * crest's own centreline whatever --badge-size is set to. It is a sibling of
 * the navigating button, never a child: nested buttons are invalid, and later
 * in the DOM means the touch that lands on the star is never also the one that
 * opens the team.
 */
.fixture-team__star {
  position: absolute;
  top: 0;
  display: grid;
  place-items: center;
  width: calc(32px * var(--scale));
  height: var(--badge-size);
  color: var(--text-muted);
}

.fixture-team--home .fixture-team__star {
  left: var(--star-inset);
}

.fixture-team--away .fixture-team__star {
  right: var(--star-inset);
}

/* Filled blue: --accent owns "this one is selected", and a favourite is that. */
.fixture-team__star[aria-pressed="true"] {
  color: var(--accent);
}

.fixture-team__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-width: 0;
  /* The star is beside the crest, not above it, so nothing has to be cleared. */
  padding-inline: var(--space-1);
}

/*
 * The box the crest is fitted into. Fixed at the crest's own size so the column
 * keeps its height whether the mark is a wide pennant or a tall shield, and so
 * the star opposite has something stable to centre against.
 */
.fixture-team__badge {
  display: grid;
  place-items: center;
  height: var(--badge-size);
}

/*
 * Contained, not covered, and not rounded.
 *
 * `.logo` fills its box (`object-fit: cover`) and `TeamLogo` masks it into a
 * disc, which is right at 18px in a list where a crest is an identifier. Here
 * it is the picture: a shield or a pennant cropped to a circle loses its points
 * and its bottom, and at 53px that is the first thing the eye lands on. So the
 * mark is fitted whole inside the box, and the grey disc behind it goes with
 * the crop — an image with its own transparent background does not need a
 * plate under it.
 */
.fixture-team__badge .logo {
  width: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.fixture-team__badge .logo:not(.logo--monogram) {
  background: none;
  border-radius: 0;
}

/* The fallback still needs its plate — a bare monogram has nothing to sit on. */
.fixture-team__badge .logo--monogram {
  width: var(--badge-size);
  border-radius: var(--radius-full);
  font-size: var(--text-lg);
}

/*
 * Wraps rather than truncating. A crest with "Borussia Mönchengla…" under it
 * has told you less than the crest did on its own, and this is the one place in
 * the app with room for the whole name — the list is where names get cut.
 */
.fixture-team__name {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  text-align: center;
  text-wrap: balance;
}

/*
 * The four nodes the status swap switches on and off.
 *
 * Not optional, and not defensive: `[hidden] { display: none }` is a *UA* rule,
 * so any author `display` in this file outranks it and the element stays on
 * screen with the attribute set. That is exactly what happened here — a
 * scheduled fixture drew the live clock's prime and its refresh mark under the
 * kick-off time, because `.fixture-score__status` is `display: flex`. The
 * overlay roots make the same declaration for the same reason.
 *
 * Not all of these currently set `display`, so some do not strictly need it.
 * They are listed anyway: the failure is silent, and the next person to give
 * one of them a `display` should not have to rediscover this.
 */
.fixture-score__line[hidden],
.fixture-score__standin[hidden],
.fixture-score__status[hidden],
.fixture-score__notes[hidden],
.fixture-team__reds[hidden] {
  display: none;
}

/*
 * The scoreline is centred on the crests, not on the whole column: the names
 * below run to one line or two depending on the club, and a score that tracked
 * the column's centre would sit at a different height on every fixture.
 */
.fixture-score__centre {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: var(--badge-size);
}

/*
 * The scoreline. Tabular figures for the same reason the list's score column
 * has them: a goal must change the number without moving it, and Plus Jakarta
 * Sans is proportional by default.
 */
.fixture-score__value {
  font-size: var(--text-4xl);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-tight);
  white-space: nowrap;
}

.fixture-score__dash {
  margin-inline: var(--space-2);
  color: var(--text-muted);
}

/*
 * The kick-off time, or the word a fixture with no score has for itself. Set
 * smaller than the scoreline it replaces: "21:00" at the score's size reads as
 * a result, which is the one thing it is not.
 */
.fixture-score__standin {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
}

/*
 * Live. The red is --highlight, which owns exactly one fact in this app, and it
 * is the same fact the running minute and the scoreline already carry on the
 * row this page was opened from — so the page and the list agree about what is
 * in play, in the same colour.
 *
 * Scheduled and finished scorelines are deliberately not coloured here: both are
 * ordinary text, which is what body colour already gives them.
 */
.fixture-score[data-status="live"] .fixture-score__value,
.fixture-score[data-status="live"] .fixture-score__status {
  color: var(--highlight);
}

/*
 * The final score, once it is final: the winner keeps the full weight and the
 * page's text colour, the loser drops to the muted grey and one step of weight.
 *
 * Only the loser is restyled. Making the winner *more* than it already is has
 * nowhere to go — the scoreline is --weight-bold, the top of the scale in
 * tokens.css — so the contrast is built by taking emphasis off the other digit
 * rather than by inventing a heavier one. The result reads the same way and
 * keeps the winning number at exactly the size and weight it has in every other
 * state, which is what stops a result looking like a different component.
 *
 * A draw sets `draw` on both and neither is touched: level is not two losses.
 */
.fixture-score__digit[data-outcome="loss"] {
  color: var(--text-muted);
  font-weight: var(--weight-semibold);
}

/*
 * One value, centred under the scoreline. Nothing sits beside it: the seconds
 * hand counting is what says the number is live, so the mark that used to say it
 * is gone and the line keeps the page's centreline.
 *
 * Muted by default, because that is what it is in every state but one — a
 * finished match's "Finished" is metadata about a score that has stopped
 * moving. Live overrides it to the red above, where the clock is not metadata
 * but the second half of the claim the scoreline is making.
 */
.fixture-score__status {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

/*
 * How the result was reached past the scoreline — "Aggregate 3–2 · Chelsea
 * won 4–3 on penalties" (`renderNotes`, FixtureDetails.js). A step under the
 * status line and in the body colour: it is the part of the result a reader
 * would otherwise have to go looking for, not an aside. Wraps between its
 * parts rather than inside one, since the centre column is narrow.
 */
.fixture-score__notes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 var(--space-1);
  margin: 0;
  max-width: calc(150px * var(--scale));
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.fixture-score__notes-dot {
  color: var(--text-muted);
}

/*
 * Players sent off, under the club name: one drawn card each, the size and
 * red of the Commentary rail's own booking (`.commentary__booking`), so a
 * red card is the same object everywhere on the page.
 */
.fixture-team__reds {
  display: flex;
  justify-content: center;
  gap: var(--space-05);
  margin-top: calc(-1 * var(--space-1));
}

.fixture-team__red {
  width: calc(9px * var(--scale));
  height: calc(13px * var(--scale));
  border-radius: 1.5px;
  background: var(--card-red);
}

/*
 * The tab row that used to live here is `.tab-bar` (styles/components/tab-bar.css),
 * shared with the club page. Nothing about it was fixture-specific — it moved
 * whole, class names and all, when the second caller arrived. The scorer lists
 * went the same way on 2026-09-22, to `styles/components/scorers.css`, when the
 * Catch-Up room's Game Snapshot card grew a pair of its own.
 */

/* --- Page behind ----------------------------------------------------------- */

/*
 * The list must not scroll under the page. Position is preserved on the
 * document, which is what lets the close land the user exactly where they were.
 */
body[data-fixture-open] {
  overflow: hidden;
}
