/* EliteTracker
   ------------------------------------------------------------------
   One typeface (Archivo variable) worked across its width axis: expanded
   for display, normal for prose, tabular figures for data. The palette is
   cold Nordic paper and petrol ink; the only saturated colours on the page
   belong to data, so a hue always means something.

   Data colours come from the validated data-viz palette:
     sequential  blue 100..700   -> finishing-position probability
     diverging   blue|grey|red   -> home win | draw | away win
   Both were checked for colour-vision separation in light and dark.        */

/* ---------- tokens ------------------------------------------------ */

:root {
  color-scheme: light;

  --paper: #e9edf1;
  --panel: #ffffff;
  --panel-sunk: #f3f6f8;
  --ink: #0d1a22;
  --ink-muted: #55666f;
  --ink-faint: #5a6c77;   /* 4.6:1 on paper; was 2.6:1 */
  --rule: #bcc8d1;
  --rule-strong: #9ab0bb;

  /* Default label ink on a cell, and the inverted ink used once the fill
     has moved far enough from the surface. */
  --cell-ink: #0d1a22;
  --cell-ink-invert: #ffffff;

  /* Qualification markers only -- labelled status marks, not part of the
     quantitative encoding above. */
  --outcome-good: #1d63bb;   /* 5.0:1 as text on paper */
  --outcome-bad: #c43534;    /* 4.6:1 as text on paper */

  /* Sequential data ramp. Multi-hue on purpose: sixteen stacked bands cannot
     be told apart in one hue. Resampled at uniform OKLab lightness from the
     ColorBrewer YlGnBu path, so lightness is monotone and every neighbouring
     pair clears dE 10.5 (light) / 11.3 (dark). The ramp is oriented per theme
     so it always moves away from the surface. */
  --seq-1: #d0edb3;
  --seq-2: #8bd1ba;
  --seq-3: #3db2c4;
  --seq-4: #1e8cbe;
  --seq-5: #2265ac;
  --seq-6: #253d98;
  --seq-7: #12246b;

  /* Diverging: home win <- draw -> away win. */
  --home: #1d63bb;   /* white odds labels 5.9:1 (was 4.4:1) */
  --draw: #8c8c86;
  --away: #c43534;   /* white odds labels 5.3:1 (was 4.0:1) */


  /* Outcome meters in the table. They borrow the qualification-marker colours
     on purpose: the stripe on a row's leading edge and the bar in its "Win it"
     column then mean the same thing in the same colour. Blue against red is
     also the validated diverging pair, holding CVD dE 21.6 light / 19.2 dark
     -- far clear of green against red, which manages only 12.4.

     Drawn SOLID: diluted into pale washes these collapse to dE ~3, and the two
     columns would read identically to a colour-blind viewer. Dark mode needs no
     override, because --outcome-* is already redefined there. */
  --meter-up: var(--outcome-good);
  --meter-down: var(--outcome-bad);

  /* Division identity: two categories, so two fixed hues. Eliteserien's
     violet keeps clear of --outcome-good, which is the blue that reads as
     "win" on rating changes (this used to be #2a78d6, nearly that blue; dark
     was #3987e5, exactly it). Light values must clear 4.5:1 as white text on
     the season row's pill, dark ones as --panel text on it. */
  --tier-1: #6f38d6;
  --tier-2: #c94a1c;

  /* Reserved status hues for qualification bands. Each ships with a label. */
  --band-champion: #f2c600;   /* yellow, kept clear of the EL orange in hue */

  /* European qualification edges on the season-shape chart.
     CL reuses --outcome-good (blue). EL orange and ECL green chosen for
     WCAG AA as label text on chart surface (paper) in BOTH themes. */
  --edge-cl: var(--outcome-good);
  --edge-el: #e07b1f;   /* orange, 4.8:1 on paper light, 5.2:1 on panel dark */
  --edge-ecl: #1e8a49;  /* green,  5.1:1 on paper light, 5.4:1 on panel dark */

  --shadow: 0 1px 2px rgb(13 26 34 / 0.04), 0 12px 32px -16px rgb(13 26 34 / 0.16);
  /* A faint wash of the brand blue behind the top of the page. */
  --glow: rgb(42 120 214 / 0.08);

  --measure: 68ch;
  --gutter: clamp(1rem, 4vw, 3rem);
  /* Panels and cards; controls use --radius-sm, toggles are full pills. */
  --radius: 14px;
  --radius-sm: 8px;

  --display: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
  --body: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* Dark palette. data-resolved-theme is set by the head script (before first
   paint) and by resolveTheme(): the user's choice, else the OS preference. */
:root[data-resolved-theme="dark"] {
  color-scheme: dark;

  --paper: #0b1116;
  --panel: #131c22;
  --panel-sunk: #0f171c;
  --ink: #e7eef3;
  --ink-muted: #93a6b1;
  --ink-faint: #7f939e;   /* 5.4:1 on panel; was 3.6:1 */
  --rule: #22303a;
  --rule-strong: #34454f;

  --cell-ink: #ffffff;
  --cell-ink-invert: #0d1a22;

  --outcome-good: #3987e5;
  --outcome-bad: #e66767;

  --seq-1: #081d58;
  --seq-2: #22318d;
  --seq-3: #225aa6;
  --seq-4: #1d7aac;   /* white numbers 4.7:1; #1f83b9 left both inks at 4.2:1 */
  --seq-5: #36abc3;
  --seq-6: #80cdbb;
  --seq-7: #caeab4;

  --home: #3987e5;
  --draw: #b5b5ac;
  --away: #e66767;

  --tier-1: #a78bfa;
  --tier-2: #d95926;

  --band-champion: #facc15;

  /* European qualification edges on the season-shape chart (dark). */
  --edge-cl: var(--outcome-good);
  --edge-el: #f09c3a;   /* lighter orange, 5.3:1 on panel dark */
  --edge-ecl: #4ade80;  /* lighter green,  5.5:1 on panel dark */

  /* The inset line lifts a panel's top edge off the page, the way light falls on it. */
  --shadow: inset 0 1px 0 rgb(255 255 255 / 0.04), 0 1px 2px rgb(0 0 0 / 0.35), 0 16px 40px -20px rgb(0 0 0 / 0.7);
  --glow: rgb(57 135 229 / 0.12);
}

/* ---------- base -------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* The page must never scroll sideways. Wide tables scroll inside their own
   panels, so anything overflowing to this level is a layout bug. clip (rather
   than hidden) avoids making <body> a scroll container. */
html, body { overflow-x: clip; }

body {
  margin: 0;
  background: radial-gradient(1100px 520px at 50% -240px, var(--glow), transparent 70%) no-repeat, var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  font-synthesis-weight: none;
}

h1, h2, h3 {
  font-family: var(--display);
  font-variation-settings: "wdth" 118;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.05;
  margin: 0;
  text-wrap: balance;
}

/* A small uppercase utility label. Used for eyebrows and column heads,
   never for prose. */
.label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-variation-settings: "wdth" 105;
}

a { color: inherit; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--home);
  outline-offset: 2px;
  border-radius: 2px;
}

.shell {
  max-width: 1220px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Off-screen until focused: the first Tab lands here and jumps past the
   navigation to the content (WCAG 2.4.1). */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: 0.75rem;
  z-index: 100;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform 0.15s var(--ease);
}
.skip-link:focus { transform: none; }
main:focus { outline: none; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

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

/* The sticky masthead (and the phone bottom bar, below) would otherwise
   cover whatever keyboard focus or a skip link scrolls to (WCAG 2.4.11). */
html { scroll-padding-top: 76px; }
@media (max-width: 760px) {
  html { scroll-padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
}

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--rule);
}

.masthead__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 60px;
}

.masthead__views {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

.masthead__views::-webkit-scrollbar { display: none; }

.wordmark {
  font-family: var(--display);
  font-variation-settings: "wdth" 125;
  font-weight: 800;
  font-size: 1.0625rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  margin-right: auto;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.wordmark span {
  font-variation-settings: "wdth" 100;
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
}

/* Segmented control: the league switch and the theme switch share it. */
.switch {
    display: inline-flex;
    background: var(--panel-sunk);
    border: 1px solid var(--rule);
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
  }

  .switch button {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--ink-muted);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 0.3rem 0.85rem;
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s var(--ease), color 0.15s var(--ease), box-shadow 0.15s var(--ease);
  }

  .switch button:hover { color: var(--ink); }

  .switch button[aria-pressed="true"] {
    background: var(--panel);
    color: var(--ink);
    box-shadow: 0 1px 3px rgb(13 26 34 / 0.18), inset 0 0 0 1px var(--rule);
  }

  /* Table view toggle: the same segmented pill as .switch. */
  .table-controls {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    background: var(--panel-sunk);
    border: 1px solid var(--rule);
    border-radius: 999px;
  }

  .table-control-btn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--ink-muted);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 0.3rem 0.95rem;
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s var(--ease), color 0.15s var(--ease), box-shadow 0.15s var(--ease);
  }

  .table-control-btn:hover { color: var(--ink); }

  .table-control-btn[aria-pressed="true"] {
    background: var(--panel);
    color: var(--ink);
    box-shadow: 0 1px 3px rgb(13 26 34 / 0.18), inset 0 0 0 1px var(--rule);
  }

/* Fixture difficulty pill — diverging red–gray–green ramp.
   --fd-hue: 0 (red) or 135 (green); --fd-sat/--fd-light interpolated to gray at k=0.
   --fd-alpha: 0.1 (mean) → 0.45 (league extreme). Flat bg, no gradient. */
.fixture-difficulty-pill {
    padding: 0 6px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    display: inline-block;
    min-width: 42px;
    text-align: center;
    background: hsl(var(--fd-hue) var(--fd-sat) var(--fd-light) / var(--fd-alpha));
    color: hsl(var(--fd-hue) var(--fd-sat) 24%);
    transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}

:root[data-resolved-theme="dark"] .fixture-difficulty-pill {
    color: hsl(var(--fd-hue) var(--fd-sat) 78%);
}

/* ---------- hero -------------------------------------------------- */

/* The masthead already names the league and season, so the hero's job is to
   say what the model thinks -- not to fill a screen before any data appears.
   On a wide screen the vitals sit beside the headline instead of under it. */
.hero {
  padding-block: clamp(1.25rem, 3vw, 2rem) 1.25rem;
  display: grid;
  gap: 0.75rem 3rem;
  align-items: end;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 1000px) {
  .hero { grid-template-columns: minmax(0, 1fr) auto; }
  .hero__meta { grid-column: 2; grid-row: 1 / span 2; }
}

.hero h1 {
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-variation-settings: "wdth" 125;
  max-width: 22ch;
}

.hero-title-part {
  cursor: pointer;
  border-bottom: 2px dashed var(--ink-faint);
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.hero-title-part:hover {
  border-color: var(--ink);
  color: var(--outcome-good);
}

/* A chevron says "this opens a list" where the dashed underline alone only
   hinted at it; it turns over while the list is open. */
.hero-title-part::after {
  content: "";
  display: inline-block;
  width: 0.32em;
  height: 0.32em;
  margin: 0 0.1em 0.18em 0.28em;
  border-right: 0.08em solid currentColor;
  border-bottom: 0.08em solid currentColor;
  transform: rotate(45deg);
  opacity: 0.55;
  transition: transform 0.15s var(--ease), opacity 0.15s var(--ease);
}
.hero-title-part:hover::after { opacity: 1; }
.hero-title-part[aria-expanded="true"]::after { transform: translateY(0.12em) rotate(-135deg); opacity: 1; }

.hero p {
  margin: 0;
  max-width: var(--measure);
  color: var(--ink-muted);
  font-size: 1rem;
}

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  align-content: end;
  gap: 0.4rem 1.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--rule);
}

@media (min-width: 1000px) {
  .hero__meta {
    flex-direction: column;
    gap: 0.3rem;
    padding-top: 0;
    padding-left: 1.5rem;
    border-top: 0;
    border-left: 1px solid var(--rule);
  }
}

/* In a club's view the league's story and vitals are someone else's
   headline; the title stays, since its league and season pickers still
   navigate. On a phone the vitals repeat the lede and push the content down. */
body[data-view="team"] #hero-lede,
body[data-view="team"] .hero__meta { display: none; }
body[data-view="team"] .hero { padding-bottom: 0.5rem; }
@media (max-width: 760px) {
  .hero__meta { display: none; }
}

