/* ============================================================
   SOOTH DESK — design system, phase 1.
   The concept: a sports-market intelligence instrument.
   Surfaces, rails, tracks and grids — not cards. Color carries
   information or it is not used. Numbers are the typography.
   ============================================================ */

/* FROZEN MARKET — the concept, and the rules that come out of it.
   ---------------------------------------------------------------
   From the sooth.bet promos: a black ground, one teal, and the product
   encased in ice. The ice is not decoration. It is the most accurate picture
   of what this product actually does.

   A betting market is LIQUID — every price on the board is moving, and the
   whole board is a photograph of something still in motion. What the pick
   engine does is FREEZE a piece of it: at seal time the slate stops moving,
   gets hashed, and cannot be edited by us or anyone else. At first kickoff it
   THAWS and everyone sees it. Liquid → frozen → thawed is the product, and it
   is also the visual language.

   So, four rules:

   1. TEAL IS THE SIGNAL. One hue on the site. It marks the thing sooth exists
      to find — a better number than the market is showing — and it marks the
      chrome that belongs to us (rules, rings, the .bet in the wordmark).
      --up is the SAME teal, deliberately: "this price is favourable" and "this
      is the sooth signal" are one idea, and giving them two nearly-identical
      greens made the brand compete with the meaning. Red is the only other
      hue, for adverse movement. Amber survives for staleness because a
      warning must not look like a brand colour.

   2. FROST MEANS SEALED. Anything committed-but-not-yet-revealed is rendered
      as ice: a pale cyan rim, a frosted fill, a crystalline highlight. The
      SEALED chip on a locked slate is the clearest example — the state and
      the metaphor are the same object, so nobody has to be taught it.

   3. GLASS, NOT CARDS. Surfaces are thin, dark and lit from one edge, the way
      the block in the promo is: a 1px light rim on top, a darker rim below, a
      faint inner glow. Not a flat grey box with a radius.

   4. THE GROUND IS COLD AND NEARLY BLACK. #06080A, not a warm graphite and
      not a blue-grey dashboard. Everything else sits a few steps above it.
   ============================================================ */

:root{
  /* ground — cold, nearly black, as in the promos */
  --g0:#06080A;          /* page */
  --g1:#0B0F13;          /* working surface */
  --g2:#111820;          /* raised surface / hover */
  --g3:#18222B;          /* inputs, selected */
  --hair:rgba(190,222,228,.085);
  --hair2:rgba(190,222,228,.17);

  /* ink — cool white, the wordmark's own colour */
  --ink:#F0F5F6;         /* primary */
  --ink2:#AEBDC2;        /* secondary */
  --mut:#7E8D93;         /* labels */
  --dim:#546268;         /* faint metadata */

  /* THE one hue. See rule 1 above before adding another. */
  --brand:#2DD4A7;       /* sooth signal + identity + interactive */
  --brand-hi:#5BF0D4;    /* the lit ring: hover, focus, live edges */
  --brand-dim:rgba(45,212,167,.10);
  --up:#2DD4A7;          /* favourable price === the sooth signal */
  --dn:#FF6B6B;          /* adverse movement */
  --amber:#E2A94A;       /* staleness and caution — never brand */
  --up-dim:rgba(45,212,167,.10);
  --dn-dim:rgba(255,107,107,.10);
  --amber-dim:rgba(226,169,74,.10);

  /* frost — the sealed state. Rule 2. */
  --frost:#BFEAF2;       /* ice edge / sealed text */
  --frost-dim:rgba(191,234,242,.09);
  --frost-rim:rgba(191,234,242,.34);

  /* Archivo over Inter and IBM Plex Mono over JetBrains Mono: both carry more
     of a voice at the small sizes this interface lives at, and neither is the
     default anyone reaches for first. The mono is doing most of the work here
     — it sets nearly every number on the site. */
  --sans:'Archivo',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,monospace;

  --r:3px;               /* radius is an accent, not a personality */
  --wrap:1360px;

  /* MOTION CONTRACT: no literal ms values below this block anywhere in this
     file. Motion fires only from (a) user action, (b) a witnessed payload
     diff, (c) a real clock event. prev === null never animates. */
  --t-press:0ms;          /* :active compress — instant in */
  --t-hover:120ms;        /* hover color/bg/border/filter, plain ease */
  --t-view:150ms;         /* crossfades, lens switches, land() fades */
  --t-ui:200ms;           /* expand, underline slide, default when unsure */
  --t-flip:250ms;         /* FLIP row reorder */
  --t-roll:450ms;         /* digit tick-roll */
  --t-flash-hold:400ms;   /* flash-decay hold */
  --t-flash-fade:1600ms;  /* flash-decay fade to transparent */
  --t-draw:400ms;         /* one-shot SVG timeline draw */
  --t-ceremony:600ms;     /* pick reveal, seal settle, pin glide */
  --e-out:cubic-bezier(0.165,0.84,0.44,1);     /* quart-out: entrances */
  --e-inout:cubic-bezier(0.645,0.045,0.355,1); /* on-screen morphs */
  --e-glide:var(--e-out);                      /* fallback first (old Safari) */
  --e-glide:linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%,
    0.938 16.7%, 1.017, 1.026 20.4%, 1.021 24.3%, 1.006 32%, 0.999 43.1%, 1);
  /* bounce-free spring, ≤2% overshoot — instrument settle only, never on
     numbers; numbers always get --e-out. Exits run ~20% faster than entries.
     Zero bounce anywhere: this is a data instrument. */
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
/* The promos light the subject from above against a black room. Same here:
   one cold teal wash from over the top edge, one faint cool fill, black. */
body{color:var(--ink);font:14px/1.5 var(--sans);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  background:
    radial-gradient(1200px 520px at 50% -200px, rgba(45,212,167,.055), transparent 72%),
    radial-gradient(900px 620px at 82% 6%, rgba(190,222,228,.022), transparent 62%),
    var(--g0)}
