/* Site styles. Edited directly — the build copies this file verbatim.
 *
 * Palette is validated: the categorical/diverging pair passes lightness-band,
 * chroma, CVD-separation, normal-vision and contrast checks in both light and
 * dark mode. Status colours always ship with an icon and a label, so meaning
 * never rides on hue alone.
 */
/* ---------------------------------------------------------------------
   Brand: Pine / Emerald / Bone. Taken from the identity sheet in the design
   folder, in the same oklch it was drawn in, so the site and the channel
   avatar are the same green rather than two greens that nearly match.

     Pine        oklch(0.20 0.035 165)   the dark ground
     Night Pine  oklch(0.16 0.025 165)   one step below it, for dark mode
     Emerald     oklch(0.68 0.14  158)   the one accent
     Bone        oklch(0.95 0.016 95)    the light ground

   Emerald is stated twice on purpose. The drawn value sits at L=0.68, which
   is right against Pine and much too light to read against Bone, so the light
   theme uses a deeper L=0.50 cut of the same hue for anything carrying text.
   --------------------------------------------------------------------- */
:root {
  color-scheme: light;
  --pine: oklch(0.20 0.035 165);
  --emerald: oklch(0.68 0.14 158);
  --bone: oklch(0.95 0.016 95);

  --page: var(--bone);
  --surface-1: oklch(0.99 0.008 95);
  --text-primary: oklch(0.21 0.03 165);
  /* Measured against BOTH grounds, and the page is the binding one: Bone sits
     at L=0.95, so anything lighter than about L=0.53 fails AA for the 11.5px
     hints these two are used for. Secondary is pushed down with muted rather
     than left where it was, or the two would land on top of each other and
     the hierarchy would vanish to buy the contrast. */
  --text-secondary: oklch(0.44 0.025 165);
  --muted: oklch(0.52 0.02 160);
  --grid: oklch(0.91 0.012 100);
  --axis: oklch(0.83 0.016 100);
  --border: oklch(0.89 0.014 100);
  --brand: oklch(0.50 0.12 158);
  --series-1: oklch(0.50 0.12 158);
  --pos: oklch(0.50 0.12 158);
  --neg: oklch(0.55 0.17 25);
  --good: oklch(0.50 0.12 158);
  --warning: oklch(0.52 0.13 75);
  --critical: oklch(0.55 0.17 25);
  --losing: oklch(0.55 0.17 25);
  --neutral: oklch(0.50 0.025 165);
  --neutral-mid: oklch(0.93 0.012 100);
  --shadow: 0 1px 2px oklch(0.20 0.035 165 / 0.05),
            0 8px 24px oklch(0.20 0.035 165 / 0.06);

  --font-sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system,
               "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo,
               Consolas, monospace;
}

/* Dark mode is Night Pine, not grey: the brand has a dark ground of its own
   and borrowing a neutral one would throw the accent off. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --page: oklch(0.16 0.025 165);
    --surface-1: oklch(0.20 0.035 165);
    --text-primary: oklch(0.97 0.012 100);
    --text-secondary: oklch(0.76 0.02 150);
    --muted: oklch(0.60 0.02 160);
    --grid: oklch(0.27 0.03 165);
    --axis: oklch(0.36 0.03 165);
    --border: oklch(0.30 0.03 165);
    --brand: var(--emerald);
    --series-1: var(--emerald);
    --pos: var(--emerald);
    --neg: oklch(0.68 0.16 25);
    --good: var(--emerald);
    --warning: oklch(0.80 0.14 78);
    --critical: oklch(0.68 0.16 25);
    --losing: oklch(0.68 0.16 25);
    --neutral: oklch(0.76 0.02 150);
    --neutral-mid: oklch(0.27 0.03 165);
    --shadow: 0 1px 2px oklch(0 0 0 / 0.30), 0 8px 24px oklch(0 0 0 / 0.28);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --page: oklch(0.16 0.025 165);
  --surface-1: oklch(0.20 0.035 165);
  --text-primary: oklch(0.97 0.012 100);
  --text-secondary: oklch(0.76 0.02 150);
  --muted: oklch(0.60 0.02 160);
  --grid: oklch(0.27 0.03 165);
  --axis: oklch(0.36 0.03 165);
  --border: oklch(0.30 0.03 165);
  --brand: var(--emerald);
  --series-1: var(--emerald);
  --pos: var(--emerald);
  --neg: oklch(0.68 0.16 25);
  --good: var(--emerald);
  --warning: oklch(0.80 0.14 78);
  --critical: oklch(0.68 0.16 25);
  --losing: oklch(0.68 0.16 25);
  --neutral: oklch(0.76 0.02 150);
  --neutral-mid: oklch(0.27 0.03 165);
  --shadow: 0 1px 2px oklch(0 0 0 / 0.30), 0 8px 24px oklch(0 0 0 / 0.28);
}

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--page); color: var(--text-primary);
  font: 15px/1.65 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Every figure on this site is meant to be compared with the one under it. */