.hero__meta div { display: flex; align-items: baseline; gap: 0.5rem; }
.hero__meta b { font-weight: 700; font-size: 1rem; }

/* ---------- panels ------------------------------------------------ */

section { margin-block: clamp(1.5rem, 3vw, 2.25rem); }

.panel {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: clip;
}

.panel__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem 2rem;
  flex-wrap: wrap;
  padding: 1.1rem 1.25rem;
  border-bottom: 1px solid var(--rule);
}

.panel__head h2 { font-size: 1.25rem; }

.panel__head p {
  margin: 0.35rem 0 0;
  color: var(--ink-muted);
  font-size: 0.875rem;
  max-width: 62ch;
}

/* A scrollport. position: relative keeps absolutely-positioned descendants
   (the .visually-hidden header labels inside the wide tables) inside this box,
   so they are clipped here instead of escaping to widen the page. */
.scroller { position: relative; overflow-x: auto; }

/* Fade the trailing edge while there is more table to the right, so the scroll
   is discoverable. scroll-timeline drives it off the scroller's own position,
   so it clears as you reach the end; browsers without it get the plain fade. */
@supports (animation-timeline: scroll(self inline)) {
  .scroller {
    scroll-timeline: --edge inline;
    animation: scroller-fade linear both;
    animation-timeline: --edge;
  }

  @keyframes scroller-fade {
    from { mask-image: linear-gradient(90deg, #000 88%, transparent 100%); }
    to { mask-image: linear-gradient(90deg, #000 100%, #000 100%); }
  }
}

/* ---------- the finish grid (signature) --------------------------- */

.grid-wrap { padding: 1.25rem; }

table.grid {
  border-collapse: separate;
  border-spacing: 2px; /* the 2px surface gap between cells */
  font-size: 0.75rem;
  margin-inline: auto;
}

table.grid th {
  font-weight: 600;
  color: var(--ink-muted);
  font-size: 0.6875rem;
  padding: 0;
}

table.grid thead th {
  text-align: center;
  padding-bottom: 0.35rem;
  min-width: 2.1rem;
}

/* Left-aligned, so the current position and the crest sit in one column on
   every row; right-aligned, they floated with the length of the name. */
table.grid tbody th {
  text-align: left;
  padding-right: 0.6rem;
  white-space: nowrap;
  color: var(--ink);
  font-weight: 500;
  font-size: 0.8125rem;
  /* Pinned so the club stays readable while the positions scroll past it. */
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--panel);
}

table.grid tbody th .pos,
table.grid .grid__corner .pos {
  display: inline-block;
  width: 1.5rem;
  margin-right: 0.4rem;
  text-align: right;
  color: var(--ink-faint);
  font-size: 0.6875rem;
  vertical-align: middle;
}

table.grid tbody th .played-card__team { vertical-align: middle; }
table.grid thead .grid__corner { text-align: left; }
table.grid .grid__corner abbr { text-decoration: none; cursor: help; }

.grid__team-name {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  vertical-align: middle;
}

.grid__team-name:hover { text-decoration: underline; }

/* Club crests, loaded locally. White-heavy crests get the panel colour behind
   them so they stay visible through transparent PNGs in both themes. The
   base rule carries a text-sized default so a misplaced crest never renders
   at its natural, full-size pixels; the context rules below refine it. */
.team-logo {
  display: inline-block;
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 4px;
  background: var(--panel);
  object-fit: contain;
}

table.grid tbody th .team-logo {
  width: 16px;
  height: 16px;
  margin-right: 0.4rem;
  vertical-align: middle;
}

/* The band strip rides in the table head so it shares the column geometry. */
.grid__bands td { padding: 0 0 0.3rem; height: 6px; }
.grid__bands .band-strip__seg { display: block; width: 100%; }

.cell {
  width: 2.1rem;
  height: 1.75rem;
  text-align: center;
  border-radius: 3px;
  color: var(--cell-ink);
  font-variant-numeric: tabular-nums;
  cursor: default;
  transition: transform 0.12s var(--ease), box-shadow 0.12s var(--ease);
}

.cell--invert { color: var(--cell-ink-invert); }
.cell--empty { color: transparent; }

/* Crosshair: hovering a cell dims everything outside its row and column. */
.grid:has(.cell:hover) .cell:not(:hover) { opacity: 0.45; }
.grid:has(.cell:hover) tbody tr:hover .cell { opacity: 1; }

.cell:hover {
  transform: scale(1.18);
  box-shadow: 0 0 0 2px var(--panel), 0 0 0 3px var(--ink);
  position: relative;
  z-index: 2;
}

/* On a phone the whole grid fits the screen. Scrolling it sideways showed
   seven of sixteen places at a time, and the grid's point is the pattern
   across all of them: so the columns share the width (about 18px each),
   the club is its crest, and a tap on a cell gives the exact figure. */
@media (max-width: 760px) {
  .grid-wrap { padding: 0.75rem 0.5rem; }
  table.grid {
    width: 100%;
    table-layout: fixed;
    border-spacing: 1px;
    font-size: 0.5625rem;
  }
  table.grid tr > :first-child { width: 2.5rem; }
  table.grid thead th { min-width: 0; font-size: 0.5625rem; padding-bottom: 0.2rem; }
  table.grid tbody th { padding-right: 0.2rem; }
  table.grid tbody th .pos,
  table.grid .grid__corner .pos { width: 0.9rem; margin-right: 0.15rem; font-size: 0.5625rem; }
  table.grid tbody th .team-logo { width: 14px; height: 14px; margin-right: 0; }
  .grid__team-name { display: none; }
  .cell { width: auto; height: 1.35rem; border-radius: 2px; letter-spacing: -0.02em; }
  .cell:hover { transform: none; }
}

/* One segment per column, marking what that finishing place is worth. Lives in
   the table head (.grid__bands) so it inherits the column geometry. */
.band-strip__seg {
  height: 3px;
  border-radius: 2px;
  flex: none;
}

/* Grid animation controls */
.grid-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Play / Stop: an icon and a word, since a lone triangle says nothing to a
   screen reader and not much more to anyone else. Pressed while playing. */
.grid-anim-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  height: 2rem;
  padding: 0 0.85rem 0 0.7rem;
  font-size: 0.8125rem;
  cursor: pointer;
  line-height: 1;
}
.grid-anim-btn__icon { font-size: 0.7rem; color: var(--tier-1); }
.grid-anim-btn[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--panel);
}
.grid-anim-btn[aria-pressed="true"] .grid-anim-btn__icon { color: inherit; }
.grid-anim-btn:disabled { opacity: 0.55; cursor: progress; }

/* While playing: the date on show, how far through the season it is, and the
   speed. Sits under the panel head, so it stays in view above a tall grid. */
.grid-anim-bar[hidden] { display: none; }
.grid-anim-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 1.25rem;
  border-block: 1px solid var(--rule);
  background: var(--panel-sunk);
}
.grid-anim-bar__when {
  min-width: 6.5rem;
  font-size: 0.8125rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.grid-anim-bar__track {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--rule);
  overflow: hidden;
}
.grid-anim-bar__fill {
  display: block;
  height: 100%;
  background: var(--tier-1);
  transform: scaleX(0);
  transform-origin: left;
}

/* Speed as a segmented control: all three choices visible, the current one
   filled, instead of a button that cycles through values you cannot see. */
.grid-anim-speed {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--panel);
}
.grid-anim-speed button {
  min-width: 2.25rem;
  padding: 0.2rem 0.5rem;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink-muted);
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.grid-anim-speed button:hover { color: var(--ink); }
.grid-anim-speed button[aria-pressed="true"] { background: var(--ink); color: var(--panel); }

/* Loading overlay on the grid during prefetch */
.grid-loading {
  position: relative;
}
.grid-loading::after {
  content: attr(data-loading-text); /* set from t(), so it is translated */
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: color-mix(in oklab, var(--panel) 85%, transparent);
  font-size: 0.875rem;
  color: var(--ink-muted);
  border-radius: 4px;
  z-index: 3;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
  padding: 0.9rem 1.25rem;
  border-top: 1px solid var(--rule);
  background: var(--panel-sunk);
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

.legend__key { display: inline-flex; align-items: center; gap: 0.45rem; }

.legend__swatch {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 2px;
  flex: none;
}

.legend__ramp { display: inline-flex; gap: 2px; }
.legend__ramp i { width: 1.1rem; height: 0.85rem; border-radius: 2px; }

/* The phone-sized heading, hidden until the media query calls for it. */
.sort-btn__short { display: none; }

/* ---------- standings table --------------------------------------- */

table.standings {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  min-width: 720px;
}

table.standings th,
table.standings td {
  padding: 0.5rem 0.6rem;
  text-align: right;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

/* Not sticky: .scroller sets overflow-x, which makes it the sticky scrollport,
   so a top offset would push the header down over the first rows instead of
   pinning it to the window. */
table.standings thead th {
  background: var(--panel);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom-color: var(--rule-strong);
}

table.standings tbody tr:hover { background: var(--panel-sunk); }

/* Sortable headers. A real button so the keyboard and screen readers get it
   for free; the <th> carries aria-sort. */
/* The padding moves off the cell and onto the button, so the whole header cell
   is clickable rather than just the few glyphs of the label. */
#standings thead th { padding: 0; }

.sort-btn {
  appearance: none;
  border: 0;
  margin: 0;
  padding: 0.55rem 0.6rem;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.3em;
  width: 100%;
  min-height: 2.25rem; /* clears the 24px minimum target size */
}

.sort-btn:hover { color: var(--ink); }

#standings thead th.num .sort-btn { justify-content: flex-end; }
#standings thead th.club .sort-btn { justify-content: flex-start; }
#standings thead th.pos .sort-btn { justify-content: center; }

/* Reserve the caret's space so a column does not shift when it becomes the
   sorted one. It inherits colour rather than taking an accent, which would
   land at 4.42:1 against the light panel. */
.sort-btn__caret {
  display: inline-block;
  min-width: 0.5em;
  font-size: 0.9em;
  line-height: 1;
}

table.standings th.is-sorted { color: var(--ink); }
table.standings .num { width: 3.2rem; }
table.standings .club { text-align: left; width: 100%; font-weight: 600; }
table.standings .pos { text-align: center; width: 2.6rem; color: var(--ink-muted); }
table.standings .sep { border-left: 1px solid var(--rule); }
table.standings .muted { color: var(--ink-muted); }

/* Attack/Defence pill — diverging red–gray–blue ramp.
   --ad-hue: 0 (red) or 218 (blue); --ad-sat/--ad-light interpolated to gray at k=0.
   --ad-alpha: 0.1 (avg) → 0.45 (league extreme). Flat bg, no gradient. */
.attack-defence-pill {
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  display: inline-block;
  min-width: 42px;
  text-align: center;
  background: hsl(var(--ad-hue) var(--ad-sat) var(--ad-light) / var(--ad-alpha));
  color: hsl(var(--ad-hue) var(--ad-sat) 24%);
}

/* Dark mode: text lightens (same hue/sat, 78% light) */
:root[data-resolved-theme="dark"] .attack-defence-pill {
  color: hsl(var(--ad-hue) var(--ad-sat) 78%);
}

/* A zone starts at this row (first CL slot, first conference slot, relegation
   play-off). The band-mark stripe names a single position's block; this line
   carries the whole region's colour and separates it from the teams above. */
table.standings tr.band-divider td {
  border-top: 2px solid var(--band-color, var(--rule-strong));
}

/* The zone's expected points cut-off, on the first row under the divider line:
    e.g. "CL ≈50" means a club realistically needs ~50 points to hold the band. */
table.standings .zone-threshold {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0 0.35rem;
  border-radius: 3px;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--panel-sunk);
  vertical-align: middle;
}

/* Full-width divider row between zones: text between two horizontal lines
   extending to table edges. Format: "======== Expected CL Threshold: 67p ========" */
table.standings tr.zone-divider {
  pointer-events: none;   /* not a team row */
}
table.standings tr.zone-divider td {
  padding: 0.5rem 0;
  border: none;
  background: transparent;
  width: 100%;
}
table.standings .zone-divider__wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  white-space: nowrap;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--band-color, var(--ink));
  width: 100%;
}
:root:not([data-resolved-theme="dark"]) table.standings .zone-divider__wrap {
  color: color-mix(in srgb, var(--band-color, var(--ink)) 50%, var(--ink));
}
table.standings .zone-divider__wrap::before,
table.standings .zone-divider__wrap::after {
  content: "";
  flex: 1;
  height: 1px;
  opacity: 0.7;
  background: var(--band-color, var(--rule-strong));
  min-width: 0;  /* allow shrinking below content width */
}

