/* ================================================== typefaces ==
   One face, two cuts, shipped from this origin. The content-security-policy
   sets no `font-src`, so it falls through to `default-src 'self'` and anything
   from a CDN is blocked outright.

   Chakra Petch carries the identity: the wordmark, page headings, section
   titles, and the one italic accent word that has always sat inside a heading.
   700 in both cuts — it is a technical, slightly angular face, which is the
   register a product with a half called Stargazer wants, and using one family
   for the roman and the italic means the accent word is the same voice leaning
   rather than a second typeface interrupting.

   Latin only, no latin-ext. Everything it renders is fixed English interface
   copy. Club names, the only strings here that reach outside latin-1, are set
   in Georgia and never in this.

   Licence: OFL-1.1, shipped alongside in web/fonts/. */
@font-face {
  font-family: 'Chakra Petch';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url('/fonts/chakra-petch-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Chakra Petch';
  font-style: italic;
  font-display: swap;
  font-weight: 700;
  src: url('/fonts/chakra-petch-latin-700-italic.woff2') format('woff2');
}

/* ============================================================================
   Almanac — broadcast-scoreboard design system.

   Inherited from garyqin.com/agentic: monospace body, Georgia display with an
   italic accent word, near-black ground, hairline rules, uppercase micro-labels
   at wide tracking, tabular numerals, deterministic inline SVG figures.

   Pushed sporty: --accent is re-bound per competition, so choosing a league
   re-tints the entire interface; numbers are sized like a stadium clock; and
   the ground carries a faint mown-turf rake plus a floodlight bloom.
   ========================================================================= */

:root {
  /* Ground and surfaces sit a few stops above true black. A near-black page
     reads as dramatic in a screenshot and as strain over a long session: the
     dim text tiers have nowhere to go, so labels and captions end up at
     contrast ratios that fail on anything but a good monitor in a dark room.
     Lifting the whole ramp keeps the broadcast register and buys real legibility. */
  /* Lifted a second time, by +0.06 lightness across the ramp. The first lift
     bought the dim tiers somewhere to live; this one is about the hours anyone
     actually spends here — near-black reads as dramatic for a minute and as
     strain for an evening.
     Raising a surface costs contrast for everything drawn on it, and three
     colours were sitting close enough to 4.5:1 that they would have failed:
     ink-faint (4.54), ink-ghost (4.50) and loss (4.52), all measured on
     panel-3, the lightest thing they are ever drawn on. Each was raised in
     lightness only — hue and saturation untouched — by the least that holds the
     line. Nothing on the site is below 4.5:1 after the change; the numbers are
     in almanac/../web/accessibility.html and were re-measured, not assumed. */
  /* The ground goes back to deep space while the panels stay where the last
     lift put them. Those are different jobs: readability lives on the panels,
     which are opaque and unchanged, and every contrast ratio measured in this
     file is a ratio against one of them. The ground is what the stars are drawn
     on, and stars need dark. Text on the ground only gains contrast here. */
  --bg: #0b0f17;
  --panel: #222a35;
  --panel-2: #28313e;
  --panel-3: #313b49;
  /* Hairlines are white at low alpha, so a lighter ground swallows them. */
  --line: rgba(255, 255, 255, 0.13);
  --line-strong: rgba(255, 255, 255, 0.24);
  --ink: #f5f8fb;
  --ink-body: #dde4ec;
  --ink-dim: #adb9c7;
  /* Both of these were raised to clear WCAG 2.2 AA (4.5:1) on the lightest
     surface they are ever drawn on, --panel-3. They carry small uppercase
     labels, which the spec still counts as normal-size text — "large" starts at
     24px, or 18.66px bold — so the 3:1 allowance for large text does not apply
     to them. Measured before: ink-ghost ran 3.12:1 to 4.20:1 depending on the
     surface, and failed on all four. Hue and saturation are unchanged; only
     lightness moved. */
  --ink-faint: #99a5b2;    /* 4.52:1 on panel-3, 6.59:1 on bg */
  --ink-ghost: #9ca5b0;    /* 4.55:1 on panel-3, 6.62:1 on bg */

  --accent: #00ff87;          /* rebound per competition by app.js */
  --accent-ink: #04120a;

  /* The only white-hot thing on the site: reserved for the top of the
     staking scale, so brightness reads as conviction. */
  --supernova: #fff4d6;

  --win: #22e07d;
  --draw: #ffc857;
  --loss: #ff7a90;      /* 4.56:1 on panel-3; was #ff5470, 3.65 after the lift */

  /* Three voices, and none of them the operating system's default UI face.
     Prose was briefly set in `-apple-system`, which resolves to SF Pro on a Mac
     and Segoe on Windows: perfectly legible, and the single most generic thing
     a page can be set in — it reads as an unstyled app rather than a product.

     An almanac is a published book, so the prose is a book face. Charter and
     Iowan Old Style ship with macOS and iOS, Georgia with Windows, and all
     three were drawn for reading at text sizes on screen. Display stays on the
     same serif so the page has one voice, separated by size rather than by
     family. Mono is kept wherever characters are data — figures, ratings, team
     codes, tables, form values — where fixed digit width does real work. */
  /* Prose is a book face again. It was briefly a sans; the reasoning for the
     original holds — an almanac is a published thing, and Charter, Iowan Old
     Style and Georgia were all drawn for reading at text sizes on a screen. */
  --text: Charter, 'Iowan Old Style', 'Palatino Linotype', Palatino,
          Georgia, 'Times New Roman', serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;
  /* Georgia keeps the club names and nothing else. A team name is content, not
     branding, and it wants a reading face rather than the display one. */
  --serif: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  /* The identity: wordmark, page headings, section titles. */
  --display: 'Chakra Petch', Georgia, 'Times New Roman', serif;
  /* The italic cut of the same family, for the accent word in a heading and
     the "vs" between two clubs. 700 to match the roman, so the accent reads as
     the display voice leaning rather than as a different typeface. */
  --italic: 'Chakra Petch', Georgia, 'Times New Roman', serif;

  --r: 8px;   /* was 3px: sharp corners read as a dashboard, not a product */

  /* Motion tokens lifted from garyqin.com/agentic so the two sites move the
     same way. --ease-out is a strong expo-out: fast departure, long settle,
     which is what makes the entrances feel like they land rather than slide. */
  --t-view: 220ms;
  --t-tab: 260ms;
  --t-rise: 300ms;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --wrap: 1180px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* The UA stylesheet gives [hidden] display:none, but any author `display` rule
   outranks it — which silently broke every element we hide by attribute while
   also styling as flex or grid. One global guard instead of per-selector patches. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }


body {
  font-family: var(--text);
  background: var(--bg);
  color: var(--ink-body);
  min-height: 100vh;
  font-size: 15px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The ground: a starfield and a horizon, both fixed so they stay put while
   content scrolls over them.

   This replaced a mown-turf rake and a floodlight bloom, which were the right
   metaphor while the product was only a football model. The agent is called
   Stargazer and the plays are Vesper; the reader is looking down at a planet
   rather than across a pitch.

   Drawn entirely in CSS. No image is fetched: `img-src` allows only this origin
   and `data:`, and a photograph of Earth good enough to sit behind a whole
   product costs more than every other asset here combined. 140 stars
   in three sizes so the field reads as depth rather than noise, tiled at 1100px
   so a phone gets a full sky rather than one corner of a large one, at a fixed
   scatter rather than a random one — a background that reshuffles on every
   navigation is a distraction pretending to be detail.

   The horizon lights the bottom edge, which is where a planet is when you are
   above it, and a thin bright rim sits on top of the glow the way an atmosphere
   does. Nothing readable is drawn on any of this — every panel is opaque — so
   no contrast ratio measured in this file changes. */
body::before {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    /* The starfield: two SVG tiles of diamonds, not 140 round gradient dots.
       At two pixels across a round speck reads as dust on the screen, which is
       what it was being mistaken for, and no outline rescues a mark that
       small. So the field is sparser and each mark is big enough to hold its
       shape -- fourteen four-point twinkles per tile (12-19px tall, concave
       sides) over twenty plain diamonds. Regenerate with seeds 3 and 11; the
       scatter is fixed so the sky does not reshuffle between deploys.
       Peak alpha is 0.125 and not a fraction more, which is the number the
       measurement gave back rather than one that was guessed. The heading,
       lede, kickers and footer of every view sit directly on this, and the
       binding case is the faintest of those greys over ground the accent wash
       has already lifted a little: there a 0.125 star lands around rgb(40,44,51)
       and clears 4.5:1, where 0.18 came back at 3.96:1. Size and count carry
       the field now that brightness cannot.
       A data URI, which `img-src 'self' data:` admits, and two paint layers
       where there were 140. */
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='600'%20height='600'%20viewBox='0%200%20600%20600'%3E%3Cpath%20d='M142.8,319.24Q144.11,325.19%20145.99,326.5Q144.11,327.81%20142.8,333.76Q141.49,327.81%20139.61,326.5Q141.49,325.19%20142.8,319.24Z'%20fill='white'%20opacity='0.113'/%3E%3Cpath%20d='M375.4,33.26Q376.49,38.21%20378.06,39.3Q376.49,40.39%20375.4,45.34Q374.31,40.39%20372.74,39.3Q374.31,38.21%20375.4,33.26Z'%20fill='white'%20opacity='0.12'/%3E%3Cpath%20d='M155.6,131.21Q157.29,138.91%20159.73,140.6Q157.29,142.29%20155.6,149.99Q153.91,142.29%20151.47,140.6Q153.91,138.91%20155.6,131.21Z'%20fill='white'%20opacity='0.109'/%3E%3Cpath%20d='M501.9,277.63Q503.37,284.33%20505.49,285.8Q503.37,287.27%20501.9,293.97Q500.43,287.27%20498.31,285.8Q500.43,284.33%20501.9,277.63Z'%20fill='white'%20opacity='0.1'/%3E%3Cpath%20d='M380.9,513.02Q382.3,519.4%20384.32,520.8Q382.3,522.2%20380.9,528.58Q379.5,522.2%20377.48,520.8Q379.5,519.4%20380.9,513.02Z'%20fill='white'%20opacity='0.117'/%3E%3Cpath%20d='M402.8,29.82Q404.34,36.86%20406.58,38.4Q404.34,39.94%20402.8,46.98Q401.26,39.94%20399.02,38.4Q401.26,36.86%20402.8,29.82Z'%20fill='white'%20opacity='0.113'/%3E%3Cpath%20d='M180.8,9.66Q182.41,16.99%20184.73,18.6Q182.41,20.21%20180.8,27.54Q179.19,20.21%20176.87,18.6Q179.19,16.99%20180.8,9.66Z'%20fill='white'%20opacity='0.109'/%3E%3Cpath%20d='M431.3,518.87Q432.82,525.78%20435.01,527.3Q432.82,528.82%20431.3,535.73Q429.78,528.82%20427.59,527.3Q429.78,525.78%20431.3,518.87Z'%20fill='white'%20opacity='0.123'/%3E%3Cpath%20d='M237.0,472.99Q238.35,479.15%20240.3,480.5Q238.35,481.85%20237.0,488.01Q235.65,481.85%20233.7,480.5Q235.65,479.15%20237.0,472.99Z'%20fill='white'%20opacity='0.123'/%3E%3Cpath%20d='M527.3,52.04Q528.46,57.34%20530.14,58.5Q528.46,59.66%20527.3,64.96Q526.14,59.66%20524.46,58.5Q526.14,57.34%20527.3,52.04Z'%20fill='white'%20opacity='0.102'/%3E%3Cpath%20d='M579.3,253.57Q580.76,260.24%20582.88,261.7Q580.76,263.16%20579.3,269.83Q577.84,263.16%20575.72,261.7Q577.84,260.24%20579.3,253.57Z'%20fill='white'%20opacity='0.104'/%3E%3Cpath%20d='M304.3,224.31Q305.59,230.21%20307.46,231.5Q305.59,232.79%20304.3,238.69Q303.01,232.79%20301.14,231.5Q303.01,230.21%20304.3,224.31Z'%20fill='white'%20opacity='0.113'/%3E%3Cpath%20d='M350.6,534.18Q352.1,541.0%20354.26,542.5Q352.1,544.0%20350.6,550.82Q349.1,544.0%20346.94,542.5Q349.1,541.0%20350.6,534.18Z'%20fill='white'%20opacity='0.123'/%3E%3Cpath%20d='M513.8,586.32Q515.29,593.11%20517.44,594.6Q515.29,596.09%20513.8,602.88Q512.31,596.09%20510.16,594.6Q512.31,593.11%20513.8,586.32Z'%20fill='white'%20opacity='0.1'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='410'%20height='410'%20viewBox='0%200%20410%20410'%3E%3Cpolygon%20points='185.5,224.44%20187.73,229.5%20185.5,234.56%20183.27,229.5'%20fill='white'%20opacity='0.073'/%3E%3Cpolygon%20points='208.2,237.07%20209.84,240.8%20208.2,244.53%20206.56,240.8'%20fill='white'%20opacity='0.074'/%3E%3Cpolygon%20points='258.3,321.53%20259.87,325.1%20258.3,328.67%20256.73,325.1'%20fill='white'%20opacity='0.068'/%3E%3Cpolygon%20points='37.2,327.35%2039.25,332.0%2037.2,336.65%2035.15,332.0'%20fill='white'%20opacity='0.059'/%3E%3Cpolygon%20points='402.7,391.02%20404.72,395.6%20402.7,400.18%20400.68,395.6'%20fill='white'%20opacity='0.078'/%3E%3Cpolygon%20points='64.6,1.85%2066.51,6.2%2064.6,10.55%2062.69,6.2'%20fill='white'%20opacity='0.06'/%3E%3Cpolygon%20points='78.0,95.75%2079.52,99.2%2078.0,102.65%2076.48,99.2'%20fill='white'%20opacity='0.073'/%3E%3Cpolygon%20points='180.6,341.07%20182.51,345.4%20180.6,349.73%20178.69,345.4'%20fill='white'%20opacity='0.078'/%3E%3Cpolygon%20points='204.9,267.38%20206.76,271.6%20204.9,275.82%20203.04,271.6'%20fill='white'%20opacity='0.067'/%3E%3Cpolygon%20points='409.0,403.29%20411.16,408.2%20409.0,413.11%20406.84,408.2'%20fill='white'%20opacity='0.081'/%3E%3Cpolygon%20points='129.3,90.28%20131.02,94.2%20129.3,98.12%20127.58,94.2'%20fill='white'%20opacity='0.06'/%3E%3Cpolygon%20points='314.2,159.28%20316.36,164.2%20314.2,169.12%20312.04,164.2'%20fill='white'%20opacity='0.07'/%3E%3Cpolygon%20points='392.8,344.0%20394.3,347.4%20392.8,350.8%20391.3,347.4'%20fill='white'%20opacity='0.065'/%3E%3Cpolygon%20points='373.2,187.54%20375.47,192.7%20373.2,197.86%20370.93,192.7'%20fill='white'%20opacity='0.071'/%3E%3Cpolygon%20points='29.9,253.3%2032.01,258.1%2029.9,262.9%2027.79,258.1'%20fill='white'%20opacity='0.067'/%3E%3Cpolygon%20points='35.7,131.26%2037.96,136.4%2035.7,141.54%2033.44,136.4'%20fill='white'%20opacity='0.082'/%3E%3Cpolygon%20points='48.4,97.42%2049.98,101.0%2048.4,104.58%2046.82,101.0'%20fill='white'%20opacity='0.06'/%3E%3Cpolygon%20points='326.8,68.39%20328.74,72.8%20326.8,77.21%20324.86,72.8'%20fill='white'%20opacity='0.072'/%3E%3Cpolygon%20points='78.2,296.46%2079.8,300.1%2078.2,303.74%2076.6,300.1'%20fill='white'%20opacity='0.079'/%3E%3Cpolygon%20points='47.8,168.72%2049.46,172.5%2047.8,176.28%2046.14,172.5'%20fill='white'%20opacity='0.067'/%3E%3C/svg%3E"),
    /* the lit rim of the atmosphere */
    radial-gradient(155% 44% at 50% 107%,
      rgba(224, 240, 255, 0.72) 0%,
      rgba(163, 208, 255, 0.46) 11%,
      rgba(96, 156, 232, 0.27) 26%,
      rgba(46, 92, 166, 0.13) 46%,
      transparent 66%),
    /* the glow standing off it, reaching about a third of the way up */
    radial-gradient(125% 88% at 50% 102%,
      rgba(132, 188, 255, 0.22) 0%,
      rgba(70, 124, 205, 0.10) 34%,
      rgba(40, 76, 140, 0.04) 58%,
      transparent 78%);
  background-repeat: repeat, repeat, no-repeat, no-repeat;
  background-size: 600px 600px, 410px 410px, cover, cover;
}
/* The competition's colour, washed in from above, and a vignette to keep the
   corners from competing with content. The accent half rebinds when the reader
   changes competition, which is the one thing on this page that does. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(120% 62% at 50% -14%,
      color-mix(in srgb, var(--accent) 10%, transparent) 0%, transparent 66%),
    radial-gradient(130% 80% at 50% 38%,
      transparent 38%, rgba(0, 0, 0, 0.62) 100%);
  transition: background 0.5s ease;
}

#app { position: relative; z-index: 1; }

/* Text that sits on the sky rather than on a panel gets a halo of the page
   colour behind it. The stars are near-white and the copy over them is not:
   without this, a diamond landing behind the hero paragraph takes that line's
   local contrast to 1.42:1, measured on rendered pixels. The halo is the
   background colour, so it costs nothing anywhere it is not needed -- and it
   is deliberately not applied to anything on a panel, where a --bg-coloured
   glow would read as a smudge. text-shadow inherits, so each entry here covers
   its own subtree. */
.view-head,
.foot,
.leagues,
.fx-note,
.pool-note,
.eg-more > summary,
.sg-gate {
  text-shadow: 0 0 6px var(--bg), 0 0 6px var(--bg), 0 0 14px var(--bg);
}

::selection { background: color-mix(in srgb, var(--accent) 32%, transparent); color: #fff; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }

/* ---------------------------------------------------------------- primitives */

.kicker {
  font-size: 0.64rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.kicker.on { color: var(--accent); }

.num { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }

.rule { height: 1px; background: var(--line); border: 0; }

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
}

.btn {
  font: inherit; font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-dim);
  background: transparent; border: 1px solid var(--line-strong);
  padding: 9px 16px; border-radius: var(--r); cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.btn:hover { color: var(--ink); border-color: var(--ink-faint); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn.primary {
  background: var(--accent); color: var(--accent-ink);
  border-color: var(--accent); font-weight: 800;
}
.btn.primary:hover { filter: brightness(1.12); color: var(--accent-ink); }
.btn.primary:disabled { opacity: 0.4; cursor: not-allowed; filter: none; }

select, input[type=date], input[type=number], input[type=search] {
  font: inherit; font-size: 0.82rem;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r);
  padding: 0 11px; height: 40px; width: 100%;
  transition: border-color 0.15s, background 0.15s;
}
select { padding-right: 30px; appearance: none; cursor: pointer;
  /* chevron drawn inline so it inherits the ink ramp instead of the OS gray */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-size: 5px 5px, 5px 5px;
  background-position: calc(100% - 16px) 18px, calc(100% - 11px) 18px;
  background-repeat: no-repeat;
  color: var(--ink);
}
select:hover, input:hover { border-color: var(--line-strong); background-color: var(--panel-3); }
/* Killing the native ring is only allowed if the rule that kills it puts one
   back. Each of these does, in the same declaration. */
select:focus-visible, input:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
input[type=date] { color-scheme: dark; font-variant-numeric: tabular-nums; }
input[type=date]::-webkit-calendar-picker-indicator {
  opacity: 0.45; cursor: pointer; transition: opacity 0.15s;
}
input[type=date]:hover::-webkit-calendar-picker-indicator { opacity: 0.9; }

label.field { display: block; }
label.field > span {
  display: block; margin-bottom: 6px;
  font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}

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

/* Both result panes get scrolled to the moment they render. `block: 'start'`
   puts them flush against the viewport top, which is *underneath* this sticky
   header — the first heading sits behind the tab bar. The offsets are the
   measured header: 61px, and 91px once the tabs wrap onto their own row. */
#result, #ask-out { scroll-margin-top: 76px; }
@media (max-width: 720px) { #result, #ask-out { scroll-margin-top: 104px; } }

header.top {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.top-in {
  display: flex; align-items: center; gap: 28px;
  height: 60px;
  position: relative;   /* the More menu hangs off this */
}
/* The lockup is a mark plus a word. It used to be a two-tone wordmark with a
   descriptor jammed beside it — "alm·anac  MATCH MODEL" — which read as two
   competing labels: the split fell mid-word for no reason once the name stopped
   being Modelo, and the nav already says what the site does. The mark carries
   the colour now, so the word can sit in one weight and one ink. */
.brand {
  display: flex; align-items: center; gap: 9px; flex-shrink: 0;
  text-decoration: none; color: inherit;
}
.brand-mark {
  width: 22px; height: 22px; display: block; flex-shrink: 0;
  color: var(--accent); transition: color 0.4s;
}
.brand-mark svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* The lockup keeps the wordmark and the line explaining it on one row, in both
   the desktop layout and the stacked mobile one. */
.lockup { display: flex; align-items: center; gap: 11px; min-width: 0; flex-shrink: 0; }
.brand-tag {
  font-family: var(--mono); font-size: 0.56rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); white-space: nowrap;
  padding-left: 11px; border-left: 1px solid var(--line);
}
/* One revolution a minute: present if you look at it, invisible if you don't. */
.bm-spin { transform-origin: 14px 14px; animation: bm-orbit 60s linear infinite; }
@keyframes bm-orbit { to { transform: rotate(360deg); } }
.brand b {
  font-family: var(--display); font-size: 1.15rem; font-weight: 700;
  color: var(--ink); letter-spacing: -0.005em;
}
.brand:hover .brand-mark { color: var(--ink); }
@media (prefers-reduced-motion: reduce) { .bm-spin { animation: none; } }

nav.tabs { display: flex; gap: 2px; margin-left: auto; }
nav.tabs button {
  font: inherit; font-size: 0.64rem; letter-spacing: 0.15em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-faint);
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  padding: 20px 13px 18px; cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
nav.tabs button:hover { color: var(--ink-dim); }
nav.tabs button[aria-selected=true] { color: var(--ink); border-bottom-color: var(--accent); }

/* The descriptor that follows a tab's name -- "— AI Agent", "— Sharp picks".
   It earns its room on a desktop row and cannot have it on a phone, where the
   four tabs have to fit across 390px. */
.tab-sub { font: inherit; }

.tab-more { display: inline-flex; align-items: center; gap: 6px; }
.more-chev { width: 9px; height: 6px; flex-shrink: 0; transition: transform 0.16s; }
.tab-more[aria-expanded=true] .more-chev { transform: rotate(180deg); }

.more-menu {
  position: absolute; top: 100%; right: 24px; z-index: 5;
  min-width: 200px; padding: 6px;
  display: flex; flex-direction: column;
  background: var(--panel-2); border: 1px solid var(--line-strong);
  border-radius: 11px; box-shadow: 0 16px 38px rgba(0, 0, 0, 0.52);
}
.more-menu[hidden] { display: none; }
.more-menu button {
  /* The tab row is set in --mono; `font: inherit` here picked up the body serif
     instead and the menu read as a different piece of furniture from the tabs
     it belongs to. */
  font: inherit; font-family: var(--mono);
  font-size: 0.64rem; letter-spacing: 0.15em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-dim);
  background: transparent; border: 0; border-radius: 8px;
  padding: 0 12px; min-height: 42px; text-align: left; cursor: pointer;
  transition: background 0.14s, color 0.14s;
}
.more-menu button:hover { background: var(--panel-3); color: var(--ink); }
.more-menu button[aria-current=page] { color: var(--accent); }

/* ---------------------------------------------------------------- league bar */

.leagues { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

/* The primary sport gets a bigger chip; the rest sit behind a group label. */
.league.primary {
  font-size: 0.72rem; padding: 11px 20px; letter-spacing: 0.14em;
  color: var(--ink); border-color: var(--line-strong);
}
.league.primary[aria-pressed=true] {
  color: var(--tint);
  border-color: var(--tint);
  background: color-mix(in srgb, var(--tint) 14%, var(--panel));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tint) 12%, transparent);
}
.league.primary .dot { width: 8px; height: 8px; }
.league-sep {
  font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-ghost);
  padding-left: 12px; margin-left: 6px; border-left: 1px solid var(--line-strong);
}
.league {
  --tint: var(--accent);
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-faint);
  background: var(--panel); border: 1px solid var(--line);
  padding: 8px 13px; border-radius: 100px; cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.league:hover { color: var(--ink-dim); border-color: var(--line-strong); }
.league[aria-pressed=true] {
  color: var(--tint); border-color: color-mix(in srgb, var(--tint) 55%, transparent);
  background: color-mix(in srgb, var(--tint) 9%, var(--panel));
}
.league .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--tint);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tint) 18%, transparent);
}
/* `.league.untrained` and its '·fallback' label are gone: untrained
   competitions are no longer offered in the selector at all. */