.hero, .kpi .v, .picknums .n .v, .accanums .n .v, .acca .nums .v,
td.num, th.num, .stat, td.conf {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
a { color: inherit; }
/* One number for both the page and the topbar, so the brand stays lined up
   with the content under it. Wide enough for the ten-column card table to fit
   without scrolling on a normal laptop. */
:root { --page-width: 1480px; }
.wrap { max-width: var(--page-width); margin: 0 auto; padding: 0 20px 80px; }

/* ---- site header + nav ---- */
.topbar { border-bottom: 1px solid var(--border); background: var(--surface-1);
  position: sticky; top: 0; z-index: 30; }
.topbar .inner { max-width: var(--page-width); margin: 0 auto; padding: 0 20px;
  display: flex; align-items: center; gap: 22px; min-height: 56px; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none;
  white-space: nowrap; color: var(--text-primary); }
.logomark { width: 46px; height: 19px; flex: none; }
.wordmark { display: flex; flex-direction: column; line-height: 1; }
.wordmark .w1 { font-size: 14px; font-weight: 700; letter-spacing: -0.015em; }
.wordmark .w2 { font-family: var(--font-mono); font-size: 8.5px; font-weight: 500;
  letter-spacing: 0.19em; color: var(--brand); margin-top: 4px; }
/* The pages and the theme switch, together, so a narrow screen can fold both
   into one menu. On a wide one this box is only a row. */
.menu { display: flex; align-items: center; gap: 22px; flex: 1 1 auto; min-width: 0; }
nav.main { display: flex; gap: 2px; margin-right: auto; }
nav.main a { text-decoration: none; font-size: 13.5px; color: var(--text-secondary);
  padding: 7px 11px; border-radius: 7px; white-space: nowrap; }
nav.main a:hover { background: color-mix(in srgb, var(--brand) 10%, transparent);
  color: var(--text-primary); }
nav.main a[aria-current="page"] { color: var(--text-primary); font-weight: 600;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  box-shadow: inset 0 -2px 0 var(--brand); }
button.theme { font: inherit; font-size: 12px; cursor: pointer; padding: 5px 11px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--page);
  color: var(--text-secondary); white-space: nowrap; }
button.theme:hover { color: var(--text-primary); }
.theme-long, .menu-toggle { display: none; }

/* Below this the seven pages and the theme switch no longer fit beside the
   brand. They used to scroll sideways in a strip that ran underneath the theme
   button; now they fold behind one button into a menu that drops under the
   bar. The bar stays pinned, so the menu is one tap away from anywhere. */
@media (max-width: 900px) {
  .topbar .inner { gap: 12px; }
  .menu-toggle { display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin: 0 -10px 0 auto; padding: 0; border: 0;
    border-radius: 10px; background: none; color: var(--text-primary); cursor: pointer; }
  .menu-toggle svg { width: 24px; height: 24px; }
  .menu-toggle .i-close, .menu-toggle[aria-expanded="true"] .i-open { display: none; }
  .menu-toggle[aria-expanded="true"] .i-close { display: block; }
  .menu { display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    max-height: calc(100vh - 56px); overflow-y: auto;
    padding: 8px 12px 14px; background: var(--surface-1);
    border-bottom: 1px solid var(--border); box-shadow: var(--shadow); }
  .menu-toggle[aria-expanded="true"] + .menu { display: flex; }
  nav.main { flex-direction: column; margin: 0; }
  nav.main a { font-size: 15px; padding: 11px 12px; border-radius: 8px; }
  nav.main a[aria-current="page"] { box-shadow: inset 3px 0 0 var(--brand); }
  /* A row like the pages above it, set off by a rule, rather than a pill. */
  .menu button.theme { margin-top: 8px; padding: 12px; border: 0; border-radius: 8px;
    border-top: 1px solid var(--border); border-top-left-radius: 0;
    border-top-right-radius: 0; background: none; text-align: left;
    font-size: 14px; color: var(--text-secondary); }
  .theme-long { display: inline; }
  #theme-label { text-transform: lowercase; }
}

.pagehead { padding: 34px 0 22px; }
.pagehead h1 { font-size: 26px; font-weight: 650; margin: 0 0 6px; letter-spacing: -0.018em; }
.pagehead p { color: var(--text-secondary); font-size: 14px; margin: 0; max-width: 72ch; }
.badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 14px; }
.badge { font-size: 11.5px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text-secondary);
  background: var(--surface-1); white-space: nowrap; }

/* Hairline, not shadow. A 1px border already separates a card from the
   ground; stacking a drop shadow on top of it is the look both of the design
   guides this was checked against call the giveaway of a generated interface.
   --shadow survives for the two things that genuinely float above the page:
   the tooltip and the accumulator tray. */
.card { background: var(--surface-1); border: 1px solid var(--border);
  border-radius: 12px; padding: 24px 26px; margin-bottom: 20px; }
.card > h2 { font-size: 15px; font-weight: 620; margin: 0 0 3px; letter-spacing: -0.005em; }
.card > .note { font-size: 12.5px; color: var(--text-secondary); margin: 0 0 18px; max-width: 72ch; }

/* ---- verdict / hero ---- */
.verdict { display: flex; gap: 28px; align-items: center; flex-wrap: wrap; }
.hero-label { font-size: 12px; color: var(--text-secondary); text-transform: uppercase;
  letter-spacing: 0.06em; margin-bottom: 2px; }
.hero { font-size: 52px; line-height: 1.05; font-weight: 640; letter-spacing: -0.025em; }
.hero .ci { display: block; font-size: 13px; font-weight: 400; letter-spacing: 0;
  color: var(--text-secondary); margin-top: 6px; }
.status { display: flex; gap: 10px; align-items: flex-start; padding: 12px 16px;
  border-radius: 10px; border: 1px solid var(--border); max-width: 48ch; }
.status .icon { flex: none; width: 20px; height: 20px; margin-top: 1px; }
.status .t { font-weight: 600; font-size: 13.5px; margin-bottom: 2px; }
.status .d { font-size: 12.5px; color: var(--text-secondary); }

.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px;
  background: var(--border); border: 1px solid var(--border); border-radius: 10px;
  overflow: hidden; margin-top: 22px; }
.kpi { background: var(--surface-1); padding: 14px 16px; }
.kpi .k { font-size: 11.5px; color: var(--text-secondary); margin-bottom: 4px; }
.kpi .v { font-size: 21px; font-weight: 620; letter-spacing: -0.015em; }
.kpi .m { font-size: 11.5px; color: var(--muted); margin-top: 2px; }