/* The band a position sits in, as a stripe on the row's leading edge.
   Coloured from JS by the same rule as the grid, so the two never disagree. */
.band-mark {
  display: inline-block;
  width: 3px;
  height: 1.15em;
  border-radius: 2px;
  margin-right: 0.5rem;
  vertical-align: -0.2em;
  background: transparent;
}



/* A probability as a solid bar next to its own number. The bar is at full
   strength rather than washed out behind the text: at low opacity the green
   and the red are the same colour to a deuteranope. */
.meter {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.45rem;
  width: 100%;
}

.meter__track {
  flex: none;
  width: 2.5rem;
  height: 0.45rem;
  border-radius: 3px;
  /* Not --panel-sunk: that is also the row hover colour, so the unfilled part
     of the bar disappeared exactly when you pointed at it. */
  background: var(--rule);
  overflow: hidden;
}

.meter__fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--meter-up);
}

.meter--down .meter__fill { background: var(--meter-down); }

.meter__value {
  min-width: 2.6rem; /* "100%" is the widest it now gets */
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Nothing to show: drop the track so the column reads as empty, not as zero. */
.meter--empty .meter__track { visibility: hidden; }

/* ---------- charts ---------------------------------------------- */

.chart { display: block; width: 100%; height: auto; overflow: visible; }
.chart .band { stroke: var(--panel); stroke-width: 0.6; }
.chart .band:hover { stroke: var(--ink); stroke-width: 1.2; }
.chart .axis-line { stroke: var(--rule-strong); stroke-width: 1; }
.chart .grid-line { stroke: var(--rule); stroke-width: 1; stroke-dasharray: 2 3; }
.chart .tick { fill: var(--ink-muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart .crosshair { stroke: var(--ink); stroke-width: 1; stroke-dasharray: 3 2; pointer-events: none; }
.chart .axis-title { fill: var(--ink-muted); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; }


/* ---------- rating ladder ----------------------------------------- */

/* ---------- ladder -------------------------------------------------- */

.ladder {
  padding: 1.25rem;
  overflow: hidden;
}

.ladder__track {
  position: relative;
  height: 12rem;
  width: 100%;
  transition: height 0.3s var(--ease);
}

/* ----- the strip (wide screens): crests at their rating ----- */

.ladder__axis {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1.5rem;
  overflow: hidden;
}

.ladder__tick {
  position: absolute;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  transform: translateX(-50%);
}

.ladder__tick::before {
  content: '';
  width: 1px;
  height: 0.4rem;
  background: var(--ink-faint);
  flex-shrink: 0;
}

.ladder__tick span {
  font-size: 0.6875rem;
  color: var(--ink-faint);
  white-space: nowrap;
}

.ladder__team {
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  z-index: 1;
  transform: translate(-50%, 0);
  transition: top 0.15s ease-out;
}

/* The list row's parts; the strip shows the crest alone. */
.ladder__rank, .ladder__name, .ladder__rating, .ladder__scale { display: none; }

.ladder__team img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: contain;
  background: var(--panel);
  transition: transform 0.06s ease-out;
}

.ladder__team:hover img { transform: scale(1.5); z-index: 3; }

.ladder__team::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.35rem 0.55rem;
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--radius-sm);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.08s ease-out;
}

.ladder__team:hover::after,
.ladder__team:focus-visible::after { opacity: 1; }
.ladder__team:focus-visible { z-index: 10; }

.ladder__team[data-tier="1"] img { border: 2px solid var(--tier-1); }
.ladder__team[data-tier="2"] img { border: 2px solid var(--tier-2); }

/* Touch: no hover, so the first tap shows the tip and the second opens the club. */
@media (pointer: coarse) {
  .ladder__team::after { display: none; }
  .ladder__team[data-tip-visible]::after { display: block; opacity: 1; }
  .ladder__team[data-tip-visible] { z-index: 10; }
}

/* ----- the list (narrow screens): one row per club, at its rank ----- */

.ladder__track--list { --scale-w: 34%; }
@media (max-width: 760px) { .ladder { padding: 0.5rem 0.75rem 1rem; } }

.ladder__track--list .ladder__team {
  width: 100%;
  height: 2.75rem;           /* LADDER_ROW in app.js - 44px touch target */
  transform: none;
  display: grid;
  grid-template-columns: 1.5rem 1.25rem minmax(0, 1fr) 2.4rem var(--scale-w);
  align-items: center;
  gap: 0.45rem;
  text-align: left;
  border-top: 1px solid var(--rule);
  border-radius: 0;
  transition: top 0.35s var(--ease);
}

.ladder__track--list .ladder__team:hover { background: var(--panel-sunk); }
.ladder__track--list .ladder__team::after { display: none; }

.ladder__track--list .ladder__rank {
  display: block;
  font-size: 0.75rem;
  color: var(--ink-muted);
  text-align: right;
}

.ladder__track--list .ladder__team img,
.ladder__track--list .ladder__team:hover img {
  width: 1.25rem;
  height: 1.25rem;
  border: 0;
  background: none;
  transform: none;
}

.ladder__track--list .ladder__name {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ladder__track--list .ladder__rating {
  display: block;
  font-size: 0.8125rem;
  font-weight: 700;
  text-align: right;
}

.ladder__track--list .ladder__scale {
  display: block;
  position: relative;
  height: 100%;
}

/* The club's rating on the shared scale, in its division's colour. */
.ladder__dot {
  position: absolute;
  top: 50%;
  left: var(--x);
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 2px var(--panel);
  transition: left 0.15s ease-out;
}
.ladder__team[data-tier="1"] .ladder__dot { background: var(--tier-1); }
.ladder__team[data-tier="2"] .ladder__dot { background: var(--tier-2); }

/* The scale sits over the rows' last column; each tick is a faint line down
   the list with its label in the header above the first row. */
.ladder__track--list .ladder__axis {
  top: 0;
  bottom: 0;
  left: auto;
  right: 0;
  width: var(--scale-w);
  height: auto;
  pointer-events: none;
}

.ladder__track--list .ladder__tick {
  top: 0;
  bottom: 0;
  flex-direction: column-reverse;
  justify-content: flex-end;
}

.ladder__track--list .ladder__tick::before {
  flex: 1;
  height: auto;
  background: var(--rule);
}

.ladder__track--list .ladder__tick span { font-size: 0.6875rem; line-height: 1.75rem; }

/* ---------- fixtures ---------------------------------------------- */

.fixtures { display: flex; flex-direction: column; }

/* Odds bar in fixture cards — reused in both Next Up and team view */
.fixture__odds-col {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 280px;
  max-width: 380px;
  flex: none;
}

.fixture__lines {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.3rem;
  overflow: hidden;
  justify-content: center;
  margin: 0 auto;
  min-width: 280px;
  max-width: 380px;
}

.fixture__line {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--panel-sunk);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.05rem 0.3rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* High-stakes flag on a fixture card: one merged line naming whose race rides
   on it. Panel-sunk, never tinted, so even a relegation decider reads as
   informative rather than alarming; the dots carry the band colours. */
.stake-flag {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  align-self: center;
  max-width: 100%;
  padding: 0.3rem 0.75rem;
  background: var(--panel-sunk);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: 0.8125rem;
  color: var(--ink-muted);
  text-align: center;
}
.stake-flag__dots { display: inline-flex; gap: 3px; flex: none; }
.stake-flag__dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; flex: none; }
.stake-flag__text { overflow-wrap: anywhere; }
/* Small coloured dot next to a team name on a fixture card, marking a
   decisive match. The hue matches the band; hover for details. */
.stake-dot {
  display: inline-flex;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  flex: none;
  vertical-align: middle;
  cursor: help;
  position: relative;
}
/* A finger-sized target around the 9px dot. */
.stake-dot::after { content: ""; position: absolute; inset: -12px; }
.stake-dot__tooltip { max-width: 280px; }
.stake-dot__tooltip strong {
  display: block;
  margin-bottom: 0.2rem;
}
.stake-dot__legs {
  margin-top: 0.3rem;
  font-size: 0.7rem;
  opacity: 0.75;
}

/* Stacked diverging bar: home | draw | away, with 2px surface gaps. */
.odds { display: flex; gap: 2px; height: 1.5rem; }

.odds__seg {
  display: grid;
  place-items: center;
  font-size: 0.6875rem;
  font-weight: 700;
  color: #fff;
  border-radius: 2px;
  min-width: 0;
  overflow: hidden;
}