/* --------------------------------------------------------------------- tabs */

section.view { display: none; padding: 34px 0 90px; }
section.view.on { display: block; animation: riseIn var(--t-view) var(--ease-out) both; }

@keyframes rise { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
@keyframes riseIn { from { opacity: 0; transform: translate3d(0, 8px, 0); } }
@keyframes valIn { from { opacity: 0; filter: blur(4px); } to { opacity: 1; filter: blur(0); } }
@keyframes fadeIn { from { opacity: 0; } }

.view-head { margin-bottom: 22px; }
.view-head h1 {
  font-family: var(--display); font-weight: 700; font-size: clamp(1.5rem, 3vw, 2.2rem);
  color: var(--ink); letter-spacing: -0.022em; line-height: 1.08; margin: 8px 0 10px;
}
/* The accent word names the italic cut explicitly: `font-style: italic` alone
   would have the browser synthesise a slant from the roman, and a real italic
   is shipped a few kilobytes away. */
.view-head h1 em, .nf h1 em {
  font-family: var(--italic); font-style: italic; font-weight: 700;
  font-size: 0.92em;
}
.view-head h1 em { color: var(--accent); }
.view-head p { color: var(--ink-dim); font-size: 0.84rem; max-width: 68ch; line-height: 1.65; }

/* ------------------------------------------------------------------- crests */

.crest {
  position: relative; flex-shrink: 0;
  display: grid; place-items: center;
  border-radius: 4px 4px 9px 9px;
  font-weight: 800; letter-spacing: 0.02em; color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16), 0 6px 20px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.crest::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.22), transparent 52%);
}
.crest.lg { width: 74px; height: 82px; font-size: 1.42rem; }
.crest.md { width: 42px; height: 47px; font-size: 0.82rem; }
.crest.sm { width: 27px; height: 30px; font-size: 0.56rem; border-radius: 3px 3px 6px 6px; }

/* ---------------------------------------------------------------- matchup UI */

/* No overflow:hidden. It was here so the child sections' backgrounds stayed
   inside the panel's rounded corners — but it also clipped the date picker,
   which is absolutely positioned and opens downward out of the last row. The
   corners are rounded on the first and last children instead, which gets the
   same look and lets the popover escape. */
.builder { padding: 0; }
.builder > *:first-child {
  border-top-left-radius: var(--r); border-top-right-radius: var(--r);
}
.builder > *:last-child {
  border-bottom-left-radius: var(--r); border-bottom-right-radius: var(--r);
}

.matchup {
  display: grid; grid-template-columns: 1fr auto 1fr;
  gap: 20px; align-items: stretch;
  padding: 26px 26px 22px;
}
.side { display: flex; flex-direction: column; gap: 13px; min-width: 0; }
.side.away { text-align: right; }
.side-top { display: flex; align-items: center; gap: 15px; }
.side.away .side-top { flex-direction: row-reverse; }
.side-id { min-width: 0; flex: 1; }
/* Which side is at home is the single most consequential fact on this panel —
   it is worth about two and a half points before anything else is considered —
   and it was set in the quietest tier on the site, a 0.56rem ghost caption
   indistinguishable from the Elo line beneath it. It is a badge now.

   Home is filled and away is outlined, so the two are told apart by shape as
   well as by reading them: at a glance the solid one is the host. Neither uses
   the accent, which belongs to the competition and would fight the team crest
   sitting immediately beside it. */
.side-role {
  display: inline-block;
  font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 700; margin-bottom: 7px; padding: 3px 8px;
  border-radius: 4px; border: 1px solid var(--line-strong);
  color: var(--ink-dim);
}
.side.home .side-role {
  background: var(--panel-3); color: var(--ink);
  border-color: transparent;
}
.side-name {
  font-family: var(--serif); font-size: 1.5rem; line-height: 1.12;
  color: var(--ink); letter-spacing: -0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-elo {
  font-size: 0.72rem; color: var(--ink-faint); margin-top: 4px; letter-spacing: 0.05em;
}
.side-elo b { color: var(--accent); font-weight: 700; }

.vs {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; padding: 0 6px; align-self: center;
}
.vs-badge {
  width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line-strong);
  font-family: var(--italic); font-style: italic; font-weight: 700;
  font-size: 0.92rem; color: var(--ink-dim);
  background: var(--panel-2);
}
.vs-date { font-size: 0.58rem; letter-spacing: 0.1em; color: var(--ink-ghost); white-space: nowrap; }