/* ---- best pick ---- */
.pick { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; }
.pick .side { flex: 1 1 260px; }
.pick .fixture { font-size: 22px; font-weight: 640; letter-spacing: -0.015em; margin-bottom: 3px; }
.pick .when { font-size: 12.5px; color: var(--text-secondary); }
.pick .selection { font-size: 13px; margin-top: 12px; color: var(--text-secondary); }
.pick .selection strong { color: var(--text-primary); font-size: 15px; }
.picknums { display: flex; gap: 26px; flex-wrap: wrap; }
.picknums .n { min-width: 78px; }
.picknums .n .k { font-size: 11.5px; color: var(--text-secondary); }
.picknums .n .v { font-size: 24px; font-weight: 640; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; }

/* ---- insights ---- */
.insight { border-left: 3px solid var(--state, var(--neutral)); }
.insight .top { display: flex; gap: 10px; align-items: flex-start; margin-bottom: 8px; }
.insight .icon { flex: none; width: 19px; height: 19px; margin-top: 2px; color: var(--state); }
.insight h2, .insight h3 { font-size: 15px; font-weight: 620; margin: 0 0 2px;
  letter-spacing: -0.008em; }
.insight .headline { font-size: 13.5px; color: var(--state); font-weight: 560; }
.insight .detail { font-size: 13px; color: var(--text-secondary); margin: 10px 0 14px;
  max-width: 76ch; }
.insight .stat { margin-left: auto; font-size: 11.5px; color: var(--text-secondary);
  border: 1px solid var(--border); padding: 3px 9px; border-radius: 999px;
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.insight table { font-size: 12.5px; }

/* Group headings on the evidence page. Ten findings in a row all looked
   equally important; these say which two settle the question and which three
   only look like rescues. The rule above each is the change of shape. */
.insight-group {
  font-size: 17px; font-weight: 650; letter-spacing: -0.012em;
  margin: 42px 0 14px; padding-top: 18px;
  border-top: 1px solid var(--border);
}
.insight-group:first-of-type { margin-top: 26px; }
.insight h4 { font-size: 15px; font-weight: 620; margin: 0 0 2px;
  letter-spacing: -0.008em; }

/* ---- charts ---- */
.chart { width: 100%; overflow-x: auto; }
svg { display: block; max-width: 100%; }
svg text { font-family: var(--font-sans); }
.tick { font-size: 11px; fill: var(--muted); font-variant-numeric: tabular-nums; }
.gridline { stroke: var(--grid); stroke-width: 1; }
.baseline { stroke: var(--axis); stroke-width: 1; }
.bar-label { font-size: 11px; fill: var(--text-secondary); font-variant-numeric: tabular-nums; }

.tooltip { position: fixed; pointer-events: none; z-index: 40; opacity: 0;
  transition: opacity .09s; background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 11px; font-size: 12.5px;
  box-shadow: 0 6px 20px rgba(0,0,0,.13); max-width: 260px; }
.tooltip .tt-h { font-weight: 620; margin-bottom: 3px; }
.tooltip .tt-r { color: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* ---- tables ---- */
/* A table wider than its box says so: a soft shade on whichever edge has more
   to scroll to. The two card-coloured washes travel with the content and cover
   the shades once an end is reached, so a table that fits shows neither. */
.tablewrap { overflow-x: auto;
  background:
    linear-gradient(to right, var(--surface-1) 40%, transparent) left / 32px 100% no-repeat local,
    linear-gradient(to left, var(--surface-1) 40%, transparent) right / 32px 100% no-repeat local,
    linear-gradient(to right, color-mix(in srgb, var(--text-primary) 13%, transparent), transparent) left / 12px 100% no-repeat scroll,
    linear-gradient(to left, color-mix(in srgb, var(--text-primary) 13%, transparent), transparent) right / 12px 100% no-repeat scroll; }
/* A long table scrolls inside its own box, so the header can actually pin.
   position:sticky resolves against the nearest scroll container, and the
   plain .tablewrap only scrolls horizontally — a sticky header inside it
   pins to a box that never moves vertically, i.e. never sticks at all. */
.tablewrap.tall { max-height: 70vh; overflow: auto; }
table { border-collapse: collapse; width: 100%; font-size: 13px; }
/* Text cells WRAP. They used to be nowrap across the board, which is what
   forced a ten-column card wider than the window and put a horizontal
   scrollbar under it — a long team name could push the whole table out on its
   own. Numbers still hold their line, because a figure broken across two rows
   is unreadable. */
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border);
  white-space: normal; overflow-wrap: break-word; }