a{color:inherit;text-decoration:none}
a:hover{color:var(--ink)}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
::selection{background:rgba(45,212,167,.26)}

/* every number in the product sits on tabular figures */
.n,td,th{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}

/* telemetry label — the small uppercase mono caption that names every
   instrument. This one class is most of the visual language. */
.tl{font:600 10px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim)}
.tl b{color:var(--mut);font-weight:600}

/* A heading, or a label, that only a screen reader gets. Needed because some
   pages have a real visual masthead and some are a diagram — /game leads with
   a two-team layout where promoting either team's name to h1 would state the
   wrong thing about the page. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* PAGE MASTHEAD. Was copy-pasted into picks.html and predictor.html with two
   slightly different type ramps, and simply absent from /edges, /props and
   /research, which opened straight onto a status strip with no heading at all
   — no h1 in the document, so nothing said what the page was to a reader, a
   screen reader or a crawler. Canonical here; both pages that already declare
   their own .ph still win on source order, since page styles load after this
   file. */
.ph{padding:34px 0 2px;max-width:80ch}
.ph h1{font:700 clamp(23px,3.3vw,30px)/1.15 var(--sans);letter-spacing:-.02em;
  margin:9px 0 0}
.ph .lede{color:var(--ink2);font-size:13.5px;line-height:1.65;margin:9px 0 0;
  max-width:68ch}
.ph .lede b{color:var(--ink)}
@media (max-width:720px){.ph{padding:22px 0 2px}}

.skip{position:absolute;left:-9999px}
.skip:focus{left:12px;top:12px;z-index:300;background:var(--g3);padding:8px 12px;
  border-radius:var(--r);outline:2px solid var(--brand)}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 28px}
@media (max-width:720px){.wrap{padding:0 14px}}

/* ============ app shell ============ */
.hd{border-bottom:1px solid var(--hair);background:rgba(6,8,10,.86);
  position:sticky;top:0;z-index:100;backdrop-filter:blur(10px);
  animation:hd-in var(--t-view) var(--e-out)}
@keyframes hd-in{from{opacity:0}}
.hd-r1{display:flex;align-items:center;gap:20px;height:52px}
/* 1024, not the 860 this used to be. The single-row nav needs about 995px of
   viewport once the wordmark is beside it, so between 861px and 1023px the
   wrap had not kicked in and the row did not fit: EVERY page on the site
   carried a horizontal scrollbar, ~110px of it, across a band that covers a
   13-inch laptop, a tablet in landscape and any half-screen window. Measured
   2026-08-28 on /verify at 870, 880, 940 and 1000px; clean at 1024 and above.
   The phone tap-target block further down deliberately stays at 860, so a
   laptop in this band gets the wrapped nav at desktop padding rather than
   40px rows it does not need. */
@media (max-width:1024px){
  /* The nav shared one row with the brand and the CTA, which left it about
     190px and pushed everything after MOVEMENT behind a horizontal scroll.
     GUIDE is last, so the one link written for a newcomer was the one they
     had to know to swipe for. Given its own full-width row it wraps instead,
     and every section is visible without discovering a gesture. */
  .hd-r1{gap:10px;flex-wrap:wrap;height:auto;padding:7px 0}
  .brand .sb{display:none}
  .hd-spacer{flex:1}
  .hd-links{order:3;flex:0 0 100%;width:100%;flex-wrap:wrap;
    overflow:visible;justify-content:flex-start}
  /* gap and link padding for this breakpoint are set AFTER the base rules
     below, not here — see the tap-target block at the end of the header
     section for why they cannot live in this one. */
  .hd-links::-webkit-scrollbar{display:none}
  .hd-spacer{display:none}
}
.brand{display:inline-flex;align-items:baseline;gap:9px}
/* The wordmark is the promo's: lowercase, tight, cool white, with the .bet in
   the one hue. The old mark was uppercase letterspaced "SOOTH" with a square
   dot, which shares nothing with the artwork the brand is actually presented
   in. The square dot survives as a small frozen pip beside it. */
.brand .mk{width:8px;height:8px;border-radius:50%;background:var(--brand);
  align-self:center;box-shadow:0 0 10px rgba(45,212,167,.55)}
.brand b{font:600 17px/1 var(--sans);letter-spacing:-.02em;color:var(--ink);
  text-transform:none}
.brand b i{font-style:normal;color:var(--brand)}
.brand .sb{font:500 8.5px/1 var(--mono);letter-spacing:.22em;color:var(--dim);
  text-transform:uppercase}
.hd-spacer{flex:1}
.hd-links{display:flex;gap:2px}
.hd-links a{font:600 12px/1 var(--sans);color:var(--mut);padding:8px 11px;
  border-radius:var(--r);
  transition:background var(--t-hover) ease,color var(--t-hover) ease}
.hd-links a:hover{color:var(--ink);background:var(--g2)}
.hd-links a[aria-current]{color:var(--brand)}

/* TAP TARGETS ON A PHONE.
   This block sits AFTER the base rules deliberately. The @media block higher
   up in this file carried `.hd-links a{padding:7px 9px}` and `gap:1px`, but
   it is written BEFORE these base rules, so at equal specificity the desktop
   padding won on every screen and those mobile values had never once applied.
   Anything here that overrides a base declaration has to stay below it.

   40px, not the 44 Apple asks for: this nav wraps to three rows on a phone,
   so every extra pixel is spent three times over on chrome that is not the
   product. 40 clears the WCAG 2.2 target-size floor of 24 with room to spare
   and costs ~29px of header. The sport row and the wordmark are cheaper and
   take what the row already allows. */