/* form pills */
.pills { display: flex; gap: 4px; }
.side.away .pills { justify-content: flex-end; }
.pill {
  width: 19px; height: 19px; border-radius: 2px;
  display: grid; place-items: center;
  font-size: 0.56rem; font-weight: 800; letter-spacing: 0;
  background: var(--panel-3); color: var(--ink-ghost);
}
.pill.W { background: color-mix(in srgb, var(--win) 22%, var(--panel-3)); color: var(--win); }
.pill.D { background: color-mix(in srgb, var(--draw) 20%, var(--panel-3)); color: var(--draw); }
.pill.L { background: color-mix(in srgb, var(--loss) 20%, var(--panel-3)); color: var(--loss); }
.pill.empty { opacity: 0.35; }

.stakes { display: flex; gap: 5px; flex-wrap: wrap; min-height: 20px; }
.side.away .stakes { justify-content: flex-end; }
.stake {
  font-size: 0.52rem; letter-spacing: 0.11em; font-weight: 700; text-transform: uppercase;
  padding: 3px 7px; border-radius: 2px;
  border: 1px solid currentColor; opacity: 0.92;
}
.stake.danger { color: var(--loss); }
.stake.gold { color: var(--draw); }
.stake.good { color: var(--win); }
.stake.mute { color: var(--ink-ghost); }

/* Elo tug-of-war */
.tug { padding: 0 26px 20px; }
.tug-bar {
  position: relative; height: 5px; border-radius: 3px;
  background: var(--panel-3); overflow: hidden;
}
.tug-fill {
  position: absolute; inset: 0 auto 0 0; border-radius: 3px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 45%, transparent), var(--accent));
  transition: width 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.tug-mid { position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px; background: var(--line-strong); }
.tug-legend {
  display: flex; justify-content: space-between;
  font-size: 0.58rem; letter-spacing: 0.1em; color: var(--ink-ghost); margin-top: 7px;
}

/* options strip */
.opts {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 14px; padding: 20px 26px;
  border-top: 1px solid var(--line); background: var(--panel-2);
}
.opts .swap { display: flex; align-items: flex-end; }
/* Swap sides sits in a row with the date field and the venue toggle, and it was
   speaking a different language from both: JetBrains Mono, uppercase, 1.6px of
   tracking, 38px tall, against two Charter controls at 40px in sentence case.
   Three registers in one line, and the odd one two pixels short of the others.

   It keeps the button's frame — it is the only thing in the row that does
   something rather than holds a value — and takes the register of its
   neighbours: same height, same family, same size and tracking as the toggle
   beside it. The uppercase mono treatment is right for the buttons that end a
   flow, like Predict and Ask, and wrong for a control standing in a field row. */
.opts .swap button {
  width: 100%; height: 40px;
  font-family: var(--text); font-size: 0.72rem; font-weight: 400;
  letter-spacing: 0.04em; text-transform: none;
  color: var(--ink-dim);
}
.opts .swap button:hover { color: var(--ink); }
.leg { display: none; grid-column: 1 / -1; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.leg.on { display: grid; }
.toggle {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  font-size: 0.64rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ink-dim); font-weight: 700; user-select: none;
}
.toggle input { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }

/* A bare checkbox floating beside a 40px-tall input never lines up: its box is
   centerd on the label text, not on the control next to it. Giving it the same
   frame and height as an input makes it a peer of the date field instead of a
   stray tick mark. */
/* Specificity note: the caption rule `label.field > span` (0,1,2) outranks a bare
   `.toggle-box` (0,1,0), so it was forcing display:block plus the 0.6rem
   uppercase caption styling onto the control itself. Matching the same shape
   here is what keeps this a flex row. */
label.field > span.toggle-box,
.toggle-box {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  cursor: pointer; margin-bottom: 0;
  text-transform: none; font-weight: 400;
  height: 40px; padding: 0 13px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r);
  font-size: 0.72rem; letter-spacing: 0.04em; color: var(--ink-dim);
  user-select: none; transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.toggle-box:hover { border-color: var(--line-strong); color: var(--ink); }
.toggle-box > span { font: inherit; letter-spacing: inherit; text-transform: none; }
.toggle-box input { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; margin: 0; flex-shrink: 0; }
.toggle-box:has(input:checked) {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel-2));
  color: var(--accent);
}

/* game-day conditions — a distinct input class from the rest of the builder,
   because these are user assertions the model never saw, so they are boxed and
   labeled rather than mixed in with the fixture fields */
.wx {
  grid-column: 1 / -1; margin-top: 4px;
  border: 1px dashed var(--line-strong); border-radius: var(--r);
  padding: 13px 15px; background: color-mix(in srgb, var(--panel) 60%, transparent);
}
.wx-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 11px; }
.wx-head > span:first-child {
  font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-dim); font-weight: 700;
}
.wx-note { font-size: 0.58rem; color: var(--ink-ghost); letter-spacing: 0.03em; }
.wx-row { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; }
.wx-field > span {
  display: block; margin-bottom: 6px;
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.seg button {
  font: inherit; font-size: 0.66rem; letter-spacing: 0.06em; font-weight: 700;
  background: var(--panel-2); color: var(--ink-faint); border: 0;
  border-right: 1px solid var(--line); padding: 8px 13px; cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.seg button:last-child { border-right: 0; }
.seg button:hover { color: var(--ink-dim); }
.seg button[aria-pressed=true] {
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-2)); color: var(--accent);
}
.wx-out { margin-left: auto; text-align: right; }
.wx-out b { display: block; font-size: 1.05rem; font-weight: 800; color: var(--loss); letter-spacing: -0.02em; }
.wx-out i { font-style: normal; font-size: 0.56rem; letter-spacing: 0.1em; color: var(--ink-ghost); }
.wx-zero { font-size: 0.66rem; color: var(--ink-ghost); letter-spacing: 0.06em; }
.cond-tag.applied { color: var(--loss); border-style: dashed; }

.go {
  padding: 18px 26px; border-top: 1px solid var(--line);
  display: flex; align-items: center; gap: 16px; background: var(--panel-2);
}
.go .btn.primary { padding: 13px 34px; font-size: 0.74rem; letter-spacing: 0.18em; }
.go-note { font-size: 0.66rem; color: var(--ink-ghost); letter-spacing: 0.04em; }

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

#result { margin-top: 26px; }
#result[hidden] { display: none; }

/* `minmax(0, 1fr)` rather than `1fr` throughout these grids. A bare `1fr` is
   `minmax(auto, 1fr)`, and `auto` floors the track at its content's min-content
   width — so one long unbreakable label (a team name, a figure with its unit)
   pushes the track wider than its share and the whole grid past the viewport.
   Measured at 320px: the result grid wanted 299px inside a 272px column and the
   first-half pair wanted 297 inside 270. Zero lets them shrink and the text
   inside wrap or ellipsis as it already knows how. */
.res-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 18px; align-items: start; }

.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); }
.card-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 15px 18px 12px; border-bottom: 1px solid var(--line);
  /* The kicker does not shrink and the note has a minimum, so on a narrow
     screen the two together were wider than the card and pushed the page out.
     They stack instead; the note keeps its own line and its right alignment
     only while there is a kicker beside it. */
  flex-wrap: wrap;
}
.card-h .kicker { flex-shrink: 0; }
.card-h .note { font-size: 0.6rem; color: var(--ink-ghost); letter-spacing: 0.04em; text-align: right; }
/* Placed after the rule it overrides, not before it: both selectors are
   (0,2,0), so source order decides, and the earlier copy of this lost silently
   — flex-basis applied, text-align did not, and the note stayed right-aligned
   on its own full-width line. */
@media (max-width: 520px) {
  .card-h .note { text-align: left; flex-basis: 100%; }
}
.card-b { padding: 18px; }

/* outcome — three scoreboard cells */
.odds3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; background: var(--line); }
.odd {
  background: var(--panel); padding: 17px 14px 15px; text-align: center;
  position: relative; overflow: hidden;
}
.odd.lead { background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.odd.lead::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 2px; background: var(--accent);
}
.odd-k {
  font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.odd-p {
  font-size: 2.5rem; font-weight: 800; color: var(--ink);
  line-height: 1.05; margin: 7px 0 2px; letter-spacing: -0.035em;
}
.odd.lead .odd-p { color: var(--accent); }
.odd-sub { font-size: 0.62rem; color: var(--ink-faint); letter-spacing: 0.06em; }
.odd-sub b { color: var(--ink-dim); font-weight: 700; }
.odd-raw { font-size: 0.56rem; color: var(--ink-ghost); margin-top: 5px; letter-spacing: 0.05em; }

.tribar { display: flex; height: 7px; margin-top: 1px; background: var(--line); gap: 1px; }
.tribar span { display: block; transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
.tribar .h { background: var(--accent); }
.tribar .d { background: var(--ink-ghost); }
.tribar .a { background: var(--ink-faint); }

/* edge readout */
.edge { display: flex; align-items: center; gap: 14px; padding: 13px 18px; border-top: 1px solid var(--line); }
.edge-v {
  font-size: 1.15rem; font-weight: 800; letter-spacing: -0.02em; min-width: 62px;
}
.edge-v.up { color: var(--win); }
.edge-v.down { color: var(--loss); }
.edge-t { font-size: 0.66rem; color: var(--ink-faint); line-height: 1.5; }
.edge-t b { color: var(--ink-dim); font-weight: 700; }

/* ladders */
.ladder { display: flex; flex-direction: column; }
/* A dynamic NFL ladder runs 21 lines. Capping the height keeps the page
   navigable while leaving every line reachable. */
.ladder.long { max-height: 430px; overflow-y: auto; scrollbar-width: thin; }
.ladder-foot {
  padding: 9px 18px; font-size: 0.6rem; letter-spacing: 0.06em;
  color: var(--ink-ghost); border-top: 1px solid var(--line);
}
.rung {
  display: grid; grid-template-columns: 62px 1fr 66px 66px; gap: 10px; align-items: center;
  padding: 8px 18px; border-bottom: 1px solid var(--line);
}
.rung:last-child { border-bottom: 0; }
.rung.head {
  padding-top: 11px; padding-bottom: 8px;
  border-bottom-color: var(--line-strong);
  font-size: 0.55rem; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.rung.head .rung-o { text-align: right; }
.rung.trained { background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* The coin-flip line is the model's actual number; everything else is a price
   for taking a side of it. */
.rung.fair { background: color-mix(in srgb, var(--accent) 13%, transparent); }
.rung.fair .rung-l { color: var(--accent); }
.rung.fair .rung-bar i { background: var(--accent); }
.rung-l { font-size: 0.78rem; font-weight: 700; color: var(--ink-dim); }
.rung-l sup { color: var(--accent); font-size: 0.7em; }
.rung.trained .rung-l { color: var(--accent); }
.rung-o.strong {
  font-size: 0.76rem; font-weight: 700; color: var(--ink);
  text-align: right; letter-spacing: 0.01em;
}
.rung-o.strong.dim { color: var(--ink-dim); font-weight: 400; }
.rung-bar { position: relative; height: 18px; background: var(--panel-3); border-radius: 2px; overflow: hidden; }
.rung-bar i {
  position: absolute; inset: 0 auto 0 0; display: block;
  background: color-mix(in srgb, var(--accent) 68%, transparent);
  transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
/* The label sits over both the filled and unfilled part of the track, so it
   cannot take its color from either. White plus a hard shadow is what
   broadcast lower-thirds do, and it survives any fill width. */
.rung-bar u {
  position: absolute; inset: 0; display: flex; align-items: center;
  padding: 0 7px; font-size: 0.6rem; text-decoration: none; color: #fff;
  font-weight: 700; letter-spacing: 0.04em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85), 0 0 6px rgba(0, 0, 0, 0.55);
}
.rung-o { font-size: 0.7rem; color: var(--ink-faint); text-align: right; letter-spacing: 0.02em; }
.rung-o b { color: var(--ink-dim); display: block; font-weight: 700; }

/* expected-goals readout */
.xg {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: center;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
}
.xg-side { text-align: center; }
.xg-v { font-size: 1.75rem; font-weight: 800; color: var(--ink); letter-spacing: -0.03em; line-height: 1; }
.xg-side.h .xg-v { color: var(--accent); }
/* No uppercase transform here — it would render the lambda as a capital Λ. */
.xg-k { font-size: 0.54rem; letter-spacing: 0.14em; color: var(--ink-ghost); margin-top: 5px; }
.xg-mid { font-size: 0.62rem; color: var(--ink-ghost); letter-spacing: 0.1em; }

/* scoreline grid */
.scores { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--line); }
.score { background: var(--panel); padding: 11px 6px; text-align: center; }
.score b { display: block; font-size: 0.95rem; color: var(--ink); font-weight: 700; letter-spacing: 0.02em; }
.score i {
  display: block; font-style: normal; font-size: 0.6rem; color: var(--ink-faint); margin-top: 3px;
}
.score.top { background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.score.top b { color: var(--accent); }

/* venue conditions strip — NFL only, since every soccer venue is open air */
.conds {
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
  padding: 12px 18px; border-bottom: 1px solid var(--line); background: var(--panel-2);
}
.cond-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.cond-dot.t0 { background: var(--ink-ghost); }            /* roofed */
.cond-dot.t1 { background: #59c9ff; }                     /* mild open air */
.cond-dot.t2 { background: #7aa7ff; }                     /* cold open air */
.cond-dot.t3 { background: #b8e0ff; box-shadow: 0 0 8px #b8e0ff88; }  /* harsh */
.cond-label {
  font-size: 0.68rem; letter-spacing: 0.06em; color: var(--ink-dim); font-weight: 700;
}
.cond-meter { display: inline-flex; gap: 3px; }
.cond-meter i { width: 14px; height: 3px; border-radius: 2px; background: var(--panel-3); }
.cond-meter i.on { background: #b8e0ff; }
.cond-tag {
  font-size: 0.55rem; letter-spacing: 0.11em; font-weight: 700; text-transform: uppercase;
  padding: 3px 7px; border-radius: 2px; border: 1px solid currentColor;
}
.cond-tag.good { color: var(--win); }
.cond-tag.danger { color: var(--loss); }

/* first half — its own card, marked as a distinct market rather than a variant
   of the full-game ladders it sits beneath */
.card.half { border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
.half-top {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--line); border-bottom: 1px solid var(--line);
}
.half-stat { background: var(--panel-2); padding: 15px 16px; text-align: center; }
.half-v { font-size: 1.5rem; font-weight: 800; color: var(--accent); letter-spacing: -0.03em; line-height: 1.1; }
.half-k {
  font-size: 0.56rem; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-faint); margin-top: 5px;
}
.half-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line); }
.half-cols > div { background: var(--panel); }
.half-h {
  font-size: 0.58rem; letter-spacing: 0.15em; text-transform: uppercase; font-weight: 700;
  color: var(--ink-faint); padding: 13px 18px 9px;
}

/* SHAP */
.shap { display: flex; flex-direction: column; gap: 7px; padding: 16px 18px; }
.shap-row { display: grid; grid-template-columns: 210px 1fr; gap: 11px; align-items: center; }
.shap-f { font-size: 0.63rem; color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shap-f b { color: var(--ink-ghost); font-weight: 400; }
.shap-track { position: relative; height: 15px; background: var(--panel-3); border-radius: 2px; }
.shap-track::before { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line-strong); }
.shap-track i {
  position: absolute; top: 2px; bottom: 2px; display: block; border-radius: 1px;
  transition: width 0.6s ease, left 0.6s ease;
}
.shap-track i.pos { background: var(--win); }
.shap-track i.neg { background: var(--loss); }
.shap-legend {
  display: flex; justify-content: space-between; padding: 0 18px 15px;
  font-size: 0.58rem; color: var(--ink-ghost); letter-spacing: 0.06em;
}

/* ------------------------------------------------------------------ the game */

.scoreboard {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 0;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--panel); overflow: hidden; margin-bottom: 22px;
}
.sb-side { padding: 18px 22px; }
.sb-side.model { text-align: right; background: var(--panel-2); }
.sb-k { font-size: 0.58rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); font-weight: 700; }
.sb-v { font-size: 2.6rem; font-weight: 800; color: var(--ink); letter-spacing: -0.04em; line-height: 1.1; }
.sb-side.you .sb-v { color: var(--accent); }
.sb-sub { font-size: 0.62rem; color: var(--ink-ghost); letter-spacing: 0.05em; }
/* Accuracy meter — gives the wide scoreboard cells something to say and makes
   the you-vs-model gap readable at a glance rather than as two bare integers. */
.sb-meter { height: 4px; background: var(--panel-3); border-radius: 2px; margin-top: 11px; overflow: hidden; }
.sb-meter i { display: block; height: 100%; transition: width 0.5s ease; }
.sb-side.you .sb-meter i { background: var(--accent); }
.sb-side.model .sb-meter i { background: var(--ink-faint); margin-left: auto; }
.sb-mid {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 26px; border-left: 1px solid var(--line); border-right: 1px solid var(--line);
}
.sb-streak { font-size: 1.5rem; font-weight: 800; color: var(--draw); letter-spacing: -0.02em; }
.sb-streak.cold { color: var(--ink-ghost); }

.fixture-card { position: relative; overflow: hidden; }
.fx-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 20px; border-bottom: 1px solid var(--line); background: var(--panel-2);
}
.fx-meta .kicker { color: var(--ink-faint); }
.fx-teams {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 18px;
  align-items: center; padding: 30px 24px 26px;
}
.fx-team { display: flex; flex-direction: column; align-items: center; gap: 11px; text-align: center; }
.fx-name { font-family: var(--serif); font-size: 1.22rem; color: var(--ink); line-height: 1.2; }
.fx-elo { font-size: 0.62rem; color: var(--ink-ghost); letter-spacing: 0.08em; }
.fx-vs { font-family: var(--italic); font-style: italic; font-weight: 700; font-size: 1.05rem; color: var(--ink-ghost); }

.picks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 0 24px 24px; }
.pick {
  font: inherit; cursor: pointer; text-align: center;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 10px; color: var(--ink-dim);
  transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.12s;
}
.pick:hover:not(:disabled) {
  border-color: var(--accent); color: var(--ink); transform: translateY(-2px);
  background: color-mix(in srgb, var(--accent) 8%, var(--panel-2));
}
.pick:disabled { cursor: default; }
.pick b { display: block; font-size: 0.92rem; font-weight: 800; letter-spacing: 0.04em; }
/* Inherit the pick's color at low opacity — a fixed ghost gray disappears once
   the button turns red or green on reveal. */
.pick i {
  display: block; font-style: normal; font-size: 0.58rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: currentColor; opacity: 0.5; margin-top: 5px;
}
.pick.chosen { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, var(--panel-2)); color: var(--ink); }
.pick.correct { border-color: var(--win); background: color-mix(in srgb, var(--win) 15%, var(--panel-2)); color: var(--win); }
.pick.wrong { border-color: var(--loss); background: color-mix(in srgb, var(--loss) 12%, var(--panel-2)); color: var(--loss); }
.pick .modelflag {
  display: inline-block; margin-top: 7px; font-size: 0.5rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-faint); border: 1px solid var(--line-strong);
  border-radius: 2px; padding: 2px 5px;
}