td.num, th.num, td.nowrap, th.nowrap { white-space: nowrap; }
th { font-size: 11.5px; color: var(--text-secondary); font-weight: 600; }
table.sticky thead th { position: sticky; top: 0; background: var(--surface-1); z-index: 2;
  box-shadow: inset 0 -1px 0 var(--border); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tbody tr:hover { background: color-mix(in srgb, var(--text-primary) 4%, transparent); }
.pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border); }
.filters { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.filters input, .filters select { font: inherit; font-size: 12.5px; padding: 5px 9px;
  border-radius: 7px; border: 1px solid var(--border); background: var(--page);
  color: var(--text-primary); }
.filters .count { font-size: 12px; color: var(--text-secondary); margin-left: auto; }

/* ---- pages of a long table ---- */
.pager { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 12px; }
.pager[hidden], .pager [hidden] { display: none; }
.pager button { font: inherit; font-size: 12.5px; cursor: pointer; min-width: 32px;
  padding: 5px 10px; border-radius: 7px; border: 1px solid var(--border);
  background: var(--page); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.pager button:hover:not(:disabled) { color: var(--text-primary); border-color: var(--series-1); }
.pager button[aria-current="page"] { color: var(--text-primary); font-weight: 600;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  border-color: color-mix(in srgb, var(--brand) 45%, var(--border)); }
.pager button:disabled { opacity: .4; cursor: default; }
.pager .gap { color: var(--muted); padding: 0 4px; }
/* The card's next rows, under the ones showing. */
.more { display: block; margin: 12px auto 0; font: inherit; font-size: 12.5px;
  cursor: pointer; padding: 6px 14px; border-radius: 7px; border: 1px solid var(--border);
  background: var(--page); color: var(--text-secondary); }
.more:hover { color: var(--text-primary); border-color: var(--series-1); }
.more[hidden] { display: none; }
.pager .n { font-size: 11px; font-weight: 400; color: var(--muted); margin-left: 3px; }
/* The day buttons sit above their table rather than under it. */
.paged > .pager:first-child { margin: 0 0 12px; }
/* Paging scrolls the table's top back into view; this keeps it clear of the
   sticky topbar rather than tucked under it. */
.paged { scroll-margin-top: 72px; }
.empty { padding: 26px; text-align: center; color: var(--text-secondary); font-size: 13px; }


footer.site { color: var(--text-secondary); font-size: 12.5px; line-height: 1.65;
  border-top: 1px solid var(--border); padding-top: 18px; margin-top: 10px; }
footer.site code, .mono { background: var(--neutral-mid); padding: 1px 5px;
  border-radius: 4px; font-size: 12px; font-family: var(--font-mono); }
footer.site p { max-width: 76ch; }
/* The underline sits on the span, not the link: an underline running beneath
   the mark itself reads as a box around it rather than as a link. */
footer.site .ext a { color: var(--brand); text-decoration: none; }
footer.site .ext a span {
  border-bottom: 1px solid color-mix(in srgb, var(--brand) 40%, transparent); }
footer.site .ext a:hover span { border-bottom-color: var(--brand); }
/* Both of these undo the blanket `svg` rule above, which exists for the charts.
   `display: block` there would drop the mark onto its own line; `max-width:
   100%` keeps a wide chart inside a narrow phone, but a 14px mark has no
   business shrinking with its container — in a narrow enough one it collapses
   to nothing at all. */
footer.site .ext svg { display: inline-block; max-width: none;
  width: 14px; height: 14px; vertical-align: -3px; margin-right: 5px; }
.next { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.next a { text-decoration: none; font-size: 13px; padding: 9px 14px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--surface-1); color: var(--text-primary); }
.next a:hover { border-color: var(--series-1); }
.next a span { display: block; font-size: 12px; color: var(--text-secondary); margin-top: 2px; }

/* ---- the card ---- */
.confbar { display: inline-block; vertical-align: middle; width: 46px; height: 7px;
  border-radius: 3px; background: var(--neutral-mid); position: relative;
  overflow: hidden; margin-right: 8px; }
.confbar > i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px;
  background: var(--series-1); }
td.conf { font-variant-numeric: tabular-nums; font-weight: 600; }
tr.unvalidated td { color: var(--muted); }
.tag { font-size: 10.5px; padding: 1px 6px; border-radius: 999px; margin-left: 6px;
  border: 1px solid var(--border); color: var(--text-secondary); }
.tag.warn, .tag.warning { border-color: color-mix(in srgb, var(--warning) 55%, var(--border));
  color: var(--warning); }
.tag.critical { border-color: color-mix(in srgb, var(--critical) 55%, var(--border));
  color: var(--critical); }
td.pickbox { width: 30px; padding-right: 0; }

/* Accumulator tray: only appears once something is ticked. */
.acca { position: sticky; bottom: 0; z-index: 20; margin-top: 14px;
  border: 1px solid var(--border); border-radius: 12px; padding: 12px 16px;
  background: var(--surface-1);
  box-shadow: 0 -6px 20px color-mix(in srgb, var(--text-primary) 8%, transparent); }
.acca[hidden] { display: none; }
.acca .legs { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 6px; }
.acca .nums { display: flex; gap: 26px; flex-wrap: wrap; align-items: baseline; }
.acca .nums .v { font-size: 22px; font-weight: 640; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; }
.acca .nums .k { font-size: 11.5px; color: var(--text-secondary); }
.acca .warn { color: var(--warning); font-size: 12px; margin-top: 6px; }
.acca button { font: inherit; font-size: 12px; cursor: pointer; padding: 5px 10px;
  border-radius: 7px; border: 1px solid var(--border); background: var(--page);
  color: var(--text-secondary); margin-left: auto; }

.empty .hint { font-size: 12px; color: var(--muted); margin-top: 6px; }

/* ---- the two headline picks ---- */
.card.best { border-left: 3px solid var(--series-1); }
.card.best .pick { margin-top: 4px; }
.accanums { display: flex; gap: 28px; flex-wrap: wrap; margin-top: 4px; }
.accanums .n .k { font-size: 11.5px; color: var(--text-secondary); }
.accanums .n .v { font-size: 22px; font-weight: 640; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; }

/* Give the wide tables a shape rather than letting the browser guess: the
   match name should absorb the slack, everything else stays as narrow as its
   content. */
table.cardtable td:nth-child(4), table.cardtable th:nth-child(4),
table.fixtures td:nth-child(3), table.fixtures th:nth-child(3) { width: 40%; }
table.cardtable td:nth-child(5), table.cardtable th:nth-child(5) { width: 22%; }

/* Narrow windows drop columns instead of scrolling sideways, least useful
   first. Offered and Edge go before the league does, because they are empty on
   every row the price feed does not quote — which is most of the card — while
   the league is on every row and is how you find the match you care about. */
@media (max-width: 1180px) { .col-band { display: none; } }
@media (max-width: 1040px) { .col-offered, .col-edge { display: none; } }
@media (max-width: 900px)  { .col-league, .col-extra { display: none; } }
@media (max-width: 760px)  { .confbar { display: none; } }

@media (max-width: 760px) {
  th, td { padding: 7px 8px; font-size: 12.5px; }
  table.cardtable td:nth-child(4), table.cardtable th:nth-child(4) { width: auto; }
}

/* ---- the accumulator book ----
   One leg to a line, in four columns that line up down the slip: when, the
   match, the bet, and its chance. They used to be one run-on sentence. */
table.slips td { vertical-align: top; padding-top: 12px; padding-bottom: 12px; }
table.slips th:nth-child(2), table.slips td:nth-child(2) { width: 60%; }
.slip-legs { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: auto minmax(0, 1.2fr) minmax(0, 1fr) auto;
  column-gap: 16px; row-gap: 5px; align-items: baseline; }
.slip-legs li { display: contents; }
.slip-legs .d, .slip-legs .p { font-size: 12px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.slip-legs .m { color: var(--text-primary); }
.slip-legs .s { color: var(--text-secondary); }
.slip-legs .p { text-align: right; }

/* Too narrow for four columns: each leg takes two lines, the match and its
   chance over the bet and its day, with a rule between legs. */
@media (max-width: 900px) {
  .slip-legs { display: block; }
  .slip-legs li { display: grid; grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px; align-items: baseline; padding: 6px 0; }
  .slip-legs li + li { border-top: 1px solid var(--border); }
  .slip-legs li:first-child { padding-top: 0; }
  .slip-legs .m { grid-area: 1 / 1; }
  .slip-legs .p { grid-area: 1 / 2; }
  .slip-legs .s { grid-area: 2 / 1; font-size: 12.5px; }
  .slip-legs .d { grid-area: 2 / 2; text-align: right; }
}

/* Up to a tablet held upright the widest tables are still wider than the
   screen, so this starts well above phone width — at the same width the nav
   folds into its menu, below which nothing on the site is laid out for a desk. */
@media (max-width: 900px) {
  /* The card no longer scrolls inside its own box. On a touch screen that is a
     scroll within a scroll, and the rows are blocks now, not a grid under a
     header that needed pinning. */
  .tablewrap.tall { max-height: none; overflow: visible; }

  /* ---- a row as a block ----
     The widest tables stop being grids: see ROLES in components.py. Two
     zero-height full-width pseudo-elements break the row into its three
     lines, so each part only has to say which line it belongs on. */
  table.stack, table.stack > tbody { display: block; }
  table.stack > thead { position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap; }
  table.stack > tbody > tr { display: flex; flex-wrap: wrap; align-items: baseline;
    column-gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--border); }
  table.stack > tbody > tr[hidden] { display: none; }
  table.stack > tbody > tr::before, table.stack > tbody > tr::after {
    content: ""; flex-basis: 100%; height: 0; }
  table.stack > tbody > tr::before { order: 25; }
  table.stack > tbody > tr::after { order: 45; }
  table.stack > tbody > tr > td { display: block; width: auto; padding: 0; border: 0;
    text-align: left; white-space: normal; font-size: 12px; line-height: 1.45;
    color: var(--text-secondary); }
  table.stack > tbody > tr > td[colspan] { flex: 1 1 100%; }
  table.stack > tbody > tr > td.s-title { order: 10; flex: 1 1 0; min-width: 0;
    font-size: 14px; font-weight: 600; color: var(--text-primary); }
  table.stack > tbody > tr > td.s-end { order: 20; flex: none; text-align: right;
    font-size: 14px; font-weight: 600; color: var(--text-primary); }
  table.stack > tbody > tr > td.s-sub { order: 30; flex: 1 1 0; min-width: 0;
    margin-top: 2px; font-size: 13px; color: var(--text-primary); }
  /* margin-left keeps it on the right in a row with no subtitle to fill the
     line before it; with one, the subtitle has taken that space already. */
  table.stack > tbody > tr > td.s-end2 { order: 40; flex: none; text-align: right;
    margin-top: 2px; margin-left: auto; font-size: 12.5px; }
  table.stack > tbody > tr > td.s-meta { order: 50; flex: none; margin-top: 5px; }
  table.stack > tbody > tr > td.s-block { order: 60; flex: 1 1 100%; margin-top: 10px;
    font-size: 13px; }
  table.stack > tbody > tr > td.s-hide { display: none; }
  table.stack td.s-label::before { content: attr(data-label) " "; color: var(--muted); }
  table.stack td .tag:first-child { margin-left: 0; }
  table.stack .confbar { display: none; }
  table.stack > tbody > tr.unvalidated > td { color: var(--muted); }
  /* The card's tick box sits in the margin, beside all three lines. */
  table.cardtable.stack > tbody > tr { position: relative; padding-left: 32px; }
  table.cardtable.stack > tbody > tr > td.pickbox { position: absolute; left: 0; top: 12px; }
  table.cardtable.stack td.pickbox input { width: 18px; height: 18px; margin: 0; }
  /* A slip's legs, grouped on a panel of their own under its figures. */
  table.slips > tbody > tr > td.s-block .slip-legs { background: var(--page);
    border-radius: 8px; padding: 8px 12px; }
  table.slips > tbody > tr > td.s-block .slip-legs li:first-child { padding-top: 0; }
  table.slips > tbody > tr > td.s-block .slip-legs li:last-child { padding-bottom: 0; }
}

@media (max-width: 640px) {
  /* The gutters: the page's, then the card's inside it, came to 93px of a
     375px screen, and every table on the site was being asked to fit into
     what was left. */
  .wrap { padding: 0 14px 64px; }
  .topbar .inner { padding: 0 14px; }
  .card { padding: 18px 16px; border-radius: 10px; margin-bottom: 14px; }
  .pagehead { padding: 24px 0 16px; }
  .pagehead h1 { font-size: 23px; }
  .kpis { margin-top: 16px; }
  .kpi { padding: 12px 14px; }
  .kpi .v { font-size: 19px; }
  .hero { font-size: 40px; }
  .verdict, .pick { gap: 18px; }
  .filters input[type="search"] { flex: 1 1 100%; }
  .filters .count { margin-left: 0; }

  /* A table that still scrolls sideways keeps its first column in place, so
     every figure you scroll to stays next to the row it belongs to. */
  .tablewrap > table:not(.stack):not(.fixtures) > * > tr > :first-child {
    position: sticky; left: 0; z-index: 1; background: var(--surface-1); }
  /* The card's own padding already sets the table off its edges, so the
     outer cells give theirs up, and the rest keep only enough to part two
     figures. Enough on its own to bring a six-column table most of the way
     back inside a phone. */
  .tablewrap > table:not(.stack):not(.fixtures) > * > tr > * { padding: 7px 6px; }
  .tablewrap > table:not(.stack):not(.fixtures) > * > tr > :first-child { padding-left: 0; }
  .tablewrap > table:not(.stack):not(.fixtures) > * > tr > :last-child { padding-right: 0; }

  /* ---- the fixture list: the match, then its four figures under it ---- */
  table.fixtures, table.fixtures > tbody { display: block; }
  table.fixtures > thead { position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap; }
  table.fixtures > tbody > tr { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: 8px; padding: 11px 0; border-bottom: 1px solid var(--border); }
  table.fixtures > tbody > tr[hidden] { display: none; }
  table.fixtures > tbody > tr > td { display: block; width: auto; padding: 0; border: 0;
    white-space: normal; }
  table.fixtures > tbody > tr > td.fx-match { grid-area: 1 / 1 / 2 / -1; width: auto;
    font-size: 14px; font-weight: 600; }
  table.fixtures > tbody > tr > td.fx-league { grid-area: 2 / 1 / 3 / 4;
    font-size: 12px; color: var(--text-secondary); }
  table.fixtures > tbody > tr > td.fx-date { grid-area: 2 / 4 / 3 / 5; text-align: right;
    font-size: 12px; color: var(--muted); white-space: nowrap; }
  table.fixtures > tbody > tr > td.num { grid-row: 3; margin-top: 8px; text-align: left;
    font-size: 15px; font-weight: 600; }
  table.fixtures > tbody > tr > td.col-extra { display: none; }
  table.fixtures > tbody > tr > td.num::before { content: attr(data-label); display: block;
    font-size: 11px; font-weight: 400; color: var(--muted); }
  table.fixtures > tbody > tr.detail { display: block; padding: 0 0 12px; }
  table.fixtures > tbody > tr.detail > td { padding: 0; }
}


/* ======================================================================
   Landing page
   ----------------------------------------------------------------------
   The front door for someone who has never seen this before, so it has to
   answer three things above the fold: what it says, what it has been worth,
   and that it is a measurement rather than a tip. Every number on it is read
   from the same artifacts the rest of the site reads — there is no marketing
   copy here quoting a figure nothing generated.
   ====================================================================== */

.lhero { background: var(--pine); color: oklch(0.97 0.012 100);
  border-radius: 20px; padding: 56px 48px; margin-top: 26px;
  position: relative; overflow: hidden; }
/* A single wash of the accent, off the top-right corner. */
.lhero::after { content: ""; position: absolute; inset: -40% -20% auto auto;
  width: 620px; height: 620px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, oklch(0.68 0.14 158 / 0.16), transparent 62%); }