@media (max-width:860px){
  /* no row gap, so the targets tile with no dead strip between them; a small
     column gap survives because side-by-side links still need a seam */
  .hd-links{column-gap:2px;row-gap:0}
  .hd-links a{padding:14px 9px}        /* 12px line + 28 = 40 */
  .brand{padding:4px 0}                /* 20 -> 26, clears the WCAG floor */
  /* .sp is handled after its own base rule further down, same reason. */
}

/* sport switcher — second shell row, horizontal, states carry data */
.hd-r2{display:flex;align-items:center;gap:4px;height:42px;
  border-top:1px solid var(--hair);overflow-x:auto;scrollbar-width:none;
  position:relative}
.rail-ink{position:absolute;bottom:0;left:0;height:2px;background:var(--brand);
  transform-origin:left;border-radius:1px;
  transition:transform var(--t-ui) var(--e-out),width var(--t-ui) var(--e-out)}
.hd-r2::-webkit-scrollbar{display:none}
.sp{display:inline-flex;align-items:center;gap:7px;font:600 12px/1 var(--mono);
  letter-spacing:.08em;color:var(--mut);padding:7px 12px;border-radius:var(--r);
  white-space:nowrap;
  transition:background var(--t-hover) ease,color var(--t-hover) ease}
.sp:hover{color:var(--ink);background:var(--g2)}
.sp[aria-selected="true"]{color:var(--ink);background:var(--g3);
  box-shadow:inset 0 -2px 0 var(--brand)}
.sp .d{width:5px;height:5px;border-radius:50%;background:var(--up)}
.sp .d.off{background:var(--dim)}
.sp .c{font-size:10px;color:var(--dim)}
/* Tap target, and below .sp's base rule for the source-order reason spelled
   out in the header block above. .hd-r2 is a fixed 42px row that scrolls
   horizontally, so the tab can take the full height without moving anything. */
@media (max-width:860px){.sp{padding:15px 12px}}   /* 12px line + 30 = 42 */
.sp[aria-selected="true"] .c{color:var(--mut)}

/* ============ status strip ============ */
.status{display:flex;align-items:baseline;gap:34px;flex-wrap:wrap;
  padding:26px 0 22px}