.reveal { border-top: 1px solid var(--line); animation: rise 0.4s ease both; }
.reveal-top {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line);
}
.rv { background: var(--panel-2); padding: 17px 20px; }
.rv-k { font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); font-weight: 700; }
.rv-v { font-size: 1.85rem; font-weight: 800; color: var(--ink); letter-spacing: -0.03em; margin-top: 3px; }
.rv-sub { font-size: 0.64rem; color: var(--ink-ghost); letter-spacing: 0.05em; margin-top: 2px; }
.verdict {
  padding: 15px 20px; font-size: 0.76rem; letter-spacing: 0.06em; font-weight: 700;
  display: flex; align-items: center; gap: 11px;
}
.verdict.beat { color: var(--win); background: color-mix(in srgb, var(--win) 10%, transparent); }
.verdict.lost { color: var(--loss); background: color-mix(in srgb, var(--loss) 9%, transparent); }
.verdict.tie { color: var(--draw); background: color-mix(in srgb, var(--draw) 8%, transparent); }
.verdict span { font-weight: 400; color: var(--ink-faint); letter-spacing: 0.03em; }

.game-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 16px 20px; border-top: 1px solid var(--line);
}

/* --------------------------------------------------------------- rankings */

.rank-tools { display: flex; gap: 12px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.rank-tools input[type=search] { max-width: 260px; }

.pool-note {
  font-size: 0.7rem; color: var(--ink-faint); line-height: 1.6;
  margin-bottom: 12px; max-width: 78ch;
}
.pool-note:empty { display: none; }

table.board { width: 100%; border-collapse: collapse; }
table.board th {
  font-size: 0.56rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700; text-align: left;
  padding: 11px 14px; border-bottom: 1px solid var(--line-strong);
}
table.board th.r, table.board td.r { text-align: right; }
table.board td { padding: 9px 14px; border-bottom: 1px solid var(--line); font-size: 0.8rem; }
table.board tr:hover td { background: var(--panel-2); }
.rk { font-size: 0.72rem; color: var(--ink-ghost); font-weight: 700; width: 46px; }
.rk.medal { color: var(--draw); }
.team-cell { display: flex; align-items: center; gap: 11px; }
.team-cell b { font-weight: 400; color: var(--ink); font-size: 0.85rem; }
.elo-cell { display: flex; align-items: center; gap: 10px; justify-content: flex-end; }
.elo-bar { width: 88px; height: 4px; background: var(--panel-3); border-radius: 2px; overflow: hidden; }
.elo-bar i { display: block; height: 100%; background: var(--accent); }
.elo-n { font-weight: 700; color: var(--ink); min-width: 52px; text-align: right; }
.comp-tag {
  font-size: 0.54rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700;
  padding: 3px 6px; border-radius: 2px; border: 1px solid currentColor;
}

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

.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin: 22px 0 30px; }
.stat b {
  display: block; font-size: 2rem; font-weight: 800; color: var(--ink);
  letter-spacing: -0.035em; line-height: 1.1;
}
.stat i {
  display: block; font-style: normal; font-size: 0.6rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-faint); margin-top: 5px; line-height: 1.4;
}

.mc-section { margin-bottom: 34px; }
.mc-section > h2 {
  font-family: var(--display); font-weight: 700; font-size: 1.2rem; color: var(--ink);
  letter-spacing: -0.02em; margin: 10px 0 6px;
}
.mc-section > p {
  color: var(--ink-dim); font-size: 0.8rem; line-height: 1.7; max-width: 76ch; margin-bottom: 16px;
}

.verdict-tag {
  font-size: 0.54rem; letter-spacing: 0.1em; font-weight: 800; text-transform: uppercase;
  padding: 3px 7px; border-radius: 2px;
}
.verdict-tag.beats { color: var(--win); background: color-mix(in srgb, var(--win) 16%, transparent); }
.verdict-tag.under { color: var(--loss); background: color-mix(in srgb, var(--loss) 14%, transparent); }
.verdict-tag.level { color: var(--ink-faint); background: var(--panel-3); }

.note-card {
  border-left: 2px solid var(--accent); background: var(--panel);
  padding: 15px 18px; border-radius: 0 var(--r) var(--r) 0; margin-bottom: 12px;
}
.note-card h3 { font-size: 0.8rem; color: var(--ink); font-weight: 700; margin-bottom: 6px; letter-spacing: 0.01em; }
.note-card p { font-size: 0.76rem; color: var(--ink-dim); line-height: 1.7; }
.note-card.warn { border-left-color: var(--loss); }
.note-card.warn h3 { color: var(--loss); }

.rationale { width: 100%; border-collapse: collapse; }
.rationale td { padding: 12px 0; border-bottom: 1px solid var(--line); vertical-align: top; font-size: 0.78rem; }
.rationale td:first-child { width: 34%; padding-right: 22px; color: var(--ink); font-weight: 700; }
.rationale td:last-child { color: var(--ink-dim); line-height: 1.65; }

.fig { width: 100%; height: auto; display: block; }
.fig-axis { stroke: var(--line-strong); stroke-width: 1; }
.fig-grid { stroke: var(--line); stroke-width: 1; }
.fig-ideal { stroke: var(--ink-ghost); stroke-width: 1; stroke-dasharray: 3 3; fill: none; }
.fig-raw { stroke: var(--ink-faint); stroke-width: 1.6; fill: none; }
.fig-cal { stroke: var(--accent); stroke-width: 1.8; fill: none; }
.fig-t { fill: var(--ink-ghost); font-size: 9px; font-family: var(--mono); letter-spacing: 0.06em; }
.fig-ax { fill: var(--ink-faint); font-size: 9.5px; font-family: var(--mono);
  letter-spacing: 0.1em; text-transform: uppercase; }
.ideal-lab { fill: var(--ink-ghost); font-size: 8.5px; letter-spacing: 0.12em; }
.fig-dot-raw { fill: var(--ink-faint); }
.fig-dot-cal { fill: var(--accent); }

/* ------------------------------------------------------------------ states */

.empty {
  padding: 60px 20px; text-align: center; color: var(--ink-ghost);
  font-size: 0.78rem; letter-spacing: 0.05em;
}
.spinner {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid var(--line-strong); border-top-color: var(--accent);
  animation: spin 0.7s linear infinite; display: inline-block; vertical-align: -3px;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--panel-3); border: 1px solid var(--loss); color: var(--loss);
  padding: 11px 18px; border-radius: var(--r); font-size: 0.72rem; letter-spacing: 0.05em;
  z-index: 90; animation: rise 0.25s ease both; max-width: 90vw;
}

footer.foot {
  border-top: 1px solid var(--line); padding: 26px 0 40px;
  font-size: 0.66rem; color: var(--ink-ghost); letter-spacing: 0.05em;
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}

/* ------------------------------------------------------------------ mobile */