.lhero > * { position: relative; z-index: 1; }
.lhero .eyebrow { font-family: var(--font-mono); font-size: 11.5px;
  letter-spacing: 0.19em; color: var(--emerald); margin-bottom: 20px; }
.lhero h1 { font-size: clamp(30px, 4.6vw, 52px); line-height: 1.06; margin: 0 0 18px;
  font-weight: 700; letter-spacing: -0.03em; max-width: 19ch; }
.lhero h1 em { font-style: normal; color: var(--emerald); }
.lhero .lead { font-size: clamp(15px, 1.5vw, 18px); line-height: 1.6; margin: 0;
  color: oklch(0.85 0.02 120); max-width: 58ch; }

/* A pair of buttons, always the same width: each column is as wide as the
   longer label needs, so the two read as one choice rather than a big button
   beside a small one. Where the pair drops under its text it takes the whole
   row instead — see the narrow-screen rules below. */
.lactions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  width: fit-content; margin-top: 30px; }
.lactions .btn { justify-content: center; text-align: center; }
.btn { display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  font-size: 14px; font-weight: 600; padding: 12px 20px; border-radius: 10px;
  border: 1px solid transparent; transition: transform .12s ease, opacity .12s ease; }
.btn:hover { transform: translateY(-1px); }
.btn:focus-visible { outline: 2px solid var(--emerald); outline-offset: 3px; }
.btn.primary { background: var(--emerald); color: oklch(0.17 0.03 165); }
.btn.primary:hover { opacity: .92; }
.btn.ghost { border-color: oklch(0.97 0.012 100 / 0.28); color: oklch(0.97 0.012 100); }
.btn.ghost:hover { border-color: var(--emerald); color: var(--emerald); }