.odds__seg:first-child { border-radius: 3px 2px 2px 3px; }
.odds__seg:last-child { border-radius: 2px 3px 3px 2px; }
.odds__seg[data-outcome="home"] { background: var(--home); }
.odds__seg[data-outcome="draw"] { background: var(--draw); color: #10171b; }
.odds__seg[data-outcome="away"] { background: var(--away); }
/* The dark theme's brighter hues take dark labels: white was 3.2-3.6:1. */
:root[data-resolved-theme="dark"] .odds__seg[data-outcome="home"],
:root[data-resolved-theme="dark"] .odds__seg[data-outcome="away"] { color: #0d1a22; }

/* Mobile: let fixture odds and lines stack instead of fixed min-width.
   Uses 760px to match the main mobile breakpoint (navigation, tables, etc.). */
@media (max-width: 760px) {
  .fixture__odds-col { min-width: 0; max-width: none; flex: 2; }
  .fixture__lines { min-width: 0; max-width: none; }
  /* The name sits under the crest rather than disappearing: crests alone
     asked the reader to know thirty badges by heart. */
  .played-card__team { flex-direction: column; gap: 0.15rem; }
  .played-card__side--home .played-card__team { flex-direction: column-reverse; }
  /* Two classes: the base rule's font: inherit comes later in the file. */
  .played-card__team .played-card__team-name {
    font-size: 0.6875rem;
    font-weight: 600;
    max-width: 4.75rem;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .played-card__side .team-logo { width: 28px; height: 28px; }

  /* Played Results and Next Up: crest only, and a bigger one. The name
     button stays, stretched invisibly over the crest, so a tap still opens
     the club, focus rings the crest and a screen reader still reads the name. */
  :is(#played-results, #fixtures, #team-content) .played-card__team { position: relative; }
  :is(#played-results, #fixtures, #team-content) .played-card__team .played-card__team-name {
    position: absolute;
    inset: 0;
    max-width: none;
    font-size: 0;
    color: transparent;
    border-radius: 6px;
  }
  :is(#played-results, #fixtures, #team-content) .played-card__side .team-logo { width: 44px; height: 44px; }
}

@media (max-width: 480px) {
  .fixture__lines { justify-content: flex-start; }
  .odds { overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
  .odds::-webkit-scrollbar { display: none; }
}

@media (max-width: 360px) {
  .odds__seg { font-size: 0.625rem; white-space: nowrap; text-overflow: ellipsis; }
}

/* Recent-form chips in the table: 5 blocks (W/D/L), colored by result. */
.form__chips { display: inline-flex; gap: 2px; justify-content: flex-end; }
.form__chip {
  width: 1.05rem; height: 1.05rem; border-radius: 3px;
  display: grid; place-items: center;
  font-size: 0.625rem; font-weight: 700; line-height: 1; color: #fff;
}
.form__chip--w { background: var(--home); }
.form__chip--d { background: var(--draw); color: #10171b; }
.form__chip--l { background: var(--away); }

/* Compare-clubs tool. Hidden <select>s hold state; the cards beneath show the
   chosen pair and open a custom popover picker with crests. */
.compare__pickers { display: none; }
.compare__select--hidden { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.compare__team {
  position: relative; cursor: pointer; text-align: right;
  display: flex; flex-direction: column; align-items: stretch; gap: 0.6rem;
  background: var(--panel-sunk); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 0.9rem 1rem;
}
.compare__card-main { display: flex; flex-direction: row; align-items: center; gap: 0.75rem; }
.compare__team .team-logo { width: 48px; height: 48px; flex: none; }
.compare__pick-hint {
  text-align: center; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ink-faint);
  border-top: 1px solid var(--rule); padding-top: 0.55rem;
}
.compare__team:hover .compare__pick-hint,
.compare__team:focus-visible .compare__pick-hint { color: var(--ink); }
#compare-output { padding: 0 1.25rem 1.25rem; }
.compare__teams { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 0.75rem; margin: 0.25rem 0 0.5rem; }
.compare__swap-center {
  font: inherit; font-size: 1.4rem; line-height: 1; color: var(--ink);
  background: var(--panel); border: 1px solid var(--rule); border-radius: 999px;
  width: 2.4rem; height: 2.4rem; cursor: pointer; display: grid; place-items: center;
  flex: none;
}
.compare__swap-center:hover { background: var(--panel-sunk); }
.compare__team-text { display: flex; flex-direction: column; align-items: flex-end; gap: 0.15rem; flex: 1; min-width: 0; }
.compare__team-side { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; }
.compare__team-name { font-size: 1.15rem; font-weight: 700; line-height: 1.1; }
.compare__team-rating { font-size: 1.7rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.compare__note { font-size: 0.8rem; color: var(--ink-faint); margin: 0 0 0.9rem; }
.compare__scorelines { margin-top: 1rem; padding: 0.7rem 0.9rem; background: var(--panel-sunk); border: 1px solid var(--rule); border-radius: var(--radius); }
.compare__scorelines-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; }
.compare__scorelines-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem; margin-top: 0.55rem; }
.compare__scoreline {
  display: flex; flex: 1 1 0; justify-content: center; align-items: baseline; gap: 0.4rem; min-width: 5rem;
  background: var(--panel); border: 1px solid var(--rule); border-radius: 999px;
  padding: 0.3rem 0.75rem; font-weight: 700; font-size: 1.05rem; font-variant-numeric: tabular-nums;
}
.compare__scoreline-prob { font-size: 0.8rem; font-weight: 600; color: var(--ink-muted); }
.compare__block { margin-top: 2.25rem; padding-top: 1.75rem; border-top: 1px solid var(--rule); }
.compare__block:first-child { margin-top: 0.75rem; padding-top: 0; border-top: 0; }
.compare__subhead { font-size: 0.95rem; font-weight: 700; margin: 0 0 0.5rem; }
.compare__block .odds { margin-top: 0.75rem; }
.compare-line { fill: none; stroke-width: 2; }
.compare-line--a { stroke: #2a78d6; }
.compare-line--b { stroke: #e0682a; }
.compare-legend__a { color: color-mix(in srgb, #2a78d6 70%, var(--ink)); font-weight: 600; margin-right: 0.75rem; }
.compare-legend__b { color: color-mix(in srgb, #e0682a 70%, var(--ink)); font-weight: 600; }
/* The line colours are chart hues; as text they are mixed toward --ink, which
   darkens them on light and lightens them on dark (>= 6:1 in both). */

.compare__menu {
  z-index: 50;
  background: var(--panel); border: 1px solid var(--rule); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 0.4rem; max-height: 60vh; overflow-y: auto;
}
.compare__option {
  display: flex; align-items: center; gap: 0.7rem; width: 100%;
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 0.55rem 0.6rem; text-align: left; cursor: pointer;
}
.compare__option:hover, .compare__option:focus-visible { background: var(--panel-sunk); outline: none; }
.compare__option:disabled { opacity: 0.4; cursor: default; }
.compare__option .team-logo { width: 32px; height: 32px; flex: none; }
.compare__option-name { font-size: 1rem; font-weight: 600; }

.compare__h2h-record {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin: 0.75rem 0 0.35rem;
  font-size: 1.5rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.compare__h2h-team { flex: 1; font-size: 0.75rem; font-weight: 600; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.compare__h2h-team:last-child { text-align: right; }
.compare__h2h-stat { font-size: 1.5rem; font-weight: 800; }
.compare__h2h-goals { display: flex; flex-direction: column; align-items: center; gap: 0.1rem; margin: 0 0 0.75rem; }
.compare__h2h-goals-label { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-muted); }
.compare__h2h-goals-stat { font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.compare__h2h-list { display: flex; flex-direction: column; gap: 0.5rem; }

/* ---------- played results ------------------------------------------ */

.played-results {
  display: flex;
  flex-direction: column;
}

/* The one pagination control (pageNav in app.js): Played Results and Next Up
   by week, the team page and Compare by page. */
.played-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 0.85rem 1.25rem;
  border-bottom: 1px solid var(--rule);
}
/* Inside an already padded section the bar lines up with its content. */
.team-section .played-nav,
.compare__block .played-nav { padding-inline: 0; }

.played-nav__btn {
  appearance: none;
  border: 1px solid var(--rule);
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 0.4rem 1rem;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease);
}

.played-nav__btn:hover { background: var(--panel-sunk); border-color: var(--rule-strong); }
.played-nav__btn:disabled { opacity: 0.35; cursor: default; }
.played-nav__btn:disabled:hover { background: var(--panel); border-color: var(--rule); }

.played-nav__label {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--ink);
  /* Flexes between the two buttons: a fixed 10rem pushed them past the
     panel edges on a 360px phone. */
  flex: 0 1 10rem;
  min-width: 0;
  text-align: center;
}

/* Card */
.played-card {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 1rem 1.5rem 0.85rem;
  border-bottom: 1px solid var(--rule);
}

.played-card:last-child { border-bottom: none; }

/* Gradient: gold on winning side, distinct from blue delta text */
/* The winner's half gets a neutral wash. It used the title gold, which
   means "champion" everywhere else and turned olive on the dark panel. */
.played-card--home-win {
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--ink) 7%, var(--panel)) 0%,
    var(--panel) 50%
  );
}

.played-card--away-win {
  background: linear-gradient(
    to left,
    color-mix(in srgb, var(--ink) 7%, var(--panel)) 0%,
    var(--panel) 50%
  );
}


/* Matchup row */
.played-card__matchup {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.played-card__side {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: 1;
}

.played-card__side--home { justify-content: flex-end; }
.played-card__side--away { justify-content: flex-start; }

.played-card__team {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.2;
  white-space: nowrap;
  min-width: 0;
}

.played-card__team-name {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.played-card__team-name:hover { text-decoration: underline; }

.played-card__side .team-logo {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

/* Rating block on the outside */
.played-card__rating {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  flex-shrink: 0;
  white-space: nowrap;
}

.played-card__rating-value {
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.played-card__delta {
  font-size: 0.8125rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.played-card__delta--up { color: var(--outcome-good); }
.played-card__delta--down { color: var(--outcome-bad); }

/* Score */
.played-card__score {
  font-family: var(--display);
  font-size: 1.375rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: center;
  white-space: nowrap;
  flex-shrink: 0;
  padding: 0 0.25rem;
  line-height: 1;
}

/* Date centered above matchup */
.played-card__date {
  text-align: center;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

@media (max-width: 760px) {
  .played-card { padding: 0.5rem 0.75rem; }
  .played-card__matchup { gap: 0.375rem; }
  .played-card__side { gap: 0.3rem; }
  /* The delta goes under the rating: side by side, the away one ran off a
     360px screen. */
  .played-card__rating { flex-direction: column; align-items: center; gap: 0; line-height: 1.15; }
  .played-card__score { font-size: 1.125rem; }
  .played-card__rating-value { font-size: 0.9375rem; }
  .played-card__delta { font-size: 0.75rem; }

  .compare__team { padding: 0.6rem 0.7rem; gap: 0.4rem; }
  .compare__team .team-logo { width: 36px; height: 36px; }
  .compare__card-main { flex-direction: column; align-items: center; gap: 0.35rem; }
  .compare__team-text { align-items: center; text-align: center; }
  .compare__team-side { font-size: 0.6875rem; }
  .compare__team-name { font-size: 0.95rem; }
  .compare__team-rating { font-size: 1.3rem; }
  .compare__pick-hint { font-size: 0.6875rem; padding-top: 0.4rem; }
  .compare__swap-center { width: 44px; height: 44px; font-size: 1.1rem; }
  .compare__scoreline { font-size: 0.85rem; padding: 0.25rem 0.6rem; min-width: 4rem; gap: 0.3rem; }
  .compare__scoreline-prob { font-size: 0.7rem; }
}

@media (max-width: 760px) {
  .compare__scoreline { min-width: auto; flex: 1 1 45%; }
}

@media (max-width: 480px) {
  .compare__h2h-record { font-size: 1.1rem; }
}

/* ---------- model card -------------------------------------------- */

.model-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  overflow: hidden; /* clips the rules the last column and row cast outward */
}

/* Each card draws its own right and bottom rule. A rule-coloured container
   behind the gaps showed through the empty cells of a short last row as a
   solid block that read as a missing card. */
.model-grid div {
  background: var(--panel);
  padding: 0.9rem 1.25rem;
  box-shadow: 1px 0 0 var(--rule), 0 1px 0 var(--rule);
}
.model-grid dt { overflow-wrap: anywhere; font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); }
.model-grid dd { margin: 0.25rem 0 0; font-size: 1.0625rem; font-weight: 700; }

.caveats { padding: 1.1rem 1.25rem; border-top: 1px solid var(--rule); background: var(--panel-sunk); }
.caveats ul { margin: 0.5rem 0 0; padding-left: 1.1rem; color: var(--ink-muted); font-size: 0.875rem; }
.caveats li { margin-block: 0.35rem; max-width: var(--measure); }

footer {
  padding-block: 2rem 3rem;
  color: var(--ink-faint);
  font-size: 0.8125rem;
  border-top: 1px solid var(--rule);
  margin-top: 3rem;
  text-align: center;
}
footer a { color: var(--ink); }

/* ---------- tooltip ----------------------------------------------- */

#tooltip {
  position: fixed;
  z-index: 80;
  pointer-events: none;
  background: var(--ink);
  color: var(--paper);
  padding: 0.45rem 0.65rem;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  line-height: 1.35;
  box-shadow: 0 4px 16px rgb(0 0 0 / 0.25);
  opacity: 0;
  transition: opacity 0.1s var(--ease);
  max-width: 240px;
}

#tooltip[data-show="true"] { opacity: 1; }
#tooltip b { font-weight: 700; }
/* Secondary line; the tooltip is inverted, so dimmed rather than recoloured. */
#tooltip .tooltip__muted { opacity: 0.75; font-variant-numeric: tabular-nums; }

/* ---------- state ------------------------------------------------- */

.status {
  padding: 3rem 1.25rem;
  text-align: center;
  color: var(--ink-muted);
}

/* ---------- motion ------------------------------------------------ */

/* One orchestrated load: the grid settles column by column, left to right,
   the way a season resolves from the top of the table down. */
@keyframes settle {
  from { opacity: 0; transform: translateY(4px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

.grid-animate .cell {
  animation: settle 0.34s var(--ease) both;
  animation-delay: calc(var(--col) * 24ms);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
  }
  .cell:hover { transform: none; }
}

/* ---------- phone navigation -------------------------------------- */

/* Eight views in a strip that showed three of them was the worst part of the
   phone layout: the rest had to be discovered by swiping a control that gave
   no sign it could scroll. Under 760px they move to a fixed bar in the thumb
   zone, four of them plus a sheet holding the rest. The buttons carry the same
   data-view attribute as the top strip, so nothing in the JS has to know which
   control was tapped. */

.mobilebar { display: none; }

/* Touch ripple for interactive elements on mobile */
@media (max-width: 760px) {
  .touch-ripple { position: relative; overflow: hidden; }
  .touch-ripple::after { content: ''; position: absolute; inset: 0; background: currentColor; opacity: 0; border-radius: inherit; pointer-events: none; }
  .touch-ripple:active::after { animation: ripple 0.3s var(--ease); opacity: 0.1; }
  @keyframes ripple { 0% { transform: scale(0.5); opacity: 0.15; } 100% { transform: scale(2.5); opacity: 0; } }
}
.sheet { display: none; }

@media (max-width: 760px) {
  .mobilebar {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 40;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: color-mix(in srgb, var(--panel) 94%, transparent);
    backdrop-filter: blur(12px);
    border-top: 1px solid var(--rule);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .mobilebar__item {
    appearance: none;
    border: 0;
    background: none;
    color: var(--ink-faint);
    font: inherit;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    min-height: 52px;
    padding: 0.4rem 0.2rem;
    cursor: pointer;
  }

  .mobilebar__icon { width: 17px; height: 17px; }

  .mobilebar__item[aria-pressed="true"] { color: var(--outcome-good); }

  /* The active tab gets a soft pill behind its icon, as native tab bars do. */
  .mobilebar__item[aria-pressed="true"]::before {
    content: "";
    position: absolute;
    top: 0.3rem;
    width: 3.25rem;
    height: 1.6rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--outcome-good) 16%, transparent);
    z-index: -1;
  }

  .mobilebar__item { isolation: isolate; transition: color 0.15s var(--ease); }

  .mobilebar__item { position: relative; }

  body { padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px)); }

  .masthead__views { display: none; }

  .sheet { display: block; position: fixed; inset: 0; z-index: 50; }
  .sheet[hidden] { display: none; }

  .sheet__scrim {
    position: absolute;
    inset: 0;
    background: rgb(0 0 0 / 0.45);
  }

  .sheet__panel {
    position: absolute;
    inset: auto 0 0 0;
    background: var(--panel);
    border-top: 1px solid var(--rule);
    border-radius: 14px 14px 0 0;
    padding: 0.5rem 0.75rem calc(0.75rem + 52px + env(safe-area-inset-bottom, 0px));
    display: grid;
    gap: 2px;
    animation: sheet-up 0.18s var(--ease);
  }

  .sheet__grip {
    width: 2.25rem;
    height: 4px;
    border-radius: 2px;
    background: var(--rule-strong);
    margin: 0.25rem auto 0.6rem;
  }

  .sheet__item {
    appearance: none;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 600;
    text-align: left;
    min-height: 48px;
    padding: 0 0.75rem;
    border-radius: var(--radius);
    cursor: pointer;
  }

  .sheet__item[aria-pressed="true"] { color: var(--outcome-good); background: var(--panel-sunk); }

  .sheet__divider {
    height: 1px;
    background: var(--rule);
    margin: 0.4rem 0.75rem;
  }

  .sheet__setting {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 48px;
    padding: 0 0.75rem;
  }

  .sheet__setting-label {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ink);
  }

  .sheet__setting .switch { padding: 2px; }
  .sheet__setting .switch button { padding: 0.3rem 0.65rem; font-size: 0.8125rem; }

  /* Sheet swipe-to-dismiss. Pausing (never cancelling) the open animation
     keeps a class toggle on any touch from restarting it. */
  .sheet__panel.is-dragging {
    animation-play-state: paused;
    transition: transform 0.05s linear, opacity 0.05s linear;
  }
}

@keyframes sheet-up {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sheet__panel { animation: none; }
}

.sheet__panel.is-dismissed {
  transform: translateY(100%);
  opacity: 0;
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}

/* ---------- touch ergonomics -------------------------------------- */

/* Keyed to the input device first -- a tablet with a finger needs the room
   whatever its width -- and to narrow screens as well, since a viewport this
   small is a phone in all but the rarest case. */
@media (pointer: coarse), (max-width: 760px) {
  .switch button { min-height: 44px; padding-inline: 1rem; }
  .season-select { min-height: 44px; }
  .standings .sort-btn { min-height: 44px; }
  .timeline__now { min-height: 44px; }
  .table-control-btn { min-height: 44px; padding-inline: 1rem; }
  .played-nav__btn { min-height: 44px; padding-inline: 1.25rem; }
  .compare__option { min-height: 44px; }
  .compare__swap-center { min-height: 44px; min-width: 44px; }
  .settings-btn { min-height: 44px; min-width: 44px; }
  .ladder__team { min-height: 44px; min-width: 44px; }
  .played-card__team-name { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; }
  .grid__team-name { min-height: 44px; min-width: 44px; }
  .sort-btn { min-width: 44px; }
  .grid-anim-speed button { min-height: 44px; min-width: 44px; padding: 0.5rem 0.75rem; }

  /* A 47-step slider is about 7px per matchday; a bigger thumb and the step
     buttons beside it make single matchdays reachable. Scoped through
     .timeline .timeline__control so these outrank the base slider rules
     further down the file rather than tying with them on source order. */
  .timeline .timeline__control input[type="range"] { height: 2.75rem; }
  .timeline .timeline__control input[type="range"]::-webkit-slider-thumb { width: 28px; height: 28px; margin-top: -11px; }
  .timeline .timeline__control input[type="range"]::-moz-range-thumb { width: 28px; height: 28px; }

  /* The default blue flash on tap reads as a rendering fault on a dark panel. */
  * { -webkit-tap-highlight-color: transparent; }
}

/* Wordmark hit-area expansion: grow element's own rect downward to ~44px,
   layout-neutral via padding + negative margin (masthead stays 60px). */
@media (pointer: coarse), (max-width: 760px) {
  .wordmark {
    padding-block-end: 24px;
    margin-block-end: -24px;
  }
}

/* ---------- the step buttons beside the rewind slider -------------- */

.timeline__step { display: none; }

@media (pointer: coarse), (max-width: 760px) {
  .timeline__control { display: flex; align-items: center; gap: 0.5rem; }
  .timeline__control input[type="range"] { flex: 1; }

  .timeline__step {
    display: grid;
    place-items: center;
    flex: none;
    width: 44px;
    height: 44px;
    appearance: none;
    background: var(--panel-sunk);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: 1.125rem;
    font-weight: 700;
    cursor: pointer;
  }

  .timeline__step:disabled { opacity: 0.4; cursor: default; }

  /* The scale would otherwise sit in the flex row and squeeze the slider;
     scoped so it outranks the base rule further down the file. */
  .timeline .timeline__scale { display: none; }
}

/* ---------- responsive -------------------------------------------- */

@media (max-width: 760px) {
  .hero__meta { gap: 0.4rem 1.25rem; }

  /* Bring the title closer to the top on mobile so "Eliteserien 2026"
     is visible immediately when scrolled to top, below the sticky masthead. */
  .hero { padding-top: clamp(0.5rem, 2vw, 1rem); }

  /* Input font size >= 16px to prevent iOS Safari zoom on focus */
  select, textarea, input:not([type="range"]) { font-size: 16px; }

  /* A phone has room for the story, not the ledger. The W/D/L/GF/GA tallies,
      xPts and the form chips go; position, club, played, GD, points, rating and
      the two odds stay. Tapping a row still opens the club's full history. */
  /* The 720px floor exists so the full desktop column set never crushes. With
      seven of those columns gone it is what was keeping the table off-screen. */
  table.standings { min-width: 0; font-size: 0.8125rem; }
  /* The ledger columns (W/D/L, GF/GA, form; xG/xGA/xGD) stay on the club's
     own page. Current keeps #, club, played, GD, points and rating;
     Prediction keeps #, club, xPts, fixtures and the two odds. */
  table.standings .col--extra { display: none; }
  /* Rating is the headline in Current; in Prediction the phone spends its
     width on the odds instead, which are that view's point. */
  #standings[data-view="prediction"] .sep { display: none; }
  table.standings .pos { width: 1.9rem; }
  .fixture-difficulty-pill { min-width: 34px; padding-inline: 4px; font-size: 0.6875rem; }
  .career-table { min-width: 0; }
  /* table.standings: the base cell rule outranks a bare .standings, which
     left this dead and every cell at 9.6px of side padding. */
  table.standings th, table.standings td { padding-inline: 0.3rem; }
  /* Chrome that carries no data goes before any column does. The sorted column
     is still marked by its ink, and aria-sort still announces the direction. */
  .standings .sort-btn { gap: 0.15rem; }
  .standings .sort-btn__caret { display: none; }
  .standings .pos { min-width: 0; }
  .standings .band-mark { margin-right: 0.25rem; }
  .standings .club-btn { gap: 0.35rem; }
  .standings .team-logo { width: 17px; height: 17px; }
  .standings .meter__value { min-width: 2rem; font-size: 0.75rem; }
  .standings th:first-child, .standings td:first-child { padding-left: 0.5rem; }
  .standings th:last-child, .standings td:last-child { padding-right: 0.85rem; }
  .standings .sort-btn__label { font-size: 0.6875rem; letter-spacing: 0.04em; }
  /* Swap in the short heading: "Relegation" is wider than any number under it. */
  .standings .sort-btn__label:has(+ .sort-btn__short) { display: none; }
  .standings .sort-btn__short { display: inline; font-size: 0.6875rem; letter-spacing: 0.04em; }
  /* One line per club. Left to wrap, "Bodø/Glimt" breaks at the slash, which
     drops the column's min-content width and stacks the name under the crest. */
  .standings .club-btn { white-space: nowrap; text-align: left; }
  /* The odds keep their number; the bar goes, since the percentage beside it
     already carries the value. */
  .meter__track { display: none; }
  .meter { gap: 0; }

  /* Left-aligned so the first view is the one you actually start on. */
  .masthead__views { justify-content: flex-start; }
  .timeline__note { display: none; }

  /* Team grid row: smaller cells on a phone */
  .team-grid-row__cell { height: 1.5rem; font-size: 0.5625rem; }
  .team-grid-row__pos { font-size: 0.5rem; }
  .team-summary__name { font-size: 1.25rem; }
  .team-summary__rating { font-size: 1.75rem; }

  .wordmark { margin-right: 0; white-space: nowrap; }
  .wordmark span { display: none; }

  /* How the model was built belongs in the Model Card, not above the table.
     Needs to outrank `.hero__meta div`, which sets these to flex. */
  .hero__meta .hero__meta-provenance { display: none; }

  /* The finish grid's explanation runs six lines on a phone -- more screen
     than the grid it introduces. Clamped to two, faded so there is visibly
     more, and expanded by tapping it. */
  .panel__head p {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    cursor: pointer;
    mask-image: linear-gradient(180deg, #000 55%, rgb(0 0 0 / 0.35) 100%);
  }

  .panel__head p.is-expanded {
    -webkit-line-clamp: unset;
    mask-image: none;
  }

  /* The rewind slider keeps its source place on a phone, under the hero's
     figures and above the view. It used to sit under the content and jump up
     once rewound, which moved it out from under the finger mid-drag. */
  /* As a flex column the sections' margins no longer collapse, so each gap
     would be both margins stacked (~48px of nothing). The gap replaces them. */
  #content { display: flex; flex-direction: column; gap: 1rem; }

  /* Pull-to-refresh indicator */
  .ptr-indicator {
    position: sticky;
    top: -60px;
    z-index: 10;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--ink-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    transform: translateY(-100%);
    transition: transform 0.2s var(--ease), opacity 0.2s var(--ease);
    opacity: 0;
    pointer-events: none;
  }
  .ptr-indicator.visible { opacity: 1; transform: translateY(0); }
  .ptr-indicator.pulling { color: var(--tier-1); }
  .ptr-indicator.loading { color: var(--tier-1); }
  .ptr-spinner {
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid var(--rule);
    border-top-color: var(--tier-1);
    border-radius: 50%;
    animation: ptr-spin 0.8s linear infinite;
  }
  .ptr-indicator.loading .ptr-spinner { animation: ptr-spin 0.6s linear infinite; }
  @keyframes ptr-spin { to { transform: rotate(360deg); } }

  /* Skeleton loading states */
  .skeleton { background: linear-gradient(90deg, var(--panel-sunk) 25%, var(--rule) 50%, var(--panel-sunk) 75%); background-size: 200% 100%; animation: shimmer 1.5s ease-in-out infinite; border-radius: var(--radius-sm); }
  @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
  .skeleton-text { height: 1rem; margin-bottom: 0.5rem; }
  .skeleton-text:last-child { width: 60%; }
  .skeleton-title { height: 1.5rem; width: 40%; margin-bottom: 0.75rem; }
  .skeleton-row { height: 2.5rem; }
  .skeleton-cell { height: 1.75rem; }
  .skeleton-grid-cell { height: 1.35rem; border-radius: 2px; }
  .skeleton-ladder-row { height: 2.25rem; border-radius: 0; border-bottom: 1px solid var(--rule); }
  .skeleton-fixture { height: 4rem; border-radius: var(--radius); margin-bottom: 0.5rem; }
  .skeleton-played-card { height: 3.5rem; border-radius: 0; border-bottom: 1px solid var(--rule); }

  /* Touch ripple effect for interactive elements */
  .touch-ripple { position: relative; overflow: hidden; }
  .touch-ripple::after { content: ''; position: absolute; inset: 0; background: currentColor; opacity: 0; border-radius: inherit; pointer-events: none; }
  .touch-ripple:active::after { animation: ripple 0.3s var(--ease); opacity: 0.1; }
  @keyframes ripple { 0% { transform: scale(0.5); opacity: 0.15; } 100% { transform: scale(2.5); opacity: 0; } }

  /* Improved momentum scrolling for tables */
  .scroller { -webkit-overflow-scrolling: touch; scroll-behavior: auto; }
  .scroller:has(> table) { scroll-snap-type: x mandatory; }
  .scroller > table { scroll-snap-align: start; }
  #content > section { margin-block: 0; }
  .hero { padding-bottom: 0.25rem; }

  /* The divider row spans the whole scrolling table, so a centred label sits
     off-screen. Pin it to the left with a short lead-in line. */
  table.standings .zone-divider__wrap { justify-content: flex-start; padding-left: 0.5rem; }
  table.standings .zone-divider__wrap::before { flex: 0 0 0.75rem; }

  /* A tighter masthead on small screens. */
  .masthead__inner { gap: 0.7rem 1rem; min-height: 0; padding-block: 0.7rem; }
  .wordmark { font-size: 0.95rem; }
  .masthead__views .switch button { padding: 0.3rem 0.5rem; font-size: 0.75rem; }

  /* Let the rewind button fall onto its own line if the title is long. */
  .timeline__head { flex-wrap: wrap; }
}

@media (max-width: 480px) {
  /* A phone has no width to spare on margins: the page gutter costs 32px of a
     375px screen, which is most of a table column. */
  :root { --gutter: 0.75rem; }

  /* Less generous panel padding so the wide tables and controls get the
     maximum usable width on small phones. */
  .panel__head, .timeline { padding: 0.9rem 1rem; }

  .standings .club-btn--crest .team-logo { width: 16px; height: 16px; margin-right: 0.3rem; }
  .standings .band-mark { margin-right: 0.2rem; }
  .grid-wrap { padding: 1rem; }
  .legend { padding: 0.8rem 1rem; }
  .fixture { padding: 0.65rem 1rem; }

  /* Two model-card columns; the long Norwegian labels need the padding back. */
  .panel .model-grid div { padding: 0.8rem 0.9rem; }
  .model-grid { grid-template-columns: 1fr; }

  /* Tighter wordmark on small phones. */
  .wordmark { font-size: 0.8rem; letter-spacing: 0; }

  /* Grid animation controls: ensure they fit */
  .grid-anim-bar { padding: 0.5rem 1rem; gap: 0.5rem; }
  .grid-anim-bar__when { min-width: 0; font-size: 0.75rem; }
  .grid-anim-speed button { min-width: 2.5rem; padding: 0.2rem 0.4rem; font-size: 0.6875rem; }
}

/* ---- 360px and below: extreme narrow ---- */
@media (max-width: 360px) {
  .grid-wrap { padding: 0.5rem 0.25rem; }
  .cell { font-size: 0.5rem; letter-spacing: -0.05em; }
  .ladder__track--list { --scale-w: 26%; }
  .panel__head { padding: 0.75rem 0.875rem; }
  .hero { padding-inline: 0.75rem; }

  /* Hide more table columns on very narrow screens */
  table.standings .sep { display: none; }
  .standings .meter__value { min-width: 1.5rem; font-size: 0.6875rem; }

  /* Ladder row height bump for touch */
  .ladder__track--list .ladder__team { height: 2.75rem; }
  .ladder__track--list .ladder__rank { font-size: 0.6875rem; }
  .ladder__track--list .ladder__name { font-size: 0.8125rem; }
  .ladder__track--list .ladder__rating { font-size: 0.75rem; }
  .ladder__track--list .ladder__team img { width: 1.125rem; height: 1.125rem; }

  /* Team focus tighter */
  .team-summary__name { font-size: 1.125rem; }
  .team-summary__rating { font-size: 2rem; }
  .team-stats__value { font-size: 1.25rem; }
  .team-stats__label { font-size: 0.625rem; }
  .team-stats__tile { padding: 0.5rem 0.35rem; }

  /* Compare clubs tighter */
  .compare__team-name { font-size: 0.875rem; }
  .compare__team-rating { font-size: 1.1rem; }
  .compare__scoreline { font-size: 0.75rem; padding: 0.2rem 0.5rem; min-width: 3.5rem; }
}

/* ---------- season selector --------------------------------------- */

.season-select,
.compare__select {
  appearance: none;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--panel-sunk);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.36rem 1.9rem 0.36rem 0.7rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.9rem center, right 0.6rem center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* ---------- settings button + popover menus ------------------------ */

.settings-btn {
  appearance: none;
  border: 0;
  background: none;
  color: var(--ink-muted);
  padding: 0.35rem;
  border-radius: var(--radius);
  cursor: pointer;
  display: grid;
  place-items: center;
  line-height: 0;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.settings-btn:hover { color: var(--ink); background: var(--panel-sunk); }

.popover-menu {
  position: absolute;
  z-index: 40;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.35rem;
}
.popover-menu[hidden] { display: none; }
.popover-menu--scroll { max-height: 50vh; overflow-y: auto; }
#settings-menu { min-width: 200px; }

.popover-menu__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.4rem 0.5rem;
}
.popover-menu__label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
}
.popover-menu__item .switch { padding: 2px; }
.popover-menu__item .switch button { padding: 0.25rem 0.55rem; font-size: 0.75rem; }

.popover-menu__btn {
  appearance: none;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  text-align: left;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  width: 100%;
}
.popover-menu__btn:hover { background: var(--panel-sunk); }
.popover-menu__btn[aria-pressed="true"] { color: var(--outcome-good); }

/* ---------- team focus view ---------------------------------------- */

.team-section { padding: 1.25rem; border-top: 1px solid var(--rule); }
.team-section:first-child { border-top: 0; padding-top: 0.75rem; }
.team-section > .label { margin-bottom: 0.6rem; }
.team-section__hint { font-size: 0.85rem; color: var(--ink-muted); margin: 0 0 0.5rem; }
.team-shape--loading { height: 280px; display: flex; align-items: center; justify-content: center; color: var(--ink-muted); }

.team-section__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.team-section__header > .label { margin-bottom: 0; }

/* Back: a quiet tinted pill with a chevron that leans the way it goes. No
   lift or shadow on hover -- a navigation control, not a call to action. */
.team-back {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 2.5rem;
  padding: 0 1rem 0 0.65rem;
  margin-bottom: 0.5rem;
  border: 0;
  border-radius: 999px;
  background: color-mix(in oklab, var(--ink) 6%, var(--panel));
  color: var(--ink);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s var(--ease);
}
.team-back svg { flex: none; transition: transform 0.15s var(--ease); }
.team-back:hover { background: color-mix(in oklab, var(--ink) 11%, var(--panel)); }
.team-back:hover svg { transform: translateX(-3px); }
.team-back:active { background: color-mix(in oklab, var(--ink) 15%, var(--panel)); }
@media (prefers-reduced-motion: reduce) {
  .team-back svg { transition: none; }
  .team-back:hover svg { transform: none; }
}

#team-content { padding: 0.5rem 1.25rem; }

.team-summary {
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.team-summary__header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}



.team-logo--large {
  width: 48px;
  height: 48px;
  border-radius: 6px;
  flex: none;
}

.team-summary__name-block {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1;
}

.team-summary__name {
  font-size: 1.5rem;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.team-summary__rating-block {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex: none;
  margin-left: auto;
}

.team-summary__rating-line {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.team-summary__rating {
  font-family: var(--display);
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.team-summary__rating-pos {
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

.team-summary__trend {
  font-size: 2.5rem;
  line-height: 1;
  display: flex;
  align-items: center;
}

.team-summary__trend--strong-rise { color: var(--outcome-good); }
.team-summary__trend--rise { color: var(--outcome-good); }
.team-summary__trend--steady { color: var(--ink-faint); }
.team-summary__trend--fall { color: var(--outcome-bad); }
.team-summary__trend--strong-fall { color: var(--outcome-bad); }

/* xG form under the rating: a labelled line, so it never reads as a second
   verdict on the rating. Only the icon takes the trend colour. */
.team-summary__form {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.3rem;
  font-size: 0.8125rem;
  color: var(--ink-muted);
  cursor: help;
}
.team-summary__form-key {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.team-summary__form-icon { display: inline-flex; font-size: 1rem; }

/* Team view fixtures and results: one compact row per match from the club's
   side -- date, H/A, opponent, then odds or result. */
.team-matches { display: flex; flex-direction: column; }
.team-match {
  display: grid;
  grid-template-columns: 6.25rem 1.5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.25rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.9375rem;
}
.team-match:last-child { border-bottom: 0; }
.team-match__date { font-size: 0.8125rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.team-match__venue {
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.5rem;
  text-align: center;
  color: var(--ink-muted);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
}
.team-match .team-match__opponent { display: flex; flex-direction: row; align-items: center; gap: 0.5rem; min-width: 0; }
.team-match .team-match__opponent .team-logo { width: 20px; height: 20px; flex: none; }
.team-match__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.team-match__name:hover { text-decoration: underline; }
.team-match__result { display: inline-flex; align-items: center; gap: 0.6rem; font-variant-numeric: tabular-nums; }
.team-match__score { font-family: var(--display); font-weight: 800; min-width: 2.2rem; }
.team-match__xg { font-size: 0.75rem; color: var(--ink-muted); min-width: 4.5rem; }
.team-match__delta { font-size: 0.8125rem; font-weight: 700; min-width: 2rem; text-align: right; color: var(--ink-faint); }
.team-match__delta.up { color: var(--outcome-good); }
.team-match__delta.down { color: var(--outcome-bad); }
.team-match__odds { width: 13rem; height: 1.25rem; font-size: 0.6875rem; }
.team-match__legend { padding: 0; border: 0; background: none; font-size: 0.75rem; }
@media (max-width: 560px) {
  .team-match { grid-template-columns: 1.5rem minmax(0, 1fr) auto; gap: 0.5rem 0.6rem; }
  .team-match__date { grid-column: 1 / -1; margin-bottom: -0.35rem; font-size: 0.75rem; }
  .team-match__odds { width: 8.5rem; }
  .team-match__xg { display: none; }
  .team-section__header:has(.team-match__legend) { flex-wrap: wrap; row-gap: 0.4rem; }
  .team-match__legend { flex-basis: 100%; }
}

/* Matches: a part-played week puts a heading over its results and fixtures. */
.matches__group { display: block; padding: 0.9rem 1.25rem 0.25rem; }

/* Outlook: the model's forecast as tiles under the table tiles, with the
   pre-season call as one line beneath. */
.team-outlook { margin-top: 0.75rem; }
.team-outlook > .label { display: block; margin-bottom: 0.45rem; }
.team-outlook__note {
  margin: 0.45rem 0 0;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

/* Rating trend arrow in the standings table — same style as the team view */
.rating-trend {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.3rem;
  font-size: 1.15rem;
  line-height: 1;
}
.rating-trend--strong-rise { color: var(--outcome-good); }
.rating-trend--rise { color: var(--outcome-good); }
.rating-trend--steady { color: var(--ink-faint); }
.rating-trend--fall { color: var(--outcome-bad); }
.rating-trend--strong-fall { color: var(--outcome-bad); }
.rating-trend--top { color: var(--band-champion); }
/* Gold on white is 1.8:1; an icon needs 3:1 (WCAG 1.4.11). */
:root:not([data-resolved-theme="dark"]) .rating-trend--top { color: color-mix(in srgb, var(--band-champion) 60%, var(--ink)); }


/* Stat tiles: equal columns split by hairlines, value over label. Four
   across for the table strip, two for the xG strip, on any width. */
.team-stats {
  display: grid;
  grid-auto-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--panel-sunk);
  overflow: hidden;
}
.team-stats__tile {
  display: flex;
  flex-direction: column-reverse; /* dt first in the markup, value on top */
  justify-content: flex-end;
  align-items: center;
  gap: 0.2rem;
  padding: 0.75rem 0.5rem;
  text-align: center;
  min-width: 0;
}
.team-stats__tile + .team-stats__tile { border-left: 1px solid var(--rule); }
.team-stats__label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.team-stats__value {
  margin: 0;
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
/* xG tiles read value, label, bar, note: order puts the bar and note after
   the label while the value stays on top. */
.team-stats--xg .team-stats__tile { flex-direction: column; align-items: stretch; }
.team-stats--xg .team-stats__value { order: -1; text-align: center; }
.team-stats__bar {
  position: relative;
  height: 6px;
  margin: 0.35rem 0.5rem 0;
  border-radius: 999px;
  background: var(--rule);
}
.team-stats__bar::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 var(--from);
  width: var(--width);
  border-radius: inherit;
  background: var(--outcome-good);
}
.team-stats__bar--bad::before { background: var(--outcome-bad); }
/* The division average: the centre line the bar grows out from. */
.team-stats__bar::after {
  content: "";
  position: absolute;
  left: calc(50% - 1px);
  top: -3px;
  bottom: -3px;
  width: 2px;
  background: var(--ink);
}
.team-stats__note {
  margin: 0.2rem 0 0;
  font-size: 0.6875rem;
  color: var(--ink-muted);
  text-align: center;
}

/* High-stakes lines in the team summary: one row per entry, the band carried
   by a dot in its palette colour and the consequence in words. Restrained by
   design — the numbers live in the sentence, not in a dashboard. */
.team-stakes > .label { display: block; margin-bottom: 0.45rem; }
.team-stakes__list + .label { margin-top: 0.85rem; }
.team-stakes__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.team-stakes__row {
  display: flex;
  gap: 0.55rem;
  align-items: flex-start;
  font-size: 0.875rem;
  line-height: 1.45;
}
.team-stakes__dot {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  flex: none;
  margin-top: 0.32rem;
}
.team-stakes__main { font-weight: 600; color: var(--ink); }
.team-stakes__sub { color: var(--ink-muted); }
.team-stakes__legs {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

@media (max-width: 760px) {
  .stake-flag { font-size: 0.75rem; padding: 0.25rem 0.6rem; }
  .team-stakes__row { font-size: 0.8125rem; }
}

/* Rating chart stats (peak/worst) beneath the chart */
.team-chart-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--ink-muted);
}

.team-chart-stat {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.team-chart-stat b { color: var(--ink); font-weight: 700; }

/* Finish grid row: one team's 16-position probability bar */
.team-grid-row {
  display: flex;
  gap: 3px;
  width: 100%;
}

.team-grid-row__cell-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  flex: 1;
  min-width: 0;
}

.team-grid-row__pos {
  font-size: 0.625rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.team-grid-row__cell {
  width: 100%;
  height: 2rem;
  display: grid;
  place-items: center;
  border-radius: 3px;
  font-size: 0.6875rem;
  color: var(--cell-ink);
  font-variant-numeric: tabular-nums;
  cursor: default;
  transition: transform 0.12s var(--ease);
}

.team-grid-row__cell--empty { color: transparent; }

.team-grid-row__cell.cell--invert { color: var(--cell-ink-invert); }

.team-grid-row__cell:hover {
  transform: scale(1.12);
  box-shadow: 0 0 0 2px var(--panel), 0 0 0 3px var(--ink);
  position: relative;
  z-index: 2;
}

/* ---------- season-by-season (team view) ---------------------------- */

/* Unified compact season list: one single column of rows under the chart,
   which is also the picker. */
.seasons-list-compact {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.4rem;
  padding: 0.25rem 0.75rem 0.75rem;
}

.season-row-compact {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.6rem 0.85rem;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease), transform 0.1s var(--ease), box-shadow 0.12s var(--ease);
  position: relative;
  width: 100%;
  min-width: 0;
  text-align: left;
}
.season-row-compact:hover,
.season-row-compact:focus-visible {
  background: var(--panel-sunk);
  border-color: var(--rule-strong);
  box-shadow: var(--shadow);
}
.season-row-compact:focus-visible {
  outline: 2px solid var(--tier-1);
  outline-offset: 2px;
}
.season-row-compact:active { transform: scale(0.99); }

/* Active state - currently displayed season shape */
.season-row-compact.is-active {
  background: color-mix(in srgb, var(--tier-1) 8%, var(--panel));
  border-color: var(--tier-1);
  box-shadow: 0 0 0 1px var(--tier-1);
}
.season-row-compact.is-active:hover {
  background: color-mix(in srgb, var(--tier-1) 12%, var(--panel));
}

.season-row-compact__season {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 7.5rem;
  flex-shrink: 0;
}
.season-row-compact__year {
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
/* Division pill: full-round, type big enough to read at a glance. */
.season-row-compact__badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.5rem;
  height: 1.375rem;
  padding: 0 0.45rem;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 999px;
  color: var(--panel);
}
.season-row-compact__badge--tier1 { background: var(--tier-1); }
.season-row-compact__badge--tier2 { background: var(--tier-2); }

.season-row-compact__main {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: 1;
  min-width: 0;
  padding-left: 0.5rem;
}
.season-row-compact__pos {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  width: 3rem;
  text-align: right;
}

.season-row-compact__rating {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  min-width: 7rem;
}
.season-row-compact__rating-start {
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  text-align: right;
  min-width: 3rem;
}
.season-row-compact__change {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 5.5rem;
}
.season-row-compact__change-val {
  font-family: var(--display);
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 2.2rem;
  text-align: right;
}
.season-row-compact__change-val.up { color: var(--outcome-good); }
.season-row-compact__change-val.down { color: var(--outcome-bad); }
.season-row-compact__change-bar {
  flex: 1;
  height: 4px;
  background: var(--rule);
  border-radius: 999px;
  overflow: hidden;
}
.season-row-compact__change-fill {
  height: 100%;
  border-radius: 999px;
  transition: width 0.3s var(--ease);
}
.season-row-compact__change-fill--up { background: var(--outcome-good); }
.season-row-compact__change-fill--down { background: var(--outcome-bad); }

/* Column names above the season rows: the rows' cells and spacing, label
   type, no chrome. Its own class, so nothing that walks the rows meets it. */
.season-row-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 calc(0.85rem + 1px) 0.1rem;
}
.team-seasons .season-row-head * {
  font: 600 0.6875rem/1.2 var(--body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.season-row-head .season-row-compact__change { justify-content: center; }
.season-row-compact__live {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--outcome-good);
}
/* On a phone the word does not fit beside the place; a dot carries it. */
@media (max-width: 760px) {
  .season-row-compact__live {
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: var(--outcome-good);
    font-size: 0;
    flex: none;
  }
}
.season-row-compact__rating-end {
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  min-width: 3rem;
  text-align: right;
}

/* Pagination in team section */
.team-section .played-nav { padding-inline: 1.25rem; }
@media (max-width: 760px) {
  .team-section .played-nav { padding-inline: 0; }
}
/* ...but under the picker it aligns with the rows and drops the trailing
   rule: the section already has an edge. */
.team-seasons .played-nav {
  padding-inline: 0;
  border-bottom: 0;
  margin-top: 0.35rem;
}

/* Rating chart used in team view */
.chart .career-line { fill: none; stroke: var(--seq-5); stroke-width: 2; }
.chart .career-area { fill: var(--seq-5); opacity: 0.12; }
.chart .season-split { stroke: var(--rule); stroke-width: 1; }
.chart .season-label { fill: var(--ink-muted); font-size: 9px; }
.chart .career-dot { fill: var(--seq-5); stroke: var(--panel); stroke-width: 2; }

/* Season shape: the place numerals sit on band colours of every strength, so
   they carry a panel halo (stroke painted under the fill) instead of flipping
   ink per band. */
.chart .band-pos {
  font-size: 9.5px;
  font-weight: 700;
  fill: var(--ink);
  dominant-baseline: middle;
  paint-order: stroke;
  stroke: var(--panel);
  stroke-width: 2.5px;
  stroke-linejoin: round;
}
.shape-legend { padding: 0.6rem 0 1rem; border: 0; background: none; font-size: 0.75rem; }

/* Responsive adjustments for compact list */
@media (max-width: 760px) {
  .seasons-list-compact { padding: 0.25rem 0.5rem 0.5rem; }
  .season-row-compact { padding: 0.5rem 0.6rem; gap: 0.75rem; }
  .season-row-head { padding-inline: calc(0.6rem + 1px); gap: 0.75rem; }
  .season-row-compact__season { width: 6.5rem; gap: 0.35rem; }
  .season-row-compact__year { font-size: 0.875rem; }
  .season-row-compact__main { gap: 0.5rem; }
  .season-row-compact__pos { font-size: 0.9375rem; min-width: 2rem; }
  .season-row-compact__rating { min-width: 6rem; gap: 0.35rem; }
  .season-row-compact__rating-start { font-size: 0.75rem; min-width: 2.5rem; }
  .season-row-compact__change { min-width: 5rem; }
  .season-row-compact__change-val { font-size: 0.8125rem; min-width: 2rem; }
  .season-row-compact__rating-end { font-size: 0.75rem; min-width: 2.5rem; }
}

@media (max-width: 480px) {
  .season-row-compact { padding: 0.45rem 0.5rem; gap: 0.5rem; }
  .season-row-head { padding-inline: calc(0.5rem + 1px); gap: 0.5rem; }
  .season-row-compact__season { width: 6rem; }
  .season-row-compact__year { font-size: 0.8125rem; }
  .season-row-compact__main { gap: 0.35rem; }
  .season-row-compact__pos { font-size: 0.875rem; min-width: 1.75rem; }
  .season-row-compact__rating { min-width: 5.5rem; }
  .season-row-compact__rating-start { min-width: 2.25rem; }
  .season-row-compact__change { min-width: 4.5rem; }
  .season-row-compact__change-val { min-width: 1.75rem; }
  .season-row-compact__rating-end { min-width: 2.25rem; }
}

#standings tbody tr { cursor: pointer; }

.club-btn {
  appearance: none;
  border: 0;
  margin: 0;
  padding: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: inherit;
  cursor: pointer;
  text-align: left;
  min-height: 44px;   /* WCAG 2.5.8 target minimum */
}
.club-btn:hover { text-decoration: underline; }

.club-btn--crest .team-logo {
  width: 18px;
  height: 18px;
  margin-right: 0.45rem;
  vertical-align: -0.3em;
}

/* ---------- season rewind timeline -------------------------------- */

.timeline-section { margin-block: clamp(1.5rem, 4vw, 2.5rem) 0; }
.timeline { padding: 0.85rem 1.25rem 0.75rem; }

.timeline__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.4rem;
}

/* The eyebrow and the state read as one line rather than a stacked block. */
.timeline__head > div:first-child {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.timeline__head p {
  margin: 0.25rem 0 0;
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.timeline__now {
  appearance: none;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--panel-sunk);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  padding: 0.35rem 0.8rem;
  cursor: pointer;
  flex: none;
}

.timeline__now:hover { border-color: var(--ink-faint); }

.timeline__control { position: relative; }

.timeline input[type="range"] {
  appearance: none;
  width: 100%;
  height: 1.5rem;
  background: none;
  cursor: pointer;
  margin: 0;
}

/* The rail is the season; the thumb is where you are standing in it. */
.timeline input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--rule);
}

.timeline input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--rule);
}

.timeline input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--tier-1);
  border: 3px solid var(--panel);
  box-shadow: 0 0 0 1px var(--rule-strong);
}

.timeline input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--tier-1);
  border: 3px solid var(--panel);
  box-shadow: 0 0 0 1px var(--rule-strong);
}

.timeline input[type="range"]:focus-visible { outline: 2px solid var(--tier-1); outline-offset: 4px; }

.timeline__scale {
  display: flex;
  justify-content: space-between;
  margin-top: 0.1rem;
  font-size: 0.6875rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.timeline__note {
  margin: 0.85rem 0 0;
  font-size: 0.8125rem;
  color: var(--ink-muted);
  max-width: var(--measure);
}

/* Everything downstream dims while a rewound view is being fetched, so it is
   obvious the numbers on screen are about to change. */
#content.is-rewinding .panel:not(.timeline) { opacity: 0.55; transition: opacity 0.15s var(--ease); }
#content.is-rewinding { cursor: progress; }

.timeline.is-past { border-color: var(--tier-1); }
.timeline.is-past .timeline__head p { color: var(--tier-1); }

/* Team focus: Season Shape responsiveness */
@media (max-width: 480px) {
  .team-section .chart .tick { font-size: 9px; }
  .team-section .chart .axis-title { font-size: 9px; }
  .team-section .chart .crosshair { stroke-width: 1.5; }

  /* Beside a 2.5rem rating the club name had ~30px left and read "Vi…". The
     rating drops to its own line so the name gets the width. */
  .team-summary__header { flex-wrap: wrap; }
  .team-summary__rating-block { flex-basis: 100%; margin-left: 0; align-items: flex-start; }

  /* #team-content and each .team-section both padded 1.25rem: 40px a side of
     a 360px screen before any content. One layer of gutter is enough. */
  #team-content { padding: 0.5rem 0.25rem; }
  .team-section { padding: 1rem 0.75rem; }
  .team-grid-row__cell { font-size: 0.5rem; letter-spacing: -0.04em; }
}

/* Prevent horizontal overflow on very narrow screens */
@media (max-width: 360px) {
  .grid-wrap { padding: 0.5rem 0.25rem; }
  .cell { font-size: 0.5rem; letter-spacing: -0.05em; }
  .ladder__track--list { --scale-w: 26%; }
  .panel__head { padding: 0.75rem 0.875rem; }
  .hero { padding-inline: 0.75rem; }

  /* Hide more table columns on very narrow screens */
  table.standings .sep { display: none; }
  .standings .meter__value { min-width: 1.5rem; font-size: 0.6875rem; }

  /* Ladder row height bump for touch */
  .ladder__track--list .ladder__team { height: 2.75rem; }
  .ladder__track--list .ladder__rank { font-size: 0.6875rem; }
  .ladder__track--list .ladder__name { font-size: 0.8125rem; }
  .ladder__track--list .ladder__rating { font-size: 0.75rem; }
  .ladder__track--list .ladder__team img { width: 1.125rem; height: 1.125rem; }

  /* Team focus tighter */
  .team-summary__name { font-size: 1.125rem; }
  .team-summary__rating { font-size: 2rem; }
  .team-stats__value { font-size: 1.25rem; }
  .team-stats__label { font-size: 0.625rem; }
  .team-stats__tile { padding: 0.5rem 0.35rem; }

  /* Compare clubs tighter */
  .compare__team-name { font-size: 0.875rem; }
  .compare__team-rating { font-size: 1.1rem; }
  .compare__scoreline { font-size: 0.75rem; padding: 0.2rem 0.5rem; min-width: 3.5rem; }
}

/* ----- Team Focus mobile refinements ----- */
@media (max-width: 760px) {
  /* Team summary: stack header elements */
  .team-summary__header { flex-wrap: wrap; gap: 0.5rem; }
  .team-summary__rating-block { flex-basis: 100%; margin-left: 0; align-items: flex-start; }
  .team-summary__rating-line { justify-content: flex-start; }

  /* Team stats grid: 2 columns on mobile */
  .team-stats { grid-template-columns: 1fr 1fr; }
  .team-stats--xg { grid-template-columns: 1fr 1fr; }

  /* Team grid row: smaller cells */
  .team-grid-row__cell { height: 1.5rem; font-size: 0.5625rem; }
  .team-grid-row__pos { font-size: 0.5rem; }

  /* Season shape chart container */
  .team-shape-container { min-height: 280px; }
  .team-section .chart { max-width: 100%; }

  /* Season by season: tighter rows */
  .season-row-compact { padding: 0.5rem 0.6rem; gap: 0.75rem; }
  .season-row-head { padding-inline: calc(0.6rem + 1px); gap: 0.75rem; }
  .season-row-compact__season { width: 6.5rem; gap: 0.35rem; }
  .season-row-compact__year { font-size: 0.875rem; }
  .season-row-compact__main { gap: 0.5rem; }
  .season-row-compact__pos { font-size: 0.9375rem; min-width: 2rem; }
  .season-row-compact__rating { min-width: 6rem; gap: 0.35rem; }
  .season-row-compact__rating-start { font-size: 0.75rem; min-width: 2.5rem; }
  .season-row-compact__change { min-width: 5rem; }
  .season-row-compact__change-val { font-size: 0.8125rem; min-width: 2rem; }
  .season-row-compact__rating-end { font-size: 0.75rem; min-width: 2.5rem; }

  /* Pagination in team section */
  .team-section .played-nav { padding-inline: 0; }

  /* Rating chart tick sizes */
  .team-section .chart .tick { font-size: 9px; }
  .team-section .chart .axis-title { font-size: 9px; }

}

@media (max-width: 480px) {
  /* Team content and sections: single gutter layer */
  #team-content { padding: 0.5rem 0.25rem; }
  .team-section { padding: 1rem 0.75rem; }
  .team-grid-row__cell { font-size: 0.5rem; letter-spacing: -0.04em; }
  .team-summary__name { font-size: 1.25rem; }
  .team-summary__rating { font-size: 2rem; }
  .team-stats__value { font-size: 1.25rem; }
  .team-stats__label { font-size: 0.625rem; }
  .team-stats__tile { padding: 0.5rem 0.35rem; }

  /* Season by season: even tighter */
  .season-row-compact { padding: 0.45rem 0.5rem; gap: 0.5rem; }
  .season-row-head { padding-inline: calc(0.5rem + 1px); gap: 0.5rem; }
  .season-row-compact__season { width: 6rem; }
  .season-row-compact__year { font-size: 0.8125rem; }
  .season-row-compact__main { gap: 0.35rem; }
  .season-row-compact__pos { font-size: 0.875rem; min-width: 1.75rem; }
  .season-row-compact__rating { min-width: 5.5rem; }
  .season-row-compact__rating-start { min-width: 2.25rem; }
  .season-row-compact__change { min-width: 4.5rem; }
  .season-row-compact__change-val { min-width: 1.75rem; }
  .season-row-compact__rating-end { min-width: 2.25rem; }

  /* Fixtures/results pagination buttons */
  .team-section .played-nav__btn { padding: 0.35rem 0.75rem; font-size: 0.75rem; }
}

/* ----- Next Up / Fixtures mobile refinements ----- */
@media (max-width: 760px) {
  /* Fixture cards stack properly */
  .played-card { padding: 0.75rem 1rem; }
  .played-card__matchup { gap: 0.5rem; }
  .played-card__side { gap: 0.4rem; }

  /* Tighter gaps: the odds bar keeps its row layout at every width */
  .fixture__odds-col { gap: 0.25rem; }
  .fixture__lines { gap: 0.25rem; }
  .fixture__line { font-size: 0.625rem; padding: 0.05rem 0.25rem; }

  /* Week pagination: larger touch targets */
  .fixtures .played-nav__btn { min-height: 44px; min-width: 44px; padding: 0.4rem 0.75rem; }
  .fixtures .played-nav__label { min-width: 0; font-size: 0.875rem; }
}

@media (max-width: 480px) {
  .played-card { padding: 0.5rem 0.75rem; }
  .played-card__matchup { gap: 0.375rem; }
  .played-card__side { gap: 0.3rem; }
  .played-card__rating { flex-direction: column; align-items: center; gap: 0; line-height: 1.15; }
  .played-card__score { font-size: 1.125rem; }
  .played-card__rating-value { font-size: 0.9375rem; }
  .played-card__delta { font-size: 0.75rem; }

  .fixtures .played-nav { padding: 0.6rem 0.75rem; }
  .fixtures .played-nav__btn { min-width: 40px; padding: 0.35rem 0.5rem; font-size: 0.75rem; }
  .fixtures .played-nav__label { font-size: 0.8125rem; }
}

/* ----- Played Results mobile refinements ----- */
@media (max-width: 760px) {
  .played-results .played-nav { padding: 0.6rem 1rem; }
  .played-results .played-nav__btn { min-height: 44px; min-width: 44px; }
  .played-results .played-nav__label { min-width: 0; }

  /* xG under score readability */
  .played-card__xg { font-size: 0.625rem; margin-top: 0.25rem; }
}

@media (max-width: 480px) {
  .played-results .played-nav { padding: 0.5rem 0.75rem; }
  .played-results .played-nav__btn { padding: 0.35rem 0.5rem; font-size: 0.75rem; }
}

/* ----- Compare Clubs mobile refinements ----- */
@media (max-width: 760px) {
  /* Team pickers already full-width cards */
  .compare__team { padding: 0.75rem 1rem; gap: 0.5rem; }
  .compare__team .team-logo { width: 40px; height: 40px; }
  .compare__card-main { flex-direction: column; align-items: center; gap: 0.35rem; }
  .compare__team-text { align-items: center; text-align: center; }
  .compare__pick-hint { font-size: 0.6875rem; padding-top: 0.4rem; }
  .compare__swap-center { width: 44px; height: 44px; font-size: 1.1rem; }

  /* Scoreline chips wrap */
  .compare__scorelines-chips { gap: 0.4rem; }
  .compare__scoreline { font-size: 0.85rem; padding: 0.25rem 0.6rem; min-width: 4rem; gap: 0.3rem; }
  .compare__scoreline-prob { font-size: 0.7rem; }

  /* H2H record */
  .compare__h2h-record { font-size: 1.1rem; }
  .compare__h2h-team { font-size: 0.6875rem; }
  .compare__h2h-stat { font-size: 1.1rem; }
}

@media (max-width: 480px) {
  .compare__team { padding: 0.6rem 0.7rem; }
  .compare__team .team-logo { width: 36px; height: 36px; }
  .compare__team-name { font-size: 0.875rem; }
  .compare__team-rating { font-size: 1.1rem; }
  .compare__scoreline { font-size: 0.75rem; padding: 0.2rem 0.5rem; min-width: 3.5rem; }
  .compare__scoreline-prob { font-size: 0.625rem; }
  .compare__h2h-record { font-size: 1rem; }
  .compare__h2h-stat { font-size: 1rem; }
}

/* ----- Model Card mobile refinements ----- */
@media (max-width: 760px) {
  .model-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 480px) {
  .model-grid { grid-template-columns: 1fr; }
  .panel .model-grid div { padding: 0.8rem 0.9rem; }
  .model-grid dt { font-size: 0.625rem; }
  .model-grid dd { font-size: 0.9375rem; }
  .caveats { padding: 1rem; }
  .caveats li { font-size: 0.8125rem; }
}

/* ----- Grid Animation Controls mobile ----- */
@media (max-width: 760px) {
  .grid-anim-btn { height: 44px; padding: 0 0.75rem; }
  .grid-anim-bar { padding: 0.5rem 1rem; gap: 0.5rem; }
  .grid-anim-bar__when { min-width: 0; font-size: 0.75rem; }
  .grid-anim-speed button { min-height: 44px; min-width: 3rem; padding: 0.2rem 0.4rem; font-size: 0.6875rem; }
  .grid-anim-speed { padding: 2px; }
}

@media (max-width: 480px) {
  .grid-anim-bar { flex-wrap: wrap; justify-content: center; gap: 0.5rem; }
  .grid-anim-bar__when { order: -1; width: 100%; text-align: center; margin-bottom: 0.25rem; }
  .grid-anim-speed { order: 0; }
}

/* ----- Finish Grid mobile: ensure tooltip works on tap ----- */
@media (pointer: coarse) {
  .cell { cursor: pointer; }
  .team-grid-row__cell { cursor: pointer; }
}

/* Ensure all interactive elements have 44px minimum touch target */
@media (pointer: coarse) {
  .compare__option { min-height: 44px; padding: 0.6rem 0.75rem; }
  .popover-menu__btn { min-height: 44px; padding: 0.6rem 0.75rem; }
  .settings-btn { min-height: 44px; min-width: 44px; }
  .hero-title-part { min-height: 44px; display: inline-flex; align-items: center; padding: 0.25rem 0; }
}

/* Focus visible styles for mobile keyboard navigation */
@media (max-width: 760px) {
  :where(a, button, [tabindex]):focus-visible {
    outline: 2px solid var(--tier-1);
    outline-offset: 2px;
    border-radius: 2px;
  }
}

/* Smooth scrolling for anchor links */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ---------- one secondary button ---------------------------------- */

/* Every secondary action shares one look, whichever view it is in: a pill
   with a hairline border on the panel colour, and the same hover. They had
   drifted apart -- 4px, 8px and 14px corners, sunk or raised fills, light or
   strong borders -- so the same kind of control looked different per view.
   Last in the file so it settles the corners and colours; each rule above
   keeps its own size. */
.grid-anim-btn,
.played-nav__btn,
.timeline__now,
.timeline__step,
.compare__swap-center {
  white-space: nowrap;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink);
  font-weight: 600;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease);
}

.grid-anim-btn:not([aria-pressed="true"]):not(:disabled):hover,
.played-nav__btn:hover,
.timeline__now:hover,
.timeline__step:hover:not(:disabled),
.compare__swap-center:hover {
  background: var(--panel-sunk);
  border-color: var(--rule-strong);
}

/* Touch size on a phone, like the rewind step buttons. */
@media (pointer: coarse), (max-width: 760px) {
  .grid-anim-btn { height: 44px; }
  .grid-anim-speed button { min-height: 44px; min-width: 3rem; }
  .grid-anim-bar { padding-inline: 1rem; gap: 0.6rem; }
  .grid-anim-bar__when { min-width: 0; }
}


/* xG beneath a played score: secondary, so smaller and muted. */
.played-card__xg {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--body);
  font-size: 0.6875rem;
  font-weight: 500;
  color: var(--ink-muted);
}