@media (max-width: 940px) {
  .res-grid { grid-template-columns: minmax(0, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .opts, .leg.on { grid-template-columns: repeat(2, 1fr); }
}

/* Two columns still gives the date about 160px on a phone, which is less than
   the date needs — so it wraps, and a 40px button cannot hold four lines. The
   date takes the row; venue pairs with swap sides on the next one. */
@media (max-width: 620px) {
  .opts .date-field-wrap { grid-column: 1 / -1; }
}

@media (max-width: 720px) {
  /* padding: 12px 0 0 used to sit here, which threw away .wrap's 24px and left
     the mark and wordmark hard against the left edge of the screen. */
  .top-in { height: auto; flex-direction: column; align-items: stretch; gap: 0; padding: 12px 24px 0; }
  .tab-sub { display: none; }
  nav.tabs { margin-left: 0; overflow-x: auto; }
  nav.tabs button { padding: 13px 11px; flex: 1; white-space: nowrap; }
  /* Two columns, not one. Stacking the sides put the whole of the home team,
     then a 46px circle floating in its own row, then the whole of the away
     team -- about 500px of panel before a single number, and the reader had to
     scroll past the fixture to reach the thing they came to press. Side by side
     the panel is half as tall, the two team selects land on one row where they
     read as the pair they are, and "vs" stops needing a row of its own.

     `display: contents` is what makes that possible without touching the
     markup: each .side stops generating a box and its four children join the
     parent grid directly, so home and away can interleave row by row. Inherited
     properties still reach them, which is why the away column stays right
     aligned below. */
  .matchup { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
             gap: 9px 12px; padding: 16px; align-items: start; }
  .side { display: contents; }
  .side.home > .side-top { grid-area: 2 / 1; }
  .side.away > .side-top { grid-area: 2 / 2; }
  /* `.sel` and not `select`: the visible control is a custom button and the
     native select is deliberately hidden at 1px beside it, so the grid item to
     place is the wrapper. */
  .side.home > .sel, .side.home > select { grid-area: 3 / 1; }
  .side.away > .sel, .side.away > select { grid-area: 3 / 2; }
  .side.home > .pills    { grid-area: 4 / 1; }
  .side.away > .pills    { grid-area: 4 / 2; }
  .side.home > .stakes   { grid-area: 5 / 1; }
  .side.away > .stakes   { grid-area: 5 / 2; }
  .side-name { white-space: normal; }
  .side-role { margin-bottom: 5px; }

  /* A 148px column cannot hold a crest and "Elo 1633 · 283 matches" on one
     line, and letting it wrap broke "283" away from "matches". So the crest
     keeps the badge and the club name company, and the Elo line drops beneath
     both and takes the whole column, where it fits. `.side-id` goes to
     `contents` for the same reason `.side` did: its three children need to be
     placed individually. */
  .side-top { display: grid; grid-template-columns: auto minmax(0, 1fr);
              gap: 2px 9px; align-items: center; }
  .side-id { display: contents; }
  .side-top > .crest    { grid-area: 1 / 1 / 3 / 2; }
  /* A grid item stretches unless told otherwise, and a stretched badge is a
     wide empty box with a word in the corner rather than a chip. */
  .side-top .side-role  { grid-area: 1 / 2; justify-self: start; }
  .side-top .side-name  { grid-area: 2 / 2; }
  .side-top .side-elo   { grid-area: 3 / 1 / auto / -1; margin-top: 3px; }
  .side.away .side-top  { grid-template-columns: minmax(0, 1fr) auto; }
  .side.away .side-top > .crest   { grid-area: 1 / 2 / 3 / 3; }
  .side.away .side-top .side-role { grid-area: 1 / 1; justify-self: end; }
  .side.away .side-top .side-name { grid-area: 2 / 1; }

  /* The fixture header rather than a divider: with the sides beside each other
     the relationship is already on screen, so this is one slim centred line
     instead of a circle with 60px of air above and below it. */
  .vs { grid-area: 1 / 1 / auto / -1;
        flex-direction: row; justify-content: center; align-items: center;
        gap: 9px; padding: 0 0 3px; align-self: start; }
  .vs-badge { width: auto; height: 22px; padding: 0 10px; border-radius: 11px;
              font-size: 0.72rem; }
  .odds3 { grid-template-columns: minmax(0, 1fr); }
  .odd-p { font-size: 2rem; }
  .scores { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shap-row { grid-template-columns: 118px 1fr; }
  /* Side-by-side first-half ladders squeeze the bar track to nothing at this
     width — the probability bar is the point of the row, so stack instead. */
  .half-cols { grid-template-columns: minmax(0, 1fr); }
  .half-v { font-size: 1.05rem; }
  .half-stat { padding: 13px 8px; }
  .shap-legend { flex-direction: column; gap: 4px; }
  .scoreboard { grid-template-columns: 1fr; }
  .sb-side.model { text-align: left; }
  .sb-mid { border: 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 14px; }
  .fx-teams { padding: 22px 16px; gap: 10px; }
  .picks { padding: 0 16px 18px; }
  .stats { grid-template-columns: 1fr 1fr; }
  .rationale td:first-child { width: 42%; }
  table.board .hide-sm { display: none; }
}

/* Reduced motion, named rather than blanket. A global
   `*, *::before, *::after { animation-duration: 0.01ms !important }` was here,
   and it also stopped the two animations on this site that carry information:
   the spinner and the scanning bar under a busy button both mean "a request is
   in flight", and someone who has asked for less motion still needs to know the
   app is working. Those two stay. Everything named below is decoration. */
@media (prefers-reduced-motion: reduce) {
  .bm-spin { animation: none; }                    /* rotating brand ring */
  .sg-dot { animation: none; }                     /* pulsing in-development dot */
  .askbox.on::before { animation: none; opacity: 1; }   /* sweeping input glow */
  .askbox.on.blank textarea::placeholder { animation: none; }
  /* Entry slides become fades rather than nothing: the arrival is still
     legible as an arrival, which is information, without travel. */
  section.view.on, .reveal, .toast, .datepop,
  .ask-res > * { animation: fadeIn 200ms ease both; }
  .pick:hover:not(:disabled) { transform: none; }  /* hover lift */
  /* The thinking indicator stays, on the same rule as the spinner and the
     scanning bar: it is how the page says a request is in flight, and someone
     who asked for less motion still needs to know the agent is working. It
     loses the travel and keeps the pulse. */
  .think-bar { animation: none; width: 100%; opacity: 0.5; }
  .think-dots i { animation: thinkFade 1.4s ease-in-out infinite; transform: none; }
  @keyframes thinkFade { 0%, 100% { opacity: 0.3; } 40% { opacity: 1; } }
}

/* compact selects inside the game-day inputs box */
select.mini { font-size: 0.66rem; padding: 7px 9px; width: auto; min-width: 148px; }

/* grouped SHAP: the group label carries the meaning, the inputs beneath it are
   there to be sanity-checked, not to be read as individually signed */
.shap-row .shap-f { display: flex; flex-direction: column; gap: 2px; }
.shap-row .shap-f b {
  font-weight: 400; font-size: 0.55rem; color: var(--ink-ghost);
  letter-spacing: 0.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.shap.raw { border-top: 1px solid var(--line); padding-top: 14px; }
.shap-foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 0 18px 14px; font-size: 0.58rem; color: var(--ink-ghost); flex-wrap: wrap;
}
.linky {
  font: inherit; font-size: 0.58rem; letter-spacing: 0.06em; background: none;
  border: 0; border-bottom: 1px dashed var(--ink-faint); color: var(--ink-dim);
  padding: 0 0 1px; cursor: pointer;
}
.linky:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* opponent-adjusted efficiency block in the context card */
.eff { border-bottom: 1px solid var(--line); }
.eff-h {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 12px 18px 8px;
  font-size: 0.58rem; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.eff-h span { text-transform: none; letter-spacing: 0.03em; color: var(--ink-ghost); font-weight: 400; }
.eff-side {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 8px 18px; border-top: 1px solid var(--line);
}
.eff-nums { display: flex; gap: 18px; }
.eff-n {
  display: flex; flex-direction: column; align-items: flex-end;
  font-size: 0.82rem; font-weight: 700; font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em; min-width: 46px;
}
.eff-n i {
  font-style: normal; font-size: 0.5rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-ghost); font-weight: 700; margin-top: 2px;
}
.eff-n.up { color: var(--win); }
.eff-n.down { color: var(--loss); }
.eff-n.vol { color: var(--ink-dim); }
@media (max-width: 720px) {
  .eff-side { flex-direction: column; align-items: flex-start; gap: 8px; }
  .eff-nums { gap: 14px; }
}

/* The raw-input list is the full feature set, so it scrolls in place rather
   than adding two screens of height when opened. */
.shap.raw { max-height: 340px; overflow-y: auto; scrollbar-width: thin; }

/* ------------------------------------------------------------- date picker */
/* Rendered rather than native: Chrome's calendar popup is in a closed shadow
   root with no CSS hooks, so a themed field with an unthemeable gray panel
   hanging off it was the one control that could never match the page. */
.field.date-field-wrap > span {
  display: block; margin-bottom: 6px;
  font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700;
}
.datefield { position: relative; }
.date-btn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; height: 40px; padding: 0 11px; cursor: pointer;
  font: inherit; font-size: 0.78rem; font-variant-numeric: tabular-nums;
  color: var(--ink); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color 0.15s, background 0.15s;
}
.date-btn:hover { border-color: var(--line-strong); background: var(--panel-3); }
.date-btn[aria-expanded=true] { border-color: var(--accent); }

/* The date control overflowed the page by 38px at 320px whenever the date was a
   long one — a grid item and a flex row both default to a min-content floor, so
   the button refused to shrink and pushed straight out of the panel. The label
   is the part that can give: it truncates, and the week badge and the calendar
   icon keep their size because neither is legible at a fraction of it. */
.opts .field { min-width: 0; }
.datefield, .date-btn { min-width: 0; }
#date-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.date-hint, .date-ico { flex-shrink: 0; }
.date-btn .date-ico { width: 15px; height: 15px; color: var(--ink-faint); flex-shrink: 0; }
.date-btn:hover .date-ico { color: var(--ink-dim); }
/* The week the date lands in, which is the thing the date actually decides.
   Sits before the icon so the icon stays rightmost, as a field affordance should. */
.date-hint {
  font-size: 0.56rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--accent); font-weight: 700; margin-left: auto; white-space: nowrap;
}
.date-hint:empty { display: none; }
/* The button is a fixed 40px, so a wrapping label does not grow it — it spills
   out of it, over the caption above and the field below. Clipping is the only
   behaviour that keeps the control the size it says it is. */
.date-btn #date-label {
  margin-right: auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.datepop {
  position: absolute; z-index: 50; top: calc(100% + 6px); left: 0;
  width: 268px; padding: 12px 12px 4px;
  background: var(--panel-2); border: 1px solid var(--line-strong);
  border-radius: var(--r); box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
  animation: rise 0.14s ease both;
}
.dp-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dp-title {
  font-size: 0.72rem; letter-spacing: 0.08em; color: var(--ink); font-weight: 700;
}
.dp-nav {
  font: inherit; font-size: 1rem; line-height: 1; width: 26px; height: 26px;
  color: var(--ink-dim); background: transparent; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r);
  transition: color 0.15s, border-color 0.15s;
}
.dp-nav:hover { color: var(--accent); border-color: var(--accent); }
.dp-dow, .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-dow { margin: 11px 0 4px; }
.dp-dow span {
  text-align: center; font-size: 0.54rem; letter-spacing: 0.08em;
  color: var(--ink-ghost); font-weight: 700;
}
.dp-day {
  font: inherit; font-size: 0.72rem; font-variant-numeric: tabular-nums;
  height: 30px; cursor: pointer; color: var(--ink-dim);
  background: transparent; border: 1px solid transparent; border-radius: var(--r);
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.dp-day:hover { background: var(--panel-3); color: var(--ink); }
.dp-day.today { color: var(--ink); border-color: var(--line-strong); }
.dp-day.on {
  background: var(--accent); color: var(--accent-ink); font-weight: 800;
  border-color: var(--accent);
}
.dp-pad { height: 30px; }
.dp-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 10px; padding: 11px 0 12px; border-top: 1px solid var(--line);
}
.dp-hint {
  font-size: 0.56rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--accent); font-weight: 700;
}

/* explanatory copy above a dense table — the table is the evidence, this is the
   part that makes it readable without prior knowledge of the vocabulary */
.legend {
  margin-bottom: 14px; padding: 13px 16px;
  background: var(--panel); border: 1px solid var(--line);
  border-left: 2px solid var(--accent); border-radius: 0 var(--r) var(--r) 0;
}
.legend p { font-size: 0.76rem; line-height: 1.7; color: var(--ink-dim); margin: 0; }
.legend b { color: var(--ink); font-weight: 700; }
.legend ul { margin: 9px 0 0; padding-left: 18px; }
.legend li { font-size: 0.75rem; line-height: 1.7; color: var(--ink-dim); margin-bottom: 5px; }
.legend li:last-child { margin-bottom: 0; }
.legend .verdict-tag { margin: 0 1px; }

.bl-how {
  display: block; font-style: normal; font-size: 0.62rem; color: var(--ink-faint);
  margin-top: 2px; letter-spacing: 0.01em;
}
.bl-floor {
  display: inline-block; margin-left: 7px; padding: 2px 6px; border-radius: 2px;
  font-size: 0.5rem; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700;
  color: var(--loss); background: color-mix(in srgb, var(--loss) 14%, transparent);
}

/* fixture-level uncertainty — a confidence read on the price above it */
.unc {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 18px; border-top: 1px solid var(--line); background: var(--panel-2);
}
.unc-meter { display: inline-flex; gap: 3px; flex-shrink: 0; }
.unc-meter i { width: 12px; height: 4px; border-radius: 2px; background: var(--panel-3); }
.unc.low .unc-meter i.on { background: var(--win); }
.unc.mid .unc-meter i.on { background: var(--draw); }
.unc.high .unc-meter i.on { background: var(--loss); }
.unc-t { font-size: 0.66rem; color: var(--ink-faint); line-height: 1.5; }
.unc-t b { color: var(--ink-dim); font-weight: 700; }
.unc.low .unc-t b { color: var(--win); }
.unc.mid .unc-t b { color: var(--draw); }
.unc.high .unc-t b { color: var(--loss); }
.unc-note { display: block; font-size: 0.56rem; color: var(--ink-ghost); letter-spacing: 0.04em; }

/* model versus the market — the one benchmark the project did not choose */
.vs-market {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r);
  margin-bottom: 14px; overflow: hidden;
}
.vs-side { background: var(--panel); padding: 18px 20px; }
.vs-side.ours { background: var(--panel-2); text-align: right; }
.vs-k { font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700; }
.vs-v { font-size: 2.4rem; font-weight: 800; letter-spacing: -0.04em; line-height: 1.1;
  color: var(--ink); }
.vs-side.ours .vs-v { color: var(--accent); }
.vs-s { font-size: 0.62rem; color: var(--ink-ghost); letter-spacing: 0.05em; }
.vs-mid { display: grid; place-items: center; padding: 0 20px; background: var(--panel);
  font-family: var(--italic); font-style: italic; font-weight: 700; color: var(--ink-ghost); }
.mc-fine { font-size: 0.62rem; color: var(--ink-ghost); margin-top: 10px; line-height: 1.6; }
@media (max-width: 720px) {
  .vs-market { grid-template-columns: 1fr; }
  .vs-side.ours { text-align: left; }
  .vs-mid { padding: 8px; }
}

/* ------------------------------------------------------- glossary terms --
   A term you can click. The panel is position:fixed and placed by script so
   it escapes the horizontal scroll containers the tables live in — an absolute
   panel inside .panel{overflow-x:auto} gets clipped at the table edge. */

.term-wrap { position: relative; display: inline; }
.term {
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: help; text-decoration: underline; text-decoration-style: dotted;
  text-decoration-color: var(--accent); text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.term:hover { color: var(--ink); text-decoration-style: solid; }
.term:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.term-pop {
  position: fixed; z-index: 90; width: min(340px, calc(100vw - 32px));
  background: var(--panel-3); border: 1px solid var(--line-strong);
  border-top: 2px solid var(--accent);
  border-radius: var(--r); padding: 13px 15px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
  display: block; text-align: left; text-transform: none; letter-spacing: 0;
}
.term-pop b {
  display: block; font-size: 0.72rem; font-weight: 700; color: var(--ink);
  margin-bottom: 5px; letter-spacing: 0.01em;
}
.term-pop > span {
  display: block; font-size: 0.72rem; line-height: 1.65; color: var(--ink-dim);
  font-family: inherit; font-weight: 400;
}

/* ------------------------------------------------- performance strips --
   The headline visual. A column of percentages tells you the values but not
   the thing you want, which is whether the model cleared the bar. */

.ps-key {
  display: flex; flex-wrap: wrap; gap: 8px 20px; margin-bottom: 14px;
  font-size: 0.66rem; color: var(--ink-faint); letter-spacing: 0.03em;
}
.ps-key span { display: inline-flex; align-items: center; gap: 7px; }
.ps-key i { display: inline-block; }
.k-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); }
.k-base { width: 2px; height: 13px; background: var(--ink-faint); }
.k-ref { width: 2px; height: 15px; background: var(--draw); }
.k-gap { width: 16px; height: 7px; border-radius: 1px; }
.k-gap.up { background: color-mix(in srgb, var(--win) 42%, transparent); }
.k-gap.down { background: color-mix(in srgb, var(--loss) 46%, transparent); }
.k-gap.level { background: color-mix(in srgb, var(--ink-faint) 40%, transparent); }

.ps { border-top: 1px solid var(--line); }
.ps-row {
  display: grid; grid-template-columns: 150px 1fr 62px; gap: 14px;
  align-items: center; padding: 6px 0; border-bottom: 1px solid var(--line);
}
.ps-label b {
  display: block; font-size: 0.76rem; font-weight: 700; color: var(--ink);
  line-height: 1.3;
}
.ps-label i {
  display: block; font-size: 0.62rem; color: var(--ink-ghost); font-style: normal;
  letter-spacing: 0.04em; margin-top: 2px;
}
.ps-chart { min-width: 0; }
.ps-svg { width: 100%; height: auto; display: block; overflow: visible; }
.ps-grid { stroke: var(--line); stroke-width: 1; }
.ps-tick { fill: var(--ink-ghost); font-size: 8px; font-family: var(--mono); }
.ps-track { stroke: var(--line-strong); stroke-width: 1; }
.ps-gap.up { fill: color-mix(in srgb, var(--win) 34%, transparent); }
.ps-gap.down { fill: color-mix(in srgb, var(--loss) 40%, transparent); }
.ps-gap.level { fill: color-mix(in srgb, var(--ink-faint) 34%, transparent); }
.ps-base { stroke: var(--ink-faint); stroke-width: 2; }
.ps-ref { stroke: var(--draw); stroke-width: 2; stroke-dasharray: 3 2; }
.ps-dot { fill: var(--accent); stroke: var(--bg); stroke-width: 1.5; }
.ps-verdict { text-align: right; }
.ps-verdict b {
  display: block; font-family: var(--mono); font-size: 0.85rem; font-weight: 700;
  letter-spacing: -0.02em;
}
.ps-verdict i {
  display: block; font-size: 0.56rem; font-style: normal; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-ghost); margin-top: 1px;
}
.ps-verdict.up b { color: var(--win); }
.ps-verdict.down b { color: var(--loss); }
.ps-verdict.level b { color: var(--ink-faint); }
.ps-foot {
  font-size: 0.7rem; color: var(--ink-faint); line-height: 1.7; margin-top: 12px;
}