/* The day's pick, inside the hero. Same numbers as the Card page. */
.lpick { margin-top: 34px; border-radius: 14px; padding: 22px 24px;
  background: oklch(0.97 0.012 100 / 0.06);
  border: 1px solid oklch(0.97 0.012 100 / 0.14);
  display: flex; gap: 30px; align-items: center; flex-wrap: wrap; }
/* Sentence case, normal tracking. It was reading as a fourth eyebrow on a
   page that could afford one. */
.lpick .band { font-size: 12.5px; font-weight: 550; color: var(--emerald);
  margin-bottom: 8px; }
.lpick .fixture { font-size: 20px; font-weight: 650; letter-spacing: -0.018em; }
.lpick .meta { font-size: 12.5px; color: oklch(0.82 0.02 120); margin-top: 3px; }
.lpick .sel { font-size: 15px; font-weight: 600; margin-top: 12px; color: var(--emerald); }
.lpick .nums { display: flex; gap: 28px; margin-left: auto; flex-wrap: wrap; }
.lpick .nums .k { font-size: 11px; color: oklch(0.82 0.02 120); }
.lpick .nums .v { font-size: 26px; font-weight: 650; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; }
.lpick.none { display: block; color: oklch(0.85 0.02 120); font-size: 14px; }

/* The record strip. Deliberately the first thing under the hero. */
/* Four abreast made four claims of equal weight, and they are not. The
   calibration record rests on a million graded selections; the daily ledger
   rests on sixteen. The grid says which is which. */