.stat .v{font:600 26px/1 var(--mono);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;
  background:linear-gradient(180deg,#FFFFFF 0%,#D9DDE4 55%,#9AA1AC 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 2px 2px rgba(0,0,0,.55))}
.stat .v small{font-size:14px;color:var(--mut);font-weight:500}
.stat .tl{margin-top:7px;display:block}
.status .live{margin-left:auto;display:flex;align-items:center;gap:8px}
.pulse{width:6px;height:6px;border-radius:50%;background:var(--up)}
@keyframes pulse{50%{opacity:.35}}
.pulse.on{animation:pulse 2.4s ease infinite}
.pulse.stale{background:var(--amber);animation:none}
.pulse.dead{background:var(--dn);animation:none}

/* ============ section machinery ============ */
.sec{border-top:1px solid var(--hair);padding:20px 0 30px}
.sec-h{display:flex;align-items:baseline;gap:14px;margin-bottom:18px}
.sec-h .tl{color:var(--mut)}
.sec-h .sub{font:400 12px/1 var(--sans);color:var(--dim)}
.sec-h .more{margin-left:auto;font:600 11px/1 var(--mono);letter-spacing:.08em;
  color:var(--dim)}
.sec-h .more:hover{color:var(--brand)}

/* ---- depth: every instrument surface is a slab of dark glass, lit along its
        top edge and sitting on an ambient shadow — the block in the promo.
        One recipe, shared, so the light source is coherent. Rule 3. */
.radar,.feed,.itab,.mkt,.ws-grid{
  background:linear-gradient(180deg,#141B22 0%,#0E141A 55%,#0A0F14 100%);
  box-shadow:inset 0 1px 0 rgba(190,240,245,.10),
             inset 0 -1px 0 rgba(0,0,0,.55),
             0 18px 40px -22px rgba(0,0,0,.9),
             0 2px 8px -2px rgba(0,0,0,.55)}
.radar-side{background:linear-gradient(180deg,rgba(0,0,0,.22),rgba(0,0,0,.05));}

/* ============ THE ROOM — REMOVED, and why ============
   assets/env.jpg was mounted here as a masthead behind every page. It is gone,
   and the reasoning is worth keeping so it is not reinvented a fourth time.

   Three variants were shipped and all three failed the same way:

     1. per-page cropped bands — each page showed a different slice of a
        different plate, ending on a hard rectangular edge;
     2. a full-page fixed wash — dimmed far enough to be safe behind live data,
        a photograph stops being anything at all;
     3. this masthead band — 440px measured from the header, on pages whose
        content starts wherever it starts. On /gamelog the table begins around
        175px and cut the plate flat across the middle; the ice read as a
        rectangle floating over the filter row.

   The common cause is not tuning. It is that a photographic plate behind a
   dense data page is sliced by boundaries that know nothing about it — an
   opaque table, a control row, a section rule. It only ever looked right on
   pages that happen to open with a tall left-hand masthead and empty space on
   the right, which is a property of two or three pages, not of the site.

   Ice still carries the identity, in the two places it can:
     · the landing hero, which is COMPOSED around the render — the block sits
       right of centre because the headline occupies the dark left third;
     · the --frost tokens and the .frost / .frosted primitives below, which
       mark the sealed state wherever it is genuinely true.

   Putting a render on any other page means designing that page around it and
   reserving the space, per page. It is not a stylesheet-level treatment. */

/* ============ FROST — the sealed state ============
   Rule 2: committed-but-not-yet-revealed is rendered as ice. The chip below
   is the atom; .frosted is the same treatment applied to a whole surface.

   The crystalline edge is two hard-stopped linear gradients crossing at 60°,
   which reads as facets rather than as a blur. No images: this has to survive
   inside an email-safe stylesheet and on a phone on a bad connection. */
.frost{display:inline-flex;align-items:center;gap:6px;
  font:600 9.5px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--frost);padding:4px 9px;border:1px solid var(--frost-rim);
  background:
    linear-gradient(115deg,rgba(191,234,242,.16) 0 18%,transparent 18% 34%,
      rgba(191,234,242,.10) 34% 44%,transparent 44%),
    linear-gradient(180deg,rgba(191,234,242,.13),rgba(191,234,242,.03));
  box-shadow:inset 0 1px 0 rgba(220,248,255,.28),0 0 14px rgba(191,234,242,.10)}
.frost::before{content:"";width:5px;height:5px;flex:0 0 auto;
  background:var(--frost);transform:rotate(45deg);
  box-shadow:0 0 7px rgba(191,234,242,.7)}
/* a whole surface under ice — locked slates, unrevealed rows */
.frosted{position:relative;border:1px solid var(--frost-rim)!important;
  background:
    linear-gradient(126deg,rgba(191,234,242,.055) 0 22%,transparent 22% 41%,
      rgba(191,234,242,.035) 41% 52%,transparent 52%),
    linear-gradient(180deg,#101a20,#0A1116)!important;
  box-shadow:inset 0 1px 0 rgba(220,248,255,.16),
             0 0 34px -12px rgba(191,234,242,.22)!important}
/* the lit rim from the logo: a hairline that catches the light on one side */
.rimlit{position:relative}
.rimlit::after{content:"";position:absolute;left:0;right:0;top:0;height:1px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(45,212,167,.55) 22%,
    rgba(91,240,212,.75) 50%,rgba(45,212,167,.55) 78%,transparent)}

/* ============ the promo's bullet ============
   ▸ PRICES AS LAST CAPTURED / ▸ AI ANALYSIS — a teal triangle, mono caps, wide tracking.
   This is the list style for anything that names a capability. */
.caps{list-style:none;margin:0;padding:0}
.caps li{position:relative;padding:7px 0 7px 17px;
  font:600 10.5px/1.4 var(--mono);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink2)}
.caps li::before{content:"";position:absolute;left:0;top:11px;
  border:4px solid transparent;border-left-color:var(--brand)}

/* raised keys — controls you can press read as physically raised */
.an-in button{
  background:linear-gradient(180deg,#F3EFE6,#DCD6C9);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),
             inset 0 -1px 0 rgba(0,0,0,.25),
             0 3px 8px -2px rgba(0,0,0,.6)}
.an-in button{transition:filter var(--t-hover) ease,
  transform var(--t-view) var(--e-out)}
.an-in button:active{transition-duration:var(--t-press);
  transform:translateY(1px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 3px -1px rgba(0,0,0,.6)}
.sp[aria-selected="true"]{
  background:linear-gradient(180deg,#232730,#1A1D24);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.09),
             0 3px 10px -4px rgba(0,0,0,.7),
             inset 0 -2px 0 var(--brand)}
.an-chip{background:linear-gradient(180deg,rgba(255,255,255,.03),rgba(0,0,0,.12));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 6px -3px rgba(0,0,0,.5)}
.mv-row{transition:transform .12s ease,background .12s ease}
a.mv-row:hover{transform:translateY(-1px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 8px 18px -12px rgba(0,0,0,.9)}

/* inset grooves — measurement rails are carved into the surface */
.gaptrk{background:linear-gradient(180deg,rgba(0,0,0,.55),rgba(255,255,255,.04));
  box-shadow:inset 0 1px 2px rgba(0,0,0,.7),0 1px 0 rgba(255,255,255,.04);
  height:4px}
.gaptrk i{background:linear-gradient(180deg,var(--brand-hi),var(--brand));
  box-shadow:0 0 6px rgba(45,212,167,.35);height:4px}

/* ============ THE MARKET — price spectrum ============ */
.spec{width:100%}
.spec-scroll{overflow-x:auto;scrollbar-width:thin}
.spec svg{width:100%;display:block;overflow:visible}
.spec .track{stroke:var(--hair2);stroke-width:1}
.spec .tick{stroke:var(--hair);stroke-width:1}
.spec .bk{fill:var(--mut)}
.spec .bk.best{fill:var(--up)}
.spec .bk-lb{font:600 9.5px var(--mono);fill:var(--dim);letter-spacing:.04em}
.spec .bk-pr{font:600 10.5px var(--mono);fill:var(--ink2)}
.spec .bk.best+g .bk-pr, .spec .g-best .bk-pr{fill:var(--up)}
.spec .fair{stroke:var(--ink2);stroke-width:1;stroke-dasharray:2 3}
.spec .fair-lb{font:600 9.5px var(--mono);fill:var(--mut);letter-spacing:.1em}
.spec .fair-pr{font:700 11px var(--mono);fill:var(--ink)}
/* THE SPECTRUM ON A PHONE.
   It used to hold a 560px floor and scroll in place — the last horizontal
   scroller carrying data on the site, and hiding stats sideways is exactly
   what we were told to stop doing.

   Scaling it to fit does not work either: measured at 375px the whole
   instrument renders at about 0.54, and pushing the labels back up to a
   legible size makes them collide (5 clusters, 1 overlap at 20 user units).
   With eleven books there is no size that is both legible and collision-free
   in 347px.

   So drop what the phone cannot carry and keep what the instrument is FOR.
   The per-book price labels are the part that collides — and they are the one
   part fully duplicated by the SPORTSBOOK COMPARISON table directly below,
   which now stacks into readable cards. What the table cannot show is the
   SHAPE: how far apart the books are and where the de-vigged fair price sits
   among them. Everything that carries the shape survives untouched — the pins,
   their ground shadows and the receding plane are unclassed geometry — along
   with the FAIR label and the BEST price, which stays printed because hiding
   it would remove the one figure the instrument exists to point at. Nothing is
   hidden off-screen and no number is lost: the rest moved to the surface that
   can render it properly.

   (The .track/.tick/.fair/.bk rules below are for the FLAT spectrum variant;
   the perspective-deck variant on /game draws unclassed geometry instead, so
   they are a no-op there rather than the thing doing the work.) */
@media (max-width:720px){
  .spec svg{min-width:0}
  .spec-scroll{overflow-x:visible}
  .spec .bk-lb,.spec .bk-pr{display:none}
  /* ...except the best price, which is the point of the instrument */
  .spec .g-best .bk-pr{display:inline;font-size:20px}
  .spec .fair-lb{font-size:17px}
  .spec .fair-pr{font-size:19px}
  .spec .track,.spec .tick,.spec .fair{stroke-width:1.8}
  .spec .bk{r:4}
}.spec-cap{display:flex;justify-content:space-between;margin-top:6px}
.spec-cap .tl b{color:var(--ink2)}

/* ============ market radar ============ */
.radar{display:grid;grid-template-columns:1fr 340px;gap:0;
  border:1px solid var(--hair);border-radius:var(--r);background:var(--g1)}
.radar-main{padding:22px 26px 24px;min-width:0;
  background:radial-gradient(620px 190px at 42% 66%,rgba(255,255,255,.035),transparent 70%)}
.radar-side{border-left:1px solid var(--hair);padding:22px 24px;
  display:flex;flex-direction:column;gap:0}
.radar-mu{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin:10px 0 4px}
.radar-mu .tm{font:700 21px/1.15 var(--sans);letter-spacing:-.015em}
.radar-mu .at{font:500 12px var(--mono);color:var(--dim)}
.radar-mu .ko{font:500 11px var(--mono);color:var(--mut);margin-left:auto}
.radar .spec{margin-top:22px}
.kv{display:flex;justify-content:space-between;align-items:baseline;
  padding:9px 0;border-bottom:1px solid var(--hair)}
.kv:last-child{border-bottom:0}
.kv .k{font:500 11px var(--mono);letter-spacing:.06em;color:var(--mut)}
.kv .v{font:600 13px var(--mono);color:var(--ink)}
.kv .v.up{color:var(--up)} .kv .v.dn{color:var(--dn)} .kv .v.dim{color:var(--dim)}
@media (max-width:900px){.radar{grid-template-columns:1fr}
  .radar-side{border-left:0;border-top:1px solid var(--hair)}}

/* ============ movers feed ============ */
.feed{border:1px solid var(--hair);border-radius:var(--r);background:var(--g1)}
.mv-row{display:grid;grid-template-columns:34px 1fr auto;gap:14px;
  align-items:center;padding:13px 18px;border-bottom:1px solid var(--hair)}
.mv-row:last-child{border-bottom:0}
a.mv-row:hover{background:var(--g2)}
.mv-rank{font:600 12px var(--mono);color:var(--dim)}
.mv-hl{font:600 13px/1.35 var(--sans);color:var(--ink)}
.mv-hl .pts{font-family:var(--mono);margin-left:8px}
.mv-hl .pts.up{color:var(--up)} .mv-hl .pts.dn{color:var(--dn)}
.mv-hl .pts.am{color:var(--amber)}
.mv-sub{display:block;font:400 12px/1.4 var(--sans);color:var(--mut);margin-top:3px;max-width:72ch}
.mv-meta{font:500 10.5px var(--mono);color:var(--dim);text-align:right;white-space:nowrap}

/* ============ intelligence table ============ */
.itab{border:1px solid var(--hair);border-radius:var(--r);background:var(--g1);
  overflow:hidden}
.itab .scr{overflow-x:auto}
.itab table{width:100%;border-collapse:collapse;min-width:760px}
.itab thead th{position:sticky;top:0;background:var(--g2);text-align:right;
  padding:9px 14px;border-bottom:1px solid var(--hair2);white-space:nowrap;
  font:600 9.5px var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);z-index:1}
.itab th.l,.itab td.l{text-align:left}
.itab tbody td{padding:10px 14px;text-align:right;border-bottom:1px solid var(--hair);
  font:500 12.5px var(--mono);color:var(--ink2);white-space:nowrap}
.itab tbody tr:last-child td{border-bottom:0}
.itab tbody tr[data-href]{cursor:pointer}
.itab tbody td{transition:background var(--t-hover) ease}
.itab tbody tr[data-href]:hover td{background:var(--g2)}
.itab .mu{font:600 13px var(--sans);color:var(--ink);letter-spacing:-.01em}
.itab .mu .at{color:var(--dim);font-weight:400;font-size:11px;margin:0 5px}
.itab .bkk{font-size:10px;color:var(--dim);margin-left:6px}
.itab .up{color:var(--up)} .itab .dn{color:var(--dn)} .itab .dim{color:var(--dim)}
.gaptrk{display:inline-block;width:56px;height:3px;background:var(--hair);
  border-radius:2px;vertical-align:2px;margin-left:8px;position:relative}
.gaptrk i{position:absolute;left:0;top:0;height:3px;border-radius:2px;
  background:var(--up);display:block}

/* ---- the same table, on a phone ------------------------------------------
   A seven-column instrument table has a 760px floor. In a 375px viewport that
   is a horizontal scroller holding 415px of hidden content — and what is
   hidden is every number on the page. The matchup column stays visible and
   the entire product goes off-screen to the right.

   So below 720px the table stops being a table. Each row becomes a card and
   each cell becomes a labelled line, with the column header supplied as
   `data-l` by Desk.stack(). Nothing is truncated, nothing scrolls sideways,
   and the reading order is the same one the markup already had. */
@media (max-width:720px){
  .itab{border-radius:0;border-left:0;border-right:0;background:none}
  .itab .scr{overflow-x:visible}
  .itab table{min-width:0;width:100%;display:block}
  .itab thead{display:none}
  .itab tbody,.itab tbody tr,.itab tbody td{display:block;width:auto}
  .itab tbody tr{border:1px solid var(--hair);background:var(--g1);
    padding:11px 13px 3px;margin:0 0 8px}
  .itab tbody tr:last-child{margin-bottom:0}
  .itab tbody td{padding:6px 0;text-align:right;white-space:normal;
    border-bottom:1px solid var(--hair);
    display:flex;align-items:baseline;justify-content:space-between;gap:14px}
  .itab tbody tr td:last-child{border-bottom:0}
  .itab tbody td::before{content:attr(data-l);flex:0 0 auto;text-align:left;
    font:600 9.5px var(--mono);letter-spacing:.11em;text-transform:uppercase;
    color:var(--dim)}
  /* An unlabelled cell — always the first, sometimes a colspan — is a
     full-width title line for the card, so the row keeps its identity. */
  .itab tbody td:not([data-l])::before{content:none}
  .itab tbody td:not([data-l]){display:block;text-align:left;padding-bottom:9px}
  .itab tbody tr:hover td{background:none}
  /* the price spectrum is a fixed-width instrument; let it size down instead
     of forcing the card wider than the screen */
  .itab .spec,.itab svg{max-width:100%}
  .itab .mu{font-size:14px}
}

/* ============ lede + progressive disclosure ============
   Several pages opened with 1,500–1,800 characters of dense argument before
   the first number. On a desktop that reads as rigour; on a phone it is four
   full screens of scrolling to reach the thing the visitor came for. The lede
   carries the position and the disqualifying figure — the two sentences that
   must never be buried — and the rest moves behind a disclosure the reader
   opens on purpose. Nothing is deleted; the order is fixed. */
.lede{color:var(--ink2);font-size:14px;line-height:1.65;margin:12px 0 0;max-width:70ch}
.lede b{color:var(--ink)}
.lede a{color:var(--brand);text-decoration:none;white-space:nowrap}
.lede a:hover{text-decoration:underline;text-underline-offset:2px}
details.more{margin:14px 0 0;max-width:86ch}
details.more>summary{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  font:600 10.5px var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--mut);padding:7px 0;list-style:none;
  transition:color var(--t-hover) ease}
details.more>summary::-webkit-details-marker{display:none}
details.more>summary::before{content:"+";font-size:13px;line-height:1;
  color:var(--dim);width:11px;text-align:center}
details.more[open]>summary::before{content:"\2212"}
details.more>summary:hover{color:var(--ink2)}
details.more>summary:hover::before{color:var(--brand)}
details.more>*+*{margin-top:10px}

/* ============ states ============ */
.state{padding:34px 22px;text-align:center;color:var(--mut);font-size:13px}
.state .tl{display:block;margin-bottom:8px}
.shimmer{height:10px;border-radius:2px;background:linear-gradient(90deg,
  var(--g2) 25%,var(--g3) 50%,var(--g2) 75%);background-size:200% 100%;
  animation:shim 1.4s linear infinite;margin:14px 18px}
@keyframes shim{to{background-position:-200% 0}}
.notice{display:flex;gap:10px;align-items:baseline;font-size:12.5px;
  color:var(--mut);border-left:2px solid var(--amber);background:var(--amber-dim);
  padding:10px 14px;border-radius:0 var(--r) var(--r) 0;margin:0 0 18px;
  line-height:1.5}
.notice b{color:var(--ink2)}

/* ============ workspace (game page) ============ */
.ws-crumb{padding:20px 0 0}
.ws-head{display:grid;grid-template-columns:1fr auto 1fr;gap:20px;
  align-items:center;padding:26px 0 8px;text-align:center}
.ws-head .side{min-width:0}
.ws-head .side.a{text-align:right}.ws-head .side.h{text-align:left}
.ws-head .nm{font:700 clamp(17px,2.4vw,24px)/1.2 var(--sans);letter-spacing:-.02em}
.ws-head .rl{font:500 10px var(--mono);letter-spacing:.14em;color:var(--dim);
  text-transform:uppercase;margin-top:4px;display:block}
.ws-mid .fair-big{font:700 30px/1 var(--mono);letter-spacing:-.02em;
  background:linear-gradient(180deg,#FFFFFF 0%,#D9DDE4 55%,#9AA1AC 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.6))}
.ws-mid .tl{display:block;text-align:center;margin-top:7px}
@media (max-width:640px){.ws-head{grid-template-columns:1fr;gap:8px}
  .ws-head .side.a,.ws-head .side.h{text-align:center}}
.ws-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border:1px solid var(--hair);border-radius:var(--r);background:var(--g1);
  margin:20px 0}
.ws-cell{padding:14px 16px;border-right:1px solid var(--hair)}
.ws-cell:last-child{border-right:0}
.ws-cell .v{font:600 17px/1 var(--mono);color:var(--ink);margin-top:6px}
.ws-cell .v small{font-size:11px;color:var(--mut)}
.ws-cell .v.up{color:var(--up)}
@media (max-width:900px){.ws-cell{border-bottom:1px solid var(--hair)}}

/* market block: one side's spectrum + ladder */
.mkt{border:1px solid var(--hair);border-radius:var(--r);background:var(--g1);
  padding:18px 22px 20px;margin-bottom:14px}
.mkt .sec-h{margin-bottom:8px}

/* analyst drawer */
.an-chips{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0 0}
.an-chip{font:600 10.5px var(--mono);letter-spacing:.08em;color:var(--mut);
  border:1px solid var(--hair2);padding:7px 11px;border-radius:var(--r)}
.an-chip{transition:color var(--t-hover) ease,border-color var(--t-hover) ease,
  filter var(--t-hover) ease}
.an-chip:hover{color:var(--brand);border-color:var(--brand)}
.an-out{border-left:2px solid var(--brand);background:var(--g1);
  padding:14px 18px;margin-top:14px;font-size:13px;line-height:1.65;
  color:var(--ink2);max-width:88ch}
.an-out:empty{display:none}
.an-out p{margin:0 0 4px}
.an-out .brk{display:block;height:8px}
.an-out b{color:var(--ink);font-weight:650}
.an-out ul{margin:2px 0 8px;padding-left:18px}
.an-out li{margin:0 0 4px}
.an-out .od{font-family:var(--mono);color:var(--ink);
  font-variant-numeric:tabular-nums}
.an-out .gn{font-family:var(--mono);color:var(--up);
  font-variant-numeric:tabular-nums}
.an-out .gnd{font-family:var(--mono);color:var(--dn);
  font-variant-numeric:tabular-nums}
.ans-card{background:linear-gradient(180deg,#15181D 0%,#101216 55%,#0D0F12 100%);
  border:1px solid var(--hair);border-radius:var(--r);padding:16px 20px 12px;
  margin-top:14px;max-width:880px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 14px 34px -20px rgba(0,0,0,.85)}
.ans-card .kv .v{font-size:12.5px}
.an-in{display:flex;gap:8px;margin-top:12px}
.an-in input{flex:1;background:var(--g2);border:1px solid var(--hair2);
  border-radius:var(--r);color:var(--ink);padding:9px 12px;font:13px var(--sans)}
.an-in input::placeholder{color:var(--dim)}
.an-in button{font:700 12px var(--sans);color:var(--g0);background:var(--brand);
  padding:0 16px;border-radius:var(--r)}

/* timeline */
.tml svg{width:100%;display:block}
.tml .ln{fill:none;stroke:var(--brand);stroke-width:1.5}
.tml .ln2{fill:none;stroke:var(--dim);stroke-width:1;stroke-dasharray:3 3}
.tml .ax{display:flex;justify-content:space-between;margin-top:4px}

/* research: computed facts + opposed form bars */
.facts{margin:0;padding:0;list-style:none;max-width:86ch}
.facts li{position:relative;padding:7px 0 7px 16px;font-size:13px;color:var(--ink2);
  line-height:1.5;border-bottom:1px solid var(--hair)}
.facts li:last-child{border-bottom:0}
.facts li::before{content:"";position:absolute;left:0;top:14px;width:4px;height:4px;
  border-radius:50%;background:var(--dim)}
.facts li.k-price_gap::before,.facts li.k-line_move::before{background:var(--up)}
.cmp{display:flex;flex-direction:column;gap:8px}
.cmp .rw{display:grid;grid-template-columns:52px 1fr 52px;gap:8px;align-items:center}
.cmp .lb{grid-column:1/-1;font:600 9.5px var(--mono);letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim);margin-bottom:-4px}
.cmp .n{font:500 11.5px var(--mono);color:var(--mut)}
.cmp .n.r{text-align:right}
.cmp .n.win{color:var(--ink);font-weight:700}
.cmp .tw{display:flex;height:5px;gap:2px}
.cmp .h{flex:1;position:relative;border-radius:2px;
  background:linear-gradient(180deg,rgba(0,0,0,.5),rgba(255,255,255,.04));
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6)}
.cmp .h i{position:absolute;top:0;height:5px;border-radius:2px;display:block;
  background:linear-gradient(180deg,#6B7280,#4B5563)}
.cmp .h.b i{left:0;background:linear-gradient(180deg,var(--brand-hi),var(--brand));
  box-shadow:0 0 5px rgba(45,212,167,.3)}
.cmp .h.a i{right:0}
/* diverging form cell on the board */
.fm{display:inline-flex;align-items:center;gap:8px}
.fm .who{font:700 10.5px var(--mono);color:var(--ink2);min-width:28px;text-align:right}
.fm .tr{position:relative;width:64px;height:5px;border-radius:2px;flex:none;
  background:linear-gradient(180deg,rgba(0,0,0,.5),rgba(255,255,255,.04));
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6)}
.fm .tr::after{content:"";position:absolute;left:50%;top:-2px;width:1px;height:9px;
  background:var(--hair2)}
.fm .fl{position:absolute;top:0;height:5px;border-radius:2px;
  background:linear-gradient(180deg,var(--brand-hi),var(--brand))}
.fm .fl.away{background:linear-gradient(180deg,#8A919D,#5A6170)}

/* footer */
/* The compliance floor was the LEAST readable text on every page: --dim on
   --g0 at 11.5px measures 3.18:1, under AA. The one paragraph that has to be
   read — not accepting wagers, past performance, 21+ — was harder to read than
   any number on the board. --mut is 5.84:1 on the same ground, and the bold
   runs go a step brighter again. */
.ft{border-top:1px solid var(--hair);margin-top:44px;padding:26px 0 40px;
  color:var(--mut);font-size:11.5px;line-height:1.7}
.ft b{color:var(--ink2)}
.ft a{color:var(--mut)} .ft a:hover{color:var(--ink)}
.ft .links{display:flex;gap:18px;flex-wrap:wrap;margin-top:10px}
/* Tap target: 7px each side takes a 20px line to 34px, clearing the WCAG 2.2
   floor of 24. These anchors are flex items of .ft .links, NOT inline, so
   they are blockified and the padding does reserve space — the footer grows
   about 28px. That is a footer, so it is a cheap place to spend it, but do
   not repeat this trick somewhere the height matters and expect it to be
   free. The 18px gap sits between the padded boxes, so no row can steal a
   click from the one above it. */
.ft .links a{padding:7px 0}

/* The guide is an entry point, not a peer of the board sections. It reads
   quieter than a section until hovered, so it is findable by someone looking
   for help without competing for the attention of someone who is not. */
.hd-links a.hd-new{color:var(--mut)}
.hd-links a.hd-new::before{content:"?";display:inline-block;margin-right:5px;
  width:13px;height:13px;line-height:13px;text-align:center;border-radius:50%;
  border:1px solid currentColor;font-size:9px;font-weight:700;vertical-align:1px}
.hd-links a.hd-new:hover{color:var(--brand)}

/* ============ pick engine ============ */
.seal-badge{display:inline-flex;align-items:center;gap:6px;
  font:600 10px var(--mono);letter-spacing:.1em;color:var(--up);
  border:1px solid rgba(45,212,167,.35);background:var(--up-dim);
  padding:4px 9px;border-radius:var(--r)}
.seal-badge{transition:filter var(--t-hover) ease}
.seal-badge:hover{filter:brightness(1.15)}
.clv{font:600 10px var(--mono);letter-spacing:.05em;padding:2px 6px;
  border-radius:var(--r);border:1px solid var(--hair2);
  font-variant-numeric:tabular-nums}
.clv.pos{color:var(--up);border-color:rgba(45,212,167,.35);background:var(--up-dim)}
.clv.neg{color:var(--dn);border-color:rgba(255,107,107,.35);background:var(--dn-dim)}
.clv.na{color:var(--dim)}
.noplay{border-left:2px solid var(--brand);background:var(--brand-dim);
  padding:12px 16px;border-radius:0 var(--r) var(--r) 0;font-size:13px;
  color:var(--ink2);margin:0 0 16px;max-width:80ch;line-height:1.6}

/* ============ embedded (inside a desk monitor) ============
   Milestone 2: inside a monitor the page is an instrument screen, not an
   article. Editorial headers collapse to instrument strips; density leads. */
.embedded body{padding-top:4px}
.embedded .skip{display:none}
.embedded .wrap{padding:0 18px 28px}
/* the instrument strip every embedded screen leads with */
.scr-strip{display:none}
.embedded .scr-strip{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:10px 2px 8px;border-bottom:1px solid var(--hair);margin-bottom:10px}
.embedded .scr-strip .nm{font:700 11px var(--mono);letter-spacing:.22em;color:var(--ink)}
.embedded .scr-strip .tl b{color:var(--ink2)}
/* editorial furniture yields inside the monitor */
.embedded .ph,.embedded .page-head{display:none}
.embedded .sec{padding-top:12px;margin-top:0}
.embedded h1{font-size:18px}

/* the way home for a monitor that navigated deeper */
.embedded .embed-back{position:sticky;top:6px;z-index:50;margin:6px 0 0 6px;
  font:600 10px var(--mono);letter-spacing:.1em;color:var(--mut);
  background:rgba(16,18,22,.92);border:1px solid var(--hair2);
  border-radius:var(--r);padding:7px 12px;cursor:pointer;
  transition:color var(--t-hover) ease,border-color var(--t-hover) ease}
.embedded .embed-back:hover{color:var(--brand);border-color:var(--brand)}

/* ---------- the phone tab bar ----------
   index.html's own note calls this "the one element that makes this read as
   an app", and until now it was the only page that had one: every tab took
   the visitor out of the app and onto a plain page whose only way back was
   the browser's own button. desk.js injects this on every non-embedded
   screen so the bar survives the tap.

   index.html carries a second copy of these rules because it deliberately
   does not load this file (see its FROZEN MARKET note). Change one, change
   both — they are the same component wearing two stylesheets. */
.m-tabs{display:none}
@media (max-width:859px){
  .m-tabs{position:fixed;left:0;right:0;bottom:0;z-index:60;display:flex;
    background:rgba(6,8,10,.94);backdrop-filter:blur(12px);
    border-top:1px solid var(--hair2);
    padding-bottom:env(safe-area-inset-bottom,0px)}
  .m-tabs a{flex:1;display:flex;flex-direction:column;align-items:center;
    justify-content:center;gap:5px;min-height:48px;padding:9px 2px 8px;
    font:600 8.5px var(--mono);letter-spacing:.1em;color:var(--mut);
    /* --mut, not --dim: --dim on this ground is 3.2:1, under AA for text,
       and this is primary navigation rather than faint metadata. */
    text-decoration:none;transition:color var(--t-hover) ease}
  /* The current tab wears a lit rule as well as the hue. Colour alone would
     be the only thing separating it, which is exactly the cue a colourblind
     visitor does not get. */
  .m-tabs a[aria-current]{color:var(--brand);
    box-shadow:inset 0 2px 0 var(--brand)}
  .m-ti{width:16px;height:16px;border:1.5px solid currentColor;position:relative}
  /* each glyph is drawn from the same square so the row stays optically even */
  .m-ti[data-i="board"]{border-width:1.5px 1.5px 5px 1.5px}
  .m-ti[data-i="picks"]{border-radius:50%}
  .m-ti[data-i="picks"]::after{content:"";position:absolute;inset:3px;
    border:1.5px solid currentColor;border-radius:50%}
  .m-ti[data-i="proof"]{border-width:1.5px;border-left-width:5px}
  .m-ti[data-i="ask"]{border-radius:3px}
  .m-ti[data-i="ask"]::after{content:"";position:absolute;left:3px;bottom:-4px;
    border:3px solid transparent;border-top-color:currentColor}
  .m-ti[data-i="alerts"]{border-radius:50% 50% 3px 3px;border-bottom-width:4px}
  /* the bar is fixed, so the end of the page has to clear it — otherwise it
     sits on top of the compliance line, which is the one line that may
     never be covered */
  body{padding-bottom:calc(66px + env(safe-area-inset-bottom,0px))}
}