/* ------------------------------------------------------------ disclosure --
   Detail that would otherwise be a wall of numbers. The chart above is the
   answer; this is the audit trail, and it stays shut until asked for. */

.disc { margin-top: 16px; }
.disc-btn {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  padding: 9px 14px; font-size: 0.68rem; letter-spacing: 0.08em;
  text-transform: uppercase; font-weight: 700; color: var(--ink-dim);
  font-family: inherit;
}
.disc-btn:hover { border-color: var(--accent); color: var(--ink); }
.disc-caret { font-style: normal; transition: transform 0.18s ease; color: var(--accent); }
.disc-btn[aria-expanded="true"] .disc-caret { transform: rotate(90deg); }
.disc-body { margin-top: 14px; }

/* ------------------------------------------------------- how to read this */

.mc-howto {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px 24px; margin-bottom: 34px;
}
.mc-howto h2 {
  font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 16px;
}
.howto-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.howto-grid b {
  display: block; font-size: 0.78rem; color: var(--ink); font-weight: 700;
  margin-bottom: 6px;
}
.howto-grid p { font-size: 0.73rem; line-height: 1.7; color: var(--ink-dim); }

/* --------------------------------------------------------- the inventory --
   Two columns because a limits section that only lists what is missing is
   half an answer. */

.inv { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.inv-col { min-width: 0; }
.inv-h {
  font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; padding-bottom: 9px; margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.inv-h.in { color: var(--win); }
.inv-h.out { color: var(--loss); }
.inv-item {
  background: var(--panel); border-radius: var(--r); padding: 12px 14px;
  margin-bottom: 8px; border-left: 2px solid var(--line-strong);
}
.inv-item.miss.high { border-left-color: var(--loss); }
.inv-item.miss.med { border-left-color: var(--draw); }
.inv-item.miss.low { border-left-color: var(--ink-ghost); }
.inv-item.off { opacity: 0.62; border-left-style: dashed; }
.inv-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-bottom: 5px;
}
.inv-top b { font-size: 0.78rem; color: var(--ink); font-weight: 700; line-height: 1.3; }
.inv-item p { font-size: 0.72rem; line-height: 1.65; color: var(--ink-dim); }
.inv-n {
  flex: none; font-family: var(--mono); font-size: 0.6rem; color: var(--ink-ghost);
  letter-spacing: 0.02em;
}
.inv-imp {
  flex: none; font-size: 0.55rem; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 700; padding: 2px 6px; border-radius: 2px; white-space: nowrap;
}
.inv-imp.high { color: var(--loss); background: rgba(255, 84, 112, 0.14); }
.inv-imp.med { color: var(--draw); background: rgba(255, 200, 87, 0.14); }
.inv-imp.low { color: var(--ink-faint); background: rgba(255, 255, 255, 0.06); }
.inv-off {
  display: inline-block; margin-top: 7px; font-size: 0.55rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700;
}

.lim-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.lim-grid .note-card { margin-bottom: 0; }

@media (max-width: 860px) {
  .howto-grid, .inv, .lim-grid { grid-template-columns: 1fr; }
  .ps-row { grid-template-columns: 118px 1fr 52px; gap: 10px; }
  .ps-label b { font-size: 0.7rem; }
}

/* Below this width the three-column strip squeezes the chart to about 180px,
   where a 760-unit viewBox renders its 8px labels at under 4px. The chart moves
   to its own full-width row and everything drawn inside it is scaled up in
   user units, which is the only way to change apparent size when the SVG is
   sized by its aspect ratio. */
@media (max-width: 640px) {
  .ps-row {
    grid-template-columns: 1fr auto;
    grid-template-areas: "label verdict" "chart chart";
    gap: 2px 10px; padding: 12px 0 16px;
  }
  .ps-label { grid-area: label; }
  .ps-verdict { grid-area: verdict; text-align: right; }
  .ps-verdict b { font-size: 1rem; }
  .ps-verdict i { display: inline; margin-left: 6px; }
  .ps-chart { grid-area: chart; padding-bottom: 10px; }
  .ps-tick { font-size: 19px; }
  .ps-tick.alt { display: none; }
  .ps-base, .ps-ref { stroke-width: 4; }
  .ps-dot { r: 9px; stroke-width: 3; }
  .ps-key { font-size: 0.62rem; gap: 6px 14px; }
}

/* -------------------------------------------------- the preseason anchor --
   The bar is the point of this block: it says how much of the number is still
   a preseason opinion, which is the one thing a reader needs in order to
   discount it appropriately in December. */

.eff.anchor { border-left: 2px solid var(--draw); }
.anch-bar {
  position: relative; height: 22px; border-radius: 2px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--line);
  margin: 0 18px 8px;
}
.anch-fill {
  position: absolute; inset: 0 auto 0 0;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--draw) 42%, transparent),
    color-mix(in srgb, var(--draw) 16%, transparent));
}
.anch-lab {
  position: relative; display: block; line-height: 22px; padding: 0 9px;
  font-size: 0.64rem; letter-spacing: 0.03em; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.anch-note {
  font-size: 0.7rem; line-height: 1.65; color: var(--ink-dim);
  padding: 0 18px; margin: 0 0 10px;
}
.anch-note b { color: var(--ink); font-weight: 700; font-family: var(--mono); }

/* ------------------------------------------------------- calibration card */

.cal-card { display: flex; flex-direction: column; }
.cal-tabs {
  display: flex; gap: 4px; flex-wrap: wrap;
  padding: 10px 18px 0; border-bottom: 1px solid var(--line);
}
.cal-tabs button {
  background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer;
  font: inherit; font-size: 0.6rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-ghost); padding: 6px 8px 7px;
}
.cal-tabs button:hover { color: var(--ink-dim); }
.cal-tabs button.on { color: var(--accent); border-bottom-color: var(--accent); }
.cal-stats {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  padding: 12px 18px 16px; border-top: 1px solid var(--line);
}
.cal-stat { display: flex; flex-direction: column; }
.cal-stat b { font-size: 1.15rem; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); }
.cal-stat b.good { color: var(--win); }
.cal-stat b.bad { color: var(--loss); }
.cal-stat i {
  font-style: normal; font-size: 0.55rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700; margin-top: 2px;
}
.cal-legend {
  display: flex; flex-wrap: wrap; gap: 3px 16px; margin-left: auto;
  max-width: 260px;
  font-size: 0.64rem; color: var(--ink-faint);
}
.cal-legend span { display: inline-flex; align-items: center; gap: 7px; }
.cal-key { width: 14px; height: 2px; border-radius: 1px; display: inline-block; }
.cal-key.raw { background: var(--ink-faint); }
.cal-key.cal { background: var(--accent); }
.cal-key.ideal { background: none; border-top: 1px dashed var(--ink-ghost); height: 0; }
.cal-fine { color: var(--ink-ghost); font-size: 0.58rem; }
@media (max-width: 720px) {
  .cal-legend { margin-left: 0; }
}

/* ------------------------------------------------------------ feature tree */

.ft-body { padding: 16px 8px 18px; overflow-x: auto; }
.ft-svg { width: 100%; min-width: 660px; height: auto; display: block; }
.ft-link { fill: none; stroke: var(--line-strong); opacity: 0.75; }
.ft-link.lin { stroke: var(--draw); opacity: 0.85; }
.ft-trunk { stroke: var(--line-strong); stroke-width: 1.5; }
.ft-root { fill: var(--accent); stroke: var(--bg); stroke-width: 2; }
.ft-rootlab { fill: var(--ink); font-size: 12px; font-weight: 700; font-family: var(--mono); }
.ft-rootsub { fill: var(--ink-ghost); font-size: 8.5px; font-family: var(--mono);
  letter-spacing: 0.08em; }
.ft-fam { fill: var(--ink); font-size: 11px; font-weight: 700; font-family: var(--mono); }
.ft-fam.lin { fill: var(--draw); }
.ft-leaf { fill: var(--ink-ghost); font-size: 8.5px; font-family: var(--mono); }
.ft-bar { fill: color-mix(in srgb, var(--accent) 55%, transparent); }
.ft-bar.lin { fill: color-mix(in srgb, var(--draw) 62%, transparent); }
.ft-pct { fill: var(--ink-dim); font-size: 10.5px; font-family: var(--mono);
  font-weight: 700; }
.ft-tabs { padding-bottom: 0; }

/* ------------------------------------------------------- custom dropdown --
   The native control stays in the DOM as the value holder and is taken out of
   the layout and the a11y tree; the visible control is the button beside it. */

.sel { position: relative; display: inline-block; width: 100%; }
.sel-native {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sel-btn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; height: 40px; padding: 0 12px; cursor: pointer;
  font: inherit; font-size: 0.82rem; text-align: left;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color 0.15s, background 0.15s;
}
.sel-btn:hover { border-color: var(--line-strong); background: var(--panel-3); }
.sel-btn[aria-expanded="true"] { border-color: var(--accent); background: var(--panel-3); }
.sel-btn:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
.sel-lab { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sel-ico { width: 10px; height: 6px; flex: none; color: var(--ink-faint); }
.sel-btn[aria-expanded="true"] .sel-ico { color: var(--accent); }

.sel-pop {
  position: absolute; z-index: 60; top: calc(100% + 5px); left: 0;
  min-width: 100%; max-width: min(340px, 88vw);
  background: var(--panel-3); border: 1px solid var(--line-strong);
  border-top: 2px solid var(--accent); border-radius: var(--r);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.62); overflow: hidden;
}
.sel-pop.right { left: auto; right: 0; }
.sel-filter {
  width: 100%; height: 34px; border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; background: var(--panel-2); font-size: 0.76rem;
}
.sel-filter:focus { border-color: var(--line); border-bottom-color: var(--accent); }
.sel-list { max-height: 300px; overflow-y: auto; padding: 4px; }
.sel-opt {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: 2px; padding: 7px 9px;
  font: inherit; font-size: 0.78rem; color: var(--ink-dim);
}
.sel-opt:hover { background: var(--panel-2); color: var(--ink); }
.sel-opt.on { color: var(--accent); font-weight: 700; }
.sel-opt.all { color: var(--ink-faint); font-style: italic; }
.sel-empty {
  padding: 14px 10px; text-align: center; font-size: 0.72rem; color: var(--ink-ghost);
}

/* --------------------------------------------------------- rankings tools */

.rank-tools { align-items: center; }
.rank-comp { width: 100%; max-width: 230px; }
.rank-tools.one-comp .rank-comp { display: none; }
.seg.pool button { min-width: 74px; }
.board .rk.medal { color: var(--accent); font-weight: 800; }
.mv {
  font-family: var(--mono); font-size: 0.74rem; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
.mv.up { color: var(--win); }
.mv.down { color: var(--loss); }
.mv.flat { color: var(--ink-ghost); }

/* The native checkbox is the last OS-drawn control on the page. */
.toggle { display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700; user-select: none; }
.toggle input[type=checkbox] {
  appearance: none; width: 16px; height: 16px; margin: 0; flex: none; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--line-strong);
  border-radius: 2px; position: relative; transition: background 0.15s, border-color 0.15s;
}
.toggle input[type=checkbox]:hover { border-color: var(--accent); }
.toggle input[type=checkbox]:checked { background: var(--accent); border-color: var(--accent); }
.toggle input[type=checkbox]:checked::after {
  content: ''; position: absolute; left: 4px; top: 1px;
  width: 5px; height: 9px; border: solid var(--accent-ink);
  border-width: 0 2px 2px 0; transform: rotate(42deg);
}
.toggle input[type=checkbox]:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.toggle:hover { color: var(--ink-dim); }

/* compact enhanced menus inside the game-day inputs box */
.wx-field .sel-btn { height: 34px; font-size: 0.66rem; padding: 0 10px; }
.wx-field .sel { min-width: 148px; }
/* the round menu sits inside a .field label, which owns the width */
label.field .sel-btn { height: 40px; }

.mc-lead { font-size: 0.78rem; line-height: 1.7; color: var(--ink-dim);
  margin: 16px 0 12px; }
.mc-lead b { color: var(--ink); font-weight: 700; }

.qb-name { display: block; font-style: normal; font-size: 0.62rem;
  color: var(--ink-ghost); letter-spacing: 0.02em; margin-top: 1px; }

/* ------------------------------------------------------------- fixtures --
   The season, on the page. 272 games is a browse-able number; six soccer
   competitions is not, which is why this is NFL-only. */

.fixtures { margin-top: 14px; }
.fx-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.fx-weeks { flex-wrap: wrap; }
.fx-weeks button { min-width: 30px; padding: 6px 8px; font-size: 0.64rem; }
.fx-note {
  font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-ghost); font-weight: 700;
}
.fx-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 7px;
}
.fx {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  padding: 8px 10px; cursor: pointer; font: inherit; text-align: left;
  transition: border-color 0.15s, background 0.15s;
}
.fx:hover { border-color: var(--accent); background: var(--panel-2); }
.fx.next { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.fx.past { opacity: 0.45; }
.fx-teams { display: flex; align-items: center; gap: 6px; min-width: 0;
  overflow: hidden; flex: 1 1 auto; }
.fx-t { display: inline-flex; align-items: center; gap: 4px; }
.fx-t b {
  font-size: 0.86rem; font-weight: 700; color: var(--ink); letter-spacing: 0.02em;
  white-space: nowrap;
}
.fx-at { font-size: 0.6rem; color: var(--ink-faint); letter-spacing: 0.06em; }
.fx-proj {
  font-family: var(--mono); font-size: 0.64rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; flex: none;
}
/* A tagged card has no room for both; the tag is the more useful of the two. */
.fx:has(.fx-tag) .fx-proj { display: none; }
.fx-tag {
  font-size: 0.5rem; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 700; color: var(--accent-ink); background: var(--accent);
  border-radius: 2px; padding: 2px 4px; flex: none;
}
.crest.xs { width: 21px; height: 21px; border-radius: 3px; font-size: 0.46rem; }
@media (max-width: 620px) {
  /* Two fixed columns overflowed a 390px viewport once the crest, both codes and
     the tag were in one card; auto-fit lets the grid drop to one column when the
     card cannot fit rather than pushing the page sideways. */
  .fx-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .fx-proj { display: none; }
  .fx { padding: 8px; }
  .fx-t b { font-size: 0.66rem; }
}

/* ------------------------------------------------- findings & sport tabs --
   Findings are a list of headlines that open one at a time. As full note cards
   they were nine stacked blocks of prose that nobody read; as headlines they can
   be scanned, and the one that matters can be opened. */

.sport-tabs { border-bottom: 1px solid var(--line); margin-bottom: 16px; }
.mc-sub { font-size: 0.76rem; line-height: 1.7; color: var(--ink-dim); margin-bottom: 14px; }

.finds { margin-top: 18px; border-top: 1px solid var(--line); }
.find { border-bottom: 1px solid var(--line); }
.find-h {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  width: 100%; background: none; border: 0; cursor: pointer; text-align: left;
  font: inherit; font-size: 0.78rem; font-weight: 700; color: var(--ink);
  padding: 11px 2px;
}
.find-h:hover { color: var(--accent); }
.find-h.warn { color: var(--loss); }
.find-h.warn:hover { color: var(--accent); }
/* A small marker beats a whole red heading: the reader can still see at a
   glance which findings are cautions without the list reading as an alarm. */
.find-h.warn span::after {
  content: 'caution'; margin-left: 10px; font-size: 0.5rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--loss);
  background: rgba(255, 84, 112, 0.14); border-radius: 2px; padding: 2px 5px;
  vertical-align: 1px;
}
.find-h.warn { color: var(--ink); }
.find-h i {
  font-style: normal; font-size: 0.9rem; color: var(--ink-ghost); flex: none;
  transition: transform 0.18s ease; line-height: 1;
}
.find-h[aria-expanded="true"] i { transform: rotate(45deg); color: var(--accent); }
.find p {
  font-size: 0.74rem; line-height: 1.75; color: var(--ink-dim);
  padding: 0 2px 14px; margin: 0; max-width: 78ch;
}