.lstats { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 1px; background: var(--border); border: 1px solid var(--border);
  border-radius: 14px; overflow: hidden; margin-top: 22px; }
.lstat { background: var(--surface-1); padding: 20px 22px; }
.lstat.lead { padding: 24px 26px; }
.lstat.lead .v { font-size: clamp(30px, 3.4vw, 40px); color: var(--brand); }
.lstat.lead .k { font-size: 12.5px; color: var(--text-primary); font-weight: 550; }
.lstat .v { font-size: 27px; font-weight: 650; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; line-height: 1.1; }
.lstat .k { font-size: 11.5px; color: var(--text-secondary); margin-top: 6px; }
.lstat .m { font-size: 11.5px; color: var(--muted); margin-top: 2px; }

.lsection { margin-top: 56px; }
/* The tracked-caps label above each section headline is gone. The headline
   was always doing the work; the label was repeating the page structure back
   at the reader. */
.lsection > .lead { font-size: clamp(20px, 2.4vw, 27px); font-weight: 650;
  letter-spacing: -0.022em; margin: 0 0 26px; max-width: 30ch; line-height: 1.25; }

/* ---- how it works: the pipeline ----
   Not cards. Each stage takes the number the stage above it produced, so the
   section is drawn as one continuous spine with a node per stage: the rail is
   what carries the ordering, which is why nothing here is numbered.

   The rail is a hairline down to the calibration and the accent from there on.
   That is the one piece of colour in the section and it is load-bearing: it
   marks where the number starts being worth trusting. */
/* Given a measure rather than the full page width. The prose caps at 62ch for
   readability, and on a 1385px row that left 500px of nothing to the right of
   every stage — the same hole the four-card version had, just moved. Bounding
   the block instead puts that space outside it, where it reads as margin. It
   is the only unboxed section on the page, so being narrower than the panels
   around it is a difference in kind rather than an inconsistency. */
.lsteps { margin-top: 4px; max-width: 900px; }
.lstep {
  --rail: var(--border);
  display: grid;
  grid-template-columns: 22px minmax(190px, 260px) minmax(0, 1fr);
  gap: 0 30px;
  padding: 20px 0 22px;
  position: relative;
}
.lstep.pivot, .lstep.trusted { --rail: var(--series-1); }

/* The spine, drawn per stage so it joins up into one line. */
.lstep .rail { position: relative; }
.lstep .rail::before {
  content: ""; position: absolute; left: 4px; top: 0; bottom: -22px;
  width: 1px; background: var(--rail);
}
.lstep:last-child .rail::before { bottom: auto; height: 26px; }
.lstep .rail::after {
  content: ""; position: absolute; left: 0; top: 5px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--page); border: 1.5px solid var(--rail);
}
/* The stage the copy above singles out: filled, not just coloured. */
.lstep.pivot .rail::after {
  background: var(--series-1); border-color: var(--series-1);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 18%, transparent);
}

.lstep h3 { font-size: 15px; font-weight: 650; margin: 0 0 6px;
  letter-spacing: -0.01em; }
.lstep.pivot h3 { color: var(--brand); }
/* What the stage takes and what it hands on. Mono because it is data, lower
   case because an uppercase tracked label here would be a fourth eyebrow. */
.lstep .io { font-family: var(--font-mono); font-size: 11.5px; line-height: 1.5;
  color: var(--muted); }
/* The arrow is the operator, not a tick on the rail: it took the rail colour
   at first and came out at 1.2:1, which is a hairline pretending to be text.
   Stronger than the words either side of it, because it is the verb. */
.lstep .io .arrow { color: var(--text-secondary); padding: 0 3px; }
.lstep p { font-size: 13.5px; color: var(--text-secondary); margin: 0;
  line-height: 1.62; max-width: 62ch; }


/* The limits. Same visual weight as the claims, which is the point. */
/* The calibration chart: the site's own claim, drawn. The note sits beside it
   on a wide screen and under it on a narrow one, because a chart squeezed into
   half a phone is not a chart. */
.lcal-body { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 28px; align-items: start; background: var(--surface-1);
  border: 1px solid var(--border); border-radius: 14px; padding: 24px 26px; }
.lcal-body .chart { overflow: visible; }
.lcal-note p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.62;
  margin: 0 0 12px; max-width: 46ch; }
.lcal-note p:last-child { margin-bottom: 0; }
.lcal-note strong { color: var(--text-primary); font-weight: 620;
  font-variant-numeric: tabular-nums; }
.lcal-note a { color: var(--brand); }

.llimits { background: var(--surface-1); border: 1px solid var(--border);
  border-radius: 14px; padding: 28px 30px; }
.llimits ul { margin: 0; padding-left: 20px; }
.llimits li { font-size: 13.5px; color: var(--text-secondary); line-height: 1.65;
  margin-bottom: 10px; }
.llimits li:last-child { margin-bottom: 0; }
.llimits li strong { color: var(--text-primary); font-weight: 600; }

/* The text takes whatever the buttons leave. It used to wrap the buttons
   under it as soon as the two no longer fit side by side at full measure,
   well before the 900px switch below, and they sat there at the left. */
.lcta { margin-top: 56px; border: 1px solid var(--border); border-radius: 16px;
  padding: 34px 36px; background: var(--surface-1);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 26px;
  align-items: center; }
.lcta .lactions { margin-top: 0; }
.lcta h2 { font-size: 21px; font-weight: 650; margin: 0 0 6px; letter-spacing: -0.02em; }
.lcta p { font-size: 13.5px; color: var(--text-secondary); margin: 0; max-width: 52ch; }
.lcta .btn.primary { background: var(--brand); color: var(--surface-1); }
.lcta .btn.ghost { border-color: var(--border); color: var(--text-primary); }

@media (max-width: 980px) {
  .lstats { grid-template-columns: 1fr 1fr; }
  .lstat.lead { grid-column: 1 / -1; }
  .lcal-body { grid-template-columns: 1fr; gap: 20px; }
}

/* The call to action's buttons go under its text, and fill the row there. */
@media (max-width: 900px) {
  .lcta { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .lcta .lactions { width: auto; }
}

@media (max-width: 760px) {
  /* The rail stays: it is the ordering, and it costs 22px. Heading, the
     in/out line and the prose stack in the column beside it. */
  .lstep { grid-template-columns: 22px minmax(0, 1fr); gap: 0 18px; }
  .lstep p { grid-column: 2; margin-top: 12px; max-width: none; }
  .lhero { padding: 38px 24px; border-radius: 16px; }
  .lpick { gap: 20px; padding: 18px; }
  .lpick .nums { margin-left: 0; gap: 22px; }
  .lsection { margin-top: 42px; }
  .lcta { padding: 26px 22px; }
}

/* Below the 980px two-up, and after it in the file so it actually wins. */
@media (max-width: 640px) {
  .lstats { grid-template-columns: 1fr; }
  .lcal-body { padding: 18px; }
  /* On a phone the hero's pair fills its row too, like the one at the foot. */
  .lactions { width: auto; }
}

/* Two abreast the longer label no longer fits its half: one above the other,
   both the full width. */
@media (max-width: 480px) {
  .lactions { grid-template-columns: 1fr; }
}

/* Someone who asked for less motion gets none of the lift on hover, and none
   of the pulse either — an indefinite loop is the one thing on the site that
   never stops on its own, so it is the one that matters most here. The dot
   stays put and stays visible; it is the word next to it that says a job is
   running, not the blinking. */
@media (prefers-reduced-motion: reduce) {
  .btn, .btn:hover { transition: none; transform: none; }
  .tooltip { transition: none; }
}


/* ---- keyboard use ----
   Every interactive thing on the site is a link, a button or a form control,
   and none of them said where the focus was beyond whatever the browser drew
   by default — which on a bordered control against a bordered card is close
   to nothing. `:focus-visible` rather than `:focus`, so a mouse click does not
   leave a ring behind it. */
a:focus-visible, button:focus-visible, select:focus-visible,
input:focus-visible, svg[tabindex]:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 4px;
}
/* A fixture's name opens its row, and is a button so a keyboard can open it:
   one that looks like the name it always was. */
button.fx-open { font: inherit; color: inherit; background: none; border: 0;
  padding: 0; margin: 0; text-align: left; cursor: pointer; }
button.fx-open:hover { text-decoration: underline; text-underline-offset: 3px; }
/* A column header that sorts: the header's own words, as a button, and an
   arrow drawn from the <th>'s aria-sort, so what a screen reader is told and
   what is shown cannot disagree. */
th button.sort { font: inherit; color: inherit; background: none; border: 0;
  padding: 0; margin: 0; cursor: pointer; text-align: inherit; white-space: nowrap; }
th button.sort:hover { color: var(--text-primary); }
th button.sort::after { content: "\2195"; opacity: .3; margin-left: 3px; font-size: .85em; }
th[aria-sort="ascending"] button.sort::after { content: "\2191"; opacity: 1; }
th[aria-sort="descending"] button.sort::after { content: "\2193"; opacity: 1; }
/* A chart with its points under the finger: a sideways drag walks along the
   curve, and an upward one still scrolls the page. */
.chart svg[tabindex] { touch-action: pan-y; }
/* Skipping straight to the content, for anyone who does not want to tab
   through the whole nav on every page. */
.skip { position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--surface-1); color: var(--text-primary); padding: 10px 16px;
  border: 1px solid var(--border); border-radius: 0 0 8px 0; font-size: 13px; }
.skip:focus { left: 0; }

/* The filter bars are read by eye off the control itself — a select whose
   first option says "All leagues" has told you what it filters. A screen
   reader gets nothing from that, and nothing at all once a league is picked,
   so each one carries a real <label> that simply is not painted. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* A price bought more than two days ago, counted by hub.js from the reader's
   clock: the forecast on it is as old as the price. */
time.stale { color: var(--warning); }