/* --------------------------------------------------------- roster movement */

.eff-side.rost { align-items: flex-start; }
.rost-cols { display: flex; gap: 26px; flex-wrap: wrap; }
.rost-col { display: flex; flex-direction: column; gap: 3px; min-width: 150px; }
.rost-k {
  font-size: 0.52rem; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; margin-bottom: 3px;
}
.rost-k.in { color: var(--win); }
.rost-k.out { color: var(--loss); }
.rost-p { font-size: 0.7rem; color: var(--ink); letter-spacing: 0.01em; }
.rost-p.gone { color: var(--ink-faint); text-decoration: line-through;
  text-decoration-color: var(--ink-ghost); }
.rost-p i {
  font-style: normal; font-size: 0.54rem; color: var(--ink-ghost);
  letter-spacing: 0.08em; margin-left: 6px;
}
@media (max-width: 720px) { .rost-cols { gap: 14px; } }

/* ----------------------------------------------------------------- ask --
   A question box, the parse, and the answer. The parse is styled to be read
   rather than skipped: an answer whose interpretation is hidden is asking to
   be trusted. */

.askbox { display: flex; gap: 10px; align-items: stretch; margin-bottom: 12px; }
/* The agent page leads straight into its input, so it sits closer to the
   description than a general view-head gap allows. */
#view-stargazer .view-head { margin-bottom: 14px; }
#view-stargazer .ask-eg { margin-top: 4px; }
.askbox textarea {
  flex: 1; font: inherit; font-size: 0.84rem; line-height: 1.6; resize: vertical;
  background: var(--panel-2); color: var(--ink); padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--r);
}
.askbox textarea:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
.askbox .btn { flex: none; align-self: stretch; padding: 0 26px; }
.eg-lab {
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-ghost); font-weight: 700; margin-right: 4px;
}
/* Prompt suggestions, not chips. Laid out as a grid rather than wrapped flex so
   every card is the same height whatever its text does — the flex version left
   a ragged second row, and one card ellipsed a URL mid-path. */
.ask-eg {
  display: grid; gap: 10px; margin-bottom: 26px;
  /* Three up on a wide screen rather than four. At 255px the cards were narrow
     enough that most example phrasings wrapped to the second line, which is the
     line they are clamped at — so nearly every card sat at its limit and the row
     read as a solid block of small grey text. */
  /* min() so the track can go under 330px when the screen is narrower than
     that. A bare minmax(330px, 1fr) is a floor the grid cannot go below, and on
     a 320px phone it pushed the whole page 34px wide. */
  grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
}
.eg {
  position: relative; display: flex; flex-direction: column; gap: 5px;
  font: inherit; cursor: pointer; text-align: left;
  background: var(--panel); color: var(--ink-dim);
  border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 40px 17px 17px; height: 100%;
  transition: border-color 0.15s, background 0.15s, transform 0.12s;
}
.eg-tag {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--ink-ghost);
}
.eg b { font-size: 1rem; color: var(--ink); font-weight: 600; line-height: 1.32; }
.eg i {
  font-family: var(--mono); font-style: normal; font-size: 0.75rem;
  color: var(--ink-faint); line-height: 1.5;
  /* Two lines, then clip cleanly — never a URL cut off mid-path. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.eg-go {
  position: absolute; right: 15px; top: 15px; color: var(--ink-ghost);
  font-size: 0.9rem; transition: transform 0.15s, color 0.15s;
}
.eg:hover {
  border-color: var(--accent); background: var(--panel-2); transform: translateY(-1px);
}
.eg:hover b { color: var(--ink); }
.eg:hover .eg-go { color: var(--accent); transform: translateX(3px); }

.ask-res { border-top: 1px solid var(--line); padding-top: 18px; }
.ask-parse { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin-bottom: 16px; }
.ask-k {
  font-size: 0.56rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-ghost); font-weight: 700;
}
.ask-chip {
  font-size: 0.68rem; color: var(--ink); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--r); padding: 4px 10px;
}
.ask-money.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ask-money { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.ask-side { background: var(--panel); padding: 18px 20px; }
.ask-side.home { background: var(--panel-2); }
.ask-team { font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 700; }
.ask-p { font-size: 2.1rem; font-weight: 800; letter-spacing: -0.04em; color: var(--ink);
  line-height: 1.15; margin-top: 4px; }
.ask-side.home .ask-p { color: var(--accent); }
.ask-odds { font-size: 0.72rem; color: var(--ink-faint); }
.ask-lines { display: flex; gap: 30px; padding: 14px 2px 4px; }
.ask-lines b { font-family: var(--mono); font-size: 1.05rem; font-weight: 700; color: var(--ink); }
.ask-lines i { display: block; font-style: normal; font-size: 0.54rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700; margin-top: 2px; }
.ask-delta { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: baseline;
  background: var(--panel); border-left: 2px solid var(--draw);
  border-radius: 0 var(--r) var(--r) 0; padding: 12px 16px; margin: 14px 0; }
.ask-delta span { font-family: var(--mono); font-size: 0.74rem; color: var(--ink); }
.ask-delta i { font-style: normal; font-size: 0.66rem; color: var(--ink-ghost); }
.ask-note { font-size: 0.72rem; color: var(--ink-dim); padding: 6px 0 6px 14px;
  border-left: 2px solid var(--line); margin-top: 6px; }
.ask-note.ok { border-left-color: var(--win); }
@media (max-width: 620px) {
  .askbox { flex-direction: column; }
  /* `align-self: stretch` sized this against the textarea while the box was a
     row. Stacked, the cross axis is horizontal, so the button stretched wide and
     collapsed to its line-height — a 20px primary action, under the 24px target
     minimum and unpleasant to hit. The row layout gets its height from the
     textarea; the column has to say it. */
  .askbox .btn { min-height: 44px; }
  .ask-money, .ask-money.three { grid-template-columns: minmax(0, 1fr); }
  /* The input is the thing this page is for, and the examples are a prompt for
     it — on a phone that ranking was inverted: a two-row box under three cards
     tall enough to fill the screen. The box grows, the cards give way. These
     sit after the base .eg rules, which is what makes them apply. */
  .askbox textarea { min-height: 92px; font-size: 0.92rem; padding: 13px 15px; }
  .ask-eg { gap: 8px; margin-bottom: 20px; }
  .eg { padding: 12px 32px 13px 14px; gap: 3px; }
  .eg b { font-size: 0.86rem; line-height: 1.28; }
  .eg i { font-size: 0.68rem; line-height: 1.45; }
  .eg-tag { font-size: 0.55rem; }
  .eg-go { right: 12px; top: 12px; font-size: 0.8rem; }
}

.ask-wx {
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: baseline;
  background: var(--panel); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0; padding: 11px 15px; margin: 14px 0;
}
.ask-wx.typical { border-left-color: var(--ink-faint); }
.ask-wx span { font-family: var(--mono); font-size: 0.74rem; color: var(--ink); }
.ask-wx .ask-k { font-family: inherit; }
.ask-wx i { font-style: normal; font-size: 0.66rem; color: var(--ink-ghost); }

/* The example-card rules live with the rest of the agent styles further up.
   A second copy sat here from an earlier pass and, being later in the file, won
   every conflict — which is why the cards stayed four-up and the labels stayed
   at 0.64rem no matter what the other block said. */

/* the written answer */
/* The overflow set. A disclosure rather than a longer board: fifteen cards is
   something to read through, nine is something to choose from. */
.eg-more { margin: -12px 0 26px; }
.eg-more > summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center;
  gap: 7px; padding: 7px 0;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700;
}
.eg-more > summary::-webkit-details-marker { display: none; }
.eg-more > summary::after {
  content: '+'; font-size: 0.85rem; line-height: 1; color: var(--ink-faint);
}
.eg-more[open] > summary::after { content: '\2212'; }
.eg-more > summary:hover { color: var(--ink-dim); }
.eg-more > summary:hover::after { color: var(--ink-dim); }
.eg-more[open] > summary { margin-bottom: 4px; }
.eg-more .ask-eg { margin-bottom: 4px; }

/* -------------------------------------------------------------- thinking --
   A request in flight. Three things move, each saying something different: the
   dots say the agent is alive, the bar says work is happening and cannot say
   how much is left, and the label says what kind of work it is. None of them
   claims progress, because none of this side can measure any. */
.thinking {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 17px; background: var(--panel);
  border: 1px solid var(--line); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0; position: relative; overflow: hidden;
}
.think-dots { display: inline-flex; gap: 5px; }
.think-dots i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
  opacity: 0.35; animation: thinkPulse 1.25s ease-in-out infinite;
}
.think-dots i:nth-child(2) { animation-delay: 0.16s; }
.think-dots i:nth-child(3) { animation-delay: 0.32s; }
.think-label {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-dim);
}
/* A sweep, not a percentage: the width is meaningless and deliberately so. */
.think-bar {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 34%;
  background: linear-gradient(90deg, transparent,
              color-mix(in srgb, var(--accent) 70%, transparent), transparent);
  animation: thinkSweep 1.5s linear infinite;
}
@keyframes thinkPulse {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  40%      { opacity: 1;   transform: translateY(-3px); }
}
@keyframes thinkSweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(390%); }
}

/* ------------------------------------------------------------ transcript --
   The agent view is a conversation now, so answers stack instead of replacing
   one another and each carries the question that produced it. */
.turn { display: flex; flex-direction: column; gap: 10px; margin-top: 22px; }
.turn + .turn { border-top: 1px solid var(--line); padding-top: 22px; }
.turn-q { display: flex; }
.turn-q span {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r); padding: 9px 14px; max-width: 62ch;
  font-size: 0.86rem; line-height: 1.5; color: var(--ink);
}
.ask-thread {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 9px 13px;
  background: var(--panel); border: 1px solid var(--line);
  border-left: 2px solid var(--accent); border-radius: 0 var(--r) var(--r) 0;
}
.thread-k {
  font-family: var(--mono); font-size: 0.56rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700;
}
.thread-sub { font-size: 0.82rem; color: var(--ink); margin-right: auto; }
.btn.ghost.sm { height: 28px; padding: 0 11px; font-size: 0.62rem; }

/* ------------------------------------------------ clarify + head to head --
   The agent asking a question back, and results rather than a forecast. Both
   reuse the panel and board shapes rather than inventing surfaces. */
.clarify-opts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.btn.ghost {
  background: var(--panel-2); color: var(--ink-dim);
  border: 1px solid var(--line); padding: 0 15px; height: 36px;
  font-size: 0.72rem; letter-spacing: 0.04em;
}
.btn.ghost:hover { border-color: var(--line-strong); color: var(--ink); }
/* The chosen answer stays lit while the next call is in flight, so the click
   is visibly registered rather than appearing to do nothing for a second. */
.btn.ghost.on {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel-2));
}
table.board.h2h td.score { font-family: var(--mono); color: var(--ink); font-weight: 600; }
table.board.h2h td.win { color: var(--ink); font-weight: 600; }
table.board.h2h td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.ask-said { background: var(--panel); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0; padding: 14px 18px; margin-bottom: 16px; }
.ask-said p { font-size: 0.82rem; line-height: 1.7; color: var(--ink-body);
  margin-top: 8px; max-width: 76ch; }
.ask-said p:first-of-type { color: var(--ink); }

/* absence estimate — visually distinct from the measured blocks beside it */
.ask-inj { background: var(--panel); border-left: 2px dashed var(--draw);
  border-radius: 0 var(--r) var(--r) 0; padding: 13px 17px; margin: 14px 0; }
.inj-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 10px; }
.inj-tag { font-size: 0.52rem; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 700; color: var(--draw); background: rgba(255,200,87,0.14);
  border-radius: 2px; padding: 2px 6px; }
.inj-nums { display: flex; flex-wrap: wrap; gap: 8px 28px; }
.inj-nums b { font-family: var(--mono); font-size: 0.95rem; font-weight: 700; color: var(--ink); }
.inj-nums i { display: block; font-style: normal; font-size: 0.54rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--ink-ghost); font-weight: 700; margin-top: 2px; }

.ask-was { font-size: 0.6rem; color: var(--ink-ghost); letter-spacing: 0.04em; margin-top: 3px; }
.ask-base b { color: var(--ink-faint) !important; font-size: 0.85rem !important; }

/* ------------------------------------------------------- the input field --
   The one control the whole page is about, so it gets treated as an instrument
   rather than a form field: a sweep of accent light travels the top edge while
   it is focused, and the frame lifts. Everything here is transform and opacity,
   so it composites on the GPU and costs nothing, and it all collapses under
   prefers-reduced-motion. */

.askbox { position: relative; }
.askbox::before {
  content: ''; position: absolute; inset: -1px; border-radius: var(--r);
  padding: 1px; pointer-events: none; opacity: 0;
  background: linear-gradient(115deg, transparent 20%,
    color-mix(in srgb, var(--accent) 85%, transparent) 50%, transparent 80%);
  background-size: 220% 100%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  transition: opacity 0.25s ease;
}
.askbox.on::before { opacity: 1; animation: sweep 2.6s linear infinite; }
@keyframes sweep {
  from { background-position: 140% 0; }
  to   { background-position: -60% 0; }
}
.askbox textarea {
  transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.25s ease;
}
.askbox.on textarea {
  background: var(--panel-3);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 26%, transparent),
              0 12px 40px rgba(0, 0, 0, 0.45);
}
/* A caret that breathes while the field is empty and focused, so the page reads
   as waiting for input rather than idle. */
.askbox.on.blank textarea::placeholder { animation: dim 2.2s ease-in-out infinite; }
@keyframes dim { 0%, 100% { opacity: 0.75; } 50% { opacity: 0.35; } }

.askbox .btn { position: relative; overflow: hidden; }
.askbox .btn.busy::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent,
    rgba(255, 255, 255, 0.28), transparent);
  animation: scan 1.1s linear infinite;
}
@keyframes scan { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* Answers arrive rather than appear. */
.ask-res > * { animation: rise-in 0.34s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.ask-res > *:nth-child(2) { animation-delay: 0.05s; }
.ask-res > *:nth-child(3) { animation-delay: 0.1s; }
.ask-res > *:nth-child(4) { animation-delay: 0.15s; }
@keyframes rise-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

/* `.askbox .btn.busy::after` is deliberately absent here: it is the progress
   scanner, and stopping it would leave a pressed button looking inert while a
   request is still running. Handled with the rest of the named rules above. */

/* title picture */
.title-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.title-col { background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); padding: 14px 16px; }
.title-row { display: flex; align-items: center; gap: 9px; padding: 8px 0;
  border-top: 1px solid var(--line); }
.title-col .ask-k { display: block; margin-bottom: 4px; }
.title-rk { font-family: var(--mono); font-size: 0.62rem; color: var(--ink-ghost);
  width: 12px; }
.title-row b { font-size: 0.8rem; color: var(--ink); flex: 1; }
.title-w { font-size: 0.62rem; color: var(--ink-faint); }
.title-e { font-size: 0.78rem; font-weight: 700; color: var(--accent); min-width: 42px;
  text-align: right; }
@media (max-width: 620px) { .title-grid { grid-template-columns: 1fr; } }

/* ================================================================ 404 ==
   A dead link is still a page of the product, so it gets the same furniture
   as any other view rather than a bare server string. The orbit is drawn
   empty on purpose: the shape is there, nothing is on it. */
.nf { padding: 64px 0 96px; text-align: center; max-width: 620px; margin: 0 auto; }
.nf-orbit { color: var(--tint, var(--accent)); opacity: 0.85; }
.nf-orbit svg { width: min(240px, 62vw); height: auto; display: block; margin: 0 auto; }
.nf-code {
  font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.22em;
  color: var(--ink-ghost); margin: 18px 0 6px;
}
.nf h1 {
  font-family: var(--display); font-weight: 700; font-size: clamp(1.5rem, 3.8vw, 2.2rem);
  line-height: 1.15; margin: 0 0 14px; color: var(--ink);
}
.nf h1 em { color: var(--tint, var(--accent)); }
.nf-msg { color: var(--ink-dim); line-height: 1.6; margin: 0 auto 26px; max-width: 46ch; }
.nf-go { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
a.brand { text-decoration: none; color: inherit; }

/* The 404's calls to action are anchors styled as buttons; without this they
   carry the underline that real <button> elements never show. */
a.btn { text-decoration: none; display: inline-flex; align-items: center; }

/* ========================================================== stargazer ==
   The page IS the gate. Stargazer has no free tier, so a paywall in a panel at
   the bottom made the view read as an article with a footnote; the offer fills
   the page instead. Only the top of the staking scale carries a name, because
   only the top of it needs one. */
.sg-page {
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r);
}
/* The gate is the content and sets the height; the blurred ledger behind it is
   decoration. Done the other way round, the offer overflowed a box sized by a
   ledger that has nothing in it yet, and clipped its own first and last line. */
.sg-blur {
  position: absolute; inset: 0; padding: 24px;
  filter: blur(6px) saturate(0.6); opacity: 0.45;
  pointer-events: none; user-select: none;
}
.sg-gate {
  position: relative; display: flex; min-height: min(72vh, 700px);
  align-items: center; justify-content: center; padding: 48px 24px;
  background:
    radial-gradient(ellipse 70% 60% at 50% 45%,
      rgba(14, 17, 22, 0.82) 0%, rgba(14, 17, 22, 0.97) 100%);
}
.sg-gate-in {
  max-width: 560px; width: 100%; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.sg-gate-in h2 {
  font-family: var(--display); font-weight: 700; font-size: 1.45rem;
  margin: 0; color: var(--ink); letter-spacing: -0.01em;
}
.sg-gate-lede {
  color: var(--ink-dim); line-height: 1.62; margin: 0; font-size: 0.94rem;
  max-width: 50ch;
}
.sg-gate-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--draw);
  border: 1px solid rgba(255, 200, 87, 0.38); border-radius: 999px;
  padding: 4px 11px; background: rgba(255, 200, 87, 0.07);
}
.sg-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--draw);
  animation: sg-pulse 2.4s ease-in-out infinite;
}
@keyframes sg-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.sg-scale-wrap { width: 100%; max-width: 420px; margin-top: 4px; }
.sg-scale { display: flex; gap: 4px; }
.sg-pip { flex: 1; height: 8px; border-radius: 2px; background: var(--line-strong); }
.sg-pip.nova {
  background: var(--supernova);
  box-shadow: 0 0 9px rgba(255, 226, 150, 0.45);
}
.sg-scale-ends {
  display: flex; justify-content: space-between; margin-top: 7px;
  font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-ghost);
}
.sg-scale-ends .nova-label { color: var(--supernova); }

.sg-rulelist {
  list-style: none; margin: 6px 0 4px; padding: 0; display: grid; gap: 10px;
  text-align: left; width: 100%;
}
.sg-rulelist li {
  color: var(--ink-faint); line-height: 1.55; padding-left: 15px;
  position: relative; font-size: 0.87rem;
}
.sg-rulelist li::before {
  content: ''; position: absolute; left: 0; top: 0.6em; width: 5px; height: 5px;
  border-radius: 50%; background: var(--accent); opacity: 0.6;
}
.sg-rulelist b { color: var(--ink); font-weight: 600; }
.sg-gate .btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.sg-gate-honest {
  color: var(--ink-ghost); font-size: 0.8rem; line-height: 1.55;
  margin: 0; max-width: 48ch;
}

.sg-h {
  font-family: var(--display); font-weight: 700; font-size: 1.05rem;
  margin: 22px 0 10px; color: var(--ink);
}
.sg-record {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden;
}
.sg-rec-cell { background: var(--panel); padding: 15px 16px; }
.sg-rec-k {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--ink-ghost); margin-bottom: 5px;
}
.sg-rec-v { font-family: var(--mono); font-size: 1.45rem; color: var(--ink); }
.sg-rec-v.net-up { color: var(--win); }
.sg-rec-v.net-down { color: var(--loss); }

.sg-tablewrap { overflow-x: auto; }
.sg-ledger { width: 100%; }
.sg-ledger .sg-date, .sg-ledger .sg-play { font-family: var(--mono); font-size: 0.83rem; }
.sg-res { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.1em; }
.sg-row.r-win .sg-res { color: var(--win); }
.sg-row.r-loss .sg-res { color: var(--loss); }
.sg-chip {
  margin-left: 8px; font-family: var(--mono); font-size: 0.62rem;
  letter-spacing: 0.11em; text-transform: uppercase; padding: 2px 7px;
  border-radius: 999px; border: 1px solid currentColor;
  color: var(--supernova);
}
.sg-skel .sg-bar {
  display: inline-block; height: 9px; border-radius: 2px;
  background: var(--line-strong); opacity: 0.5;
}
.sg-skel td { padding-block: 11px; }

@media (max-width: 760px) {
  .sg-record { grid-template-columns: repeat(2, 1fr); }
  .sg-rec-v { font-size: 1.2rem; }
  .sg-gate { padding: 24px 16px; }
  .sg-gate-in h2 { font-size: 1.4rem; }
}
/* Named, not blanket: killing every animation would also kill the ones that
   carry meaning elsewhere on the site. */
@media (prefers-reduced-motion: reduce) {
  .sg-dot { animation: none; }
}

/* ==================================================== accessibility ==
   A site-wide focus ring. Without this only the three controls that had
   hand-written focus styles were reachable by eye when tabbing; everything
   else — every tab, pill, fixture card and link — relied on a native ring that
   the reset had already flattened against a dark background. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Skip link. Hidden until focused, then the first thing in the tab order. */
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 200;
  background: var(--panel-3); color: var(--ink);
  border: 1px solid var(--accent); border-radius: var(--r);
  padding: 10px 16px; font-size: 0.72rem; letter-spacing: 0.1em;
  text-transform: uppercase; text-decoration: none;
  transition: top 0.15s;
}
.skip:focus { top: 8px; }

/* The view a route lands on receives focus so a screen reader announces the new
   page instead of staying silent, but it is not a tab stop on its own. */
section.view:focus { outline: none; }
section.view:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Validation and status text reserves its line before it has anything to say,
   so a message appearing cannot shove the button out from under the cursor. */
.go-note {
  min-height: 1.25em; display: inline-block;
}
.go-note.bad { color: var(--loss); }

/* ================================================= data stays mono ==
   Restores the fixed-width face on everything whose characters are values
   rather than sentences. Anything that already declared var(--mono) keeps it;
   these are the surfaces that were relying on inheriting it from body. */
table.board, table.board th, table.board td,
input, select, textarea,
.num, .crest, .pills, .pill,
.side-elo, .fx-note, .go-note,
.ladder, .odds, .price, .amer,
/* Chrome is not prose. Nav labels, buttons and small caps labels are UI
   furniture, and setting them in the book face left the site with serif
   uppercase everywhere — the one place a text face has nothing to offer,
   because there is no reading happening. */
nav.tabs button, .btn, .seg button, .eg-tag, .eg i, .kicker,
.side-role, .fx-weeks button, .disc-btn, .find-h, .sg-gate-badge,
/* Fixture cards are a schedule grid: three-letter codes, projected scores and
   the 'at' between them are all data, not sentences. */
.fx-t, .fx-at, .fx-proj, .fx-tag, .fx-elo, .sg-scale-ends, .ps-label {
  font-family: var(--mono);
}
/* Prose gets a little more room to breathe now that it is not fixed-width. */
.view-head p { font-size: 1.02rem; line-height: 1.68; max-width: 60ch; }
@media (prefers-reduced-motion: reduce) {
  .eg:hover { transform: none; }
  .eg:hover .eg-go { transform: none; }
}

/* -------------------------------------------- standalone documents --
   The accessibility statement and the privacy policy: prose pages that
   share the shell but none of the app's interface. One panel style, since
   the second page proved the first one was never accessibility-specific. */
.foot-links { display: flex; gap: 16px; align-items: baseline; }
.foot a { color: var(--ink-faint); text-decoration: underline; text-underline-offset: 2px; }
.foot a:hover { color: var(--ink); }
.doc { padding: 26px 28px; max-width: 74ch; }
.doc h2 {
  font-family: var(--display); font-weight: 700; font-size: 1rem;
  color: var(--ink); margin: 26px 0 8px;
}
.doc h2:first-child { margin-top: 0; }
.doc p { color: var(--ink-dim); line-height: 1.68; margin: 0 0 10px; }
.doc ul { margin: 0 0 6px; padding-left: 18px; }
.doc li { color: var(--ink-dim); line-height: 1.65; margin-bottom: 9px; }
.doc b { color: var(--ink); font-weight: 600; }
/* There is no global anchor rule on the site, because until these pages every
   link lived in a component that styled its own. A bare mailto: in prose fell
   through to the browser's blue — the only blue on the site. */
.doc a {
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
.doc a:hover { color: var(--ink); }
/* Storage APIs and header names read as data, so they take the mono voice like
   every other literal on the site. Sized in `em` rather than `rem`: monospace
   faces run large against a book serif at the same nominal size. */
.doc code {
  font-family: var(--mono); font-size: 0.84em; color: var(--ink);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 4px; padding: 1px 5px; white-space: nowrap;
}
.doc-date {
  font-family: var(--mono); font-size: 0.74rem; color: var(--ink-ghost) !important;
  margin-top: 22px !important; padding-top: 14px; border-top: 1px solid var(--line);
}

/* ================================================== motion ==
   Ported from garyqin.com/agentic rather than invented, so the two sites feel
   like one product: a staggered rise for anything that arrives in a group, a
   blur-in for a number that has just changed, a sliding indicator under the
   active tab, and a press response on everything clickable. */

/* Anything rendered as a group arrives staggered. `--i` is the item index, set
   by stagger() at render time; the cap keeps a 32-row table from taking a
   second and a half to finish arriving. */
.rise-in > * {
  animation: riseIn var(--t-rise) var(--ease-out) both;
  animation-delay: calc(min(var(--i, 0), 14) * 22ms);
}

/* A value that has just been recomputed, rather than one that has just
   appeared: same idea as the reference site's .val.swap. */
.val-swap { animation: valIn 220ms var(--ease-out) both; }

/* The active-tab indicator slides between tabs instead of cutting. It is one
   element moved with a transform, so the animation is composited and does not
   relayout the header on every navigation. */
nav.tabs { position: relative; }
.tab-ink {
  position: absolute; bottom: 0; left: 0; height: 2px; width: 0;
  background: var(--accent); border-radius: 2px;
  transform: translateX(0); pointer-events: none;
  transition: transform var(--t-tab) var(--ease-in-out),
              width var(--t-tab) var(--ease-in-out),
              opacity 160ms linear, background-color 0.4s;
}
.tab-ink.hidden { opacity: 0; }
/* The static underline is retired now that the ink bar draws it. */
nav.tabs button[aria-selected="true"] { border-bottom-color: transparent; }

/* Press response. Cheap, and it is most of what makes an interface feel
   answered rather than merely wired up. */
.btn:active:not([disabled]),
nav.tabs button:active,
.league:active,
.seg button:active,
.eg:active,
.fx-card:active,
.pick:active:not(:disabled) { transform: scale(0.97); }
.btn, .league, .seg button, .fx-card { transition: transform 90ms var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  /* Not switched off — swapped for a fade. The arrival still reads as an
     arrival, which is information, without anything travelling across the
     screen. This is how the reference site handles it too. */
  .rise-in > * { animation: fadeIn 200ms ease both; animation-delay: 0ms; }
  section.view.on { animation: fadeIn 200ms ease both; }
  .val-swap { animation: fadeIn 200ms ease both; }
  .tab-ink { transition: opacity 160ms linear; }
  .btn:active:not([disabled]), nav.tabs button:active, .league:active,
  .seg button:active, .eg:active, .fx-card:active,
  .pick:active:not(:disabled) { transform: none; }
}


/* A 74px crest and a 24px club name are right on a wide two-column matchup and
   much too loud stacked on a phone, where they take the top third of the panel
   before a single number is shown. */
@media (max-width: 560px) {
  /* Half the panel width per side now, so the crest and the club name come
     down again to leave the Elo line a row of its own rather than three. */
  .crest.lg { width: 42px; height: 47px; font-size: 0.86rem; }
  .side-name { font-size: 1.02rem; }
  .side-elo { font-size: 0.64rem; }
  .side-top { gap: 2px 8px; }
  .side-role { font-size: 0.56rem; letter-spacing: 0.12em; padding: 2px 6px; }
  /* Reserved for stakes that are usually not there, and 20px of nothing is
     worth more here than the shift it prevents. */
  .stakes:empty { min-height: 0; }
}
