/* INSERT COIN — racing-telemetry aesthetic.
   Discipline: ONE accent (signal orange) for brand and live state. Green/red are
   reserved strictly for price direction and never used decoratively. Everything
   else is neutral. Density over decoration; type does the hierarchy, not colour. */

/* ═══════════════════════════════════════════════════════════════════════════
   THE TOKEN LAYER.

   Eight stylesheets are written against these names by people who never read
   each other's files, so every value that more than one of them could plausibly
   need lives here and nowhere else. If you are about to type a literal into
   floor.css / crash.css / arcade.css / meta.css / audio.css / onboarding.css /
   chat.css, the answer is almost always a token from this block.

   Audited before this pass: 88 distinct rgba() literals, 45 distinct font-sizes,
   21 radii, 63 shadows and 37 transition durations across the eight files — for
   a palette of three colours, which is what "assembled" rather than "designed"
   actually looks like from the inside.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  /* ── surfaces: four levels, in stacking order ────────────────
     page → recessed well → card → raised (hover / active / nested). A dark UI
     needs the ladder to be explicit; borrowing a lighter grey ad hoc is how a
     card ends up on the same plane as the thing it is supposed to sit above. */
  --bg:#0a0a0c; --bg-1:#0e0e11; --surface:#121216; --surface-2:#16161b;
  --line:#1e1e25; --line-2:#2a2a34; --line-3:#3a3a48;
  --bg-rgb:10,10,12; --bg1-rgb:14,14,17; --surface-rgb:18,18,22;
  /* Glass and scrim. There were four modal backdrops on this site — .72, .78,
     .82 and .86 of the same near-black — which means the page dimmed by a
     different amount depending on which agent wrote the sheet. One value. */
  --glass:rgba(var(--bg-rgb),.72);   /* sticky bars over content */
  --scrim:rgba(6,6,8,.82);           /* anything modal */

  /* ── text: four steps, all of them legible ───────────────────
     Measured against --bg and against --surface-2, the lightest ground a label
     can land on. The bottom two used to be --dim #75747f (4.30:1 on --bg, 3.92
     on --surface-2) and --dim-2 #4e4d57 (2.38:1 / 2.17), and --dim-2 carries the
     10px uppercase keys on the pot strip, the fairness panel, the rig board and
     the crash proof — small text, so the bar is 4.5:1, and it was under half of
     it. Raised until every step clears 4.5:1 on every surface. Still four
     visibly distinct steps; the bottom one is now a colour rather than a
     rumour. */
  --txt:#f2f1ee;    /* 17.51:1 on --bg   15.96:1 on --surface-2 */
  --txt-2:#a8a7b3;  /*  8.33:1           7.59:1 */
  --dim:#94939f;    /*  6.53:1           5.95:1   (was 4.30 / 3.92) */
  --dim-2:#807f8c;  /*  5.02:1           4.58:1   (was 2.38 / 2.17) */
  --txt-rgb:242,241,238;

  /* ── the one accent, and the two directions ──────────────────
     Orange is brand and live state. GREEN AND RED MEAN PRICE DIRECTION AND
     NOTHING ELSE — never "success", never "danger", never decoration. Violet
     for real money lives in onboarding.css and is deliberately none of these.
     The -rgb channel forms exist so a tint can be written as
     rgba(var(--up-rgb),.12) instead of re-typing 47,217,127 for the 91st time. */
  --acc:#ff7a1a; --acc-soft:rgba(255,122,26,.13); --acc-line:rgba(255,122,26,.42);
  --up:#2fd97f; --down:#ff4d5e; --hold:#c9c8d2;
  --acc-rgb:255,122,26; --up-rgb:47,217,127; --down-rgb:255,77,94;
  --shade-rgb:0,0,0; --light-rgb:255,255,255;
  /* hover states, and the dark ink that goes ON a saturated fill */
  --acc-hi:#ff8c3a; --up-hi:#4ae89a; --down-hi:#ff6f83;
  --on-acc:#0a0a0c;  /* 7.58:1 on --acc  */
  --on-up:#06180f;   /* 9.91:1 on --up   */
  --on-down:#1a060c; /* 6.02:1 on --down */
  /* --down at full saturation is 6.10:1 on --bg but only ~2.9:1 on its own 9%
     tint, which is the ground the bust chips and the trap tiles actually sit on.
     This is --down lightened until it clears there: 8.78:1 on --bg, 7.84:1 on
     the tint. Two files had independently arrived at the same hex. */
  --down-txt:#ff8a95;
  /* Two more that are neither brand nor direction, so they cannot borrow one.
     --warn is the near-miss amber; --info the neutral-outcome blue. */
  --warn:#ffc247; --info:#7fb3ff;
  --warn-rgb:255,194,71; --info-rgb:127,179,255;

  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
  --mono:ui-monospace,"SF Mono","JetBrains Mono","Cascadia Mono",Menlo,Consolas,monospace;

  /* ── type scale ──────────────────────────────────────────────
     Eleven steps replacing forty-five sizes. The small band was nine distinct
     values inside 5.5px — 9/9.5/10/10.5/11/11.5/12/12.5/13 — which is not a
     scale, it is nine people each nudging by half a pixel. Steps are chosen so
     the most-used values ARE the scale: nothing moves by more than 0.5px in the
     band that carries the labels, and --fs-base stays exactly the body size. */
  --fs-micro:9.5px;   /* uppercase keys, tracking-out, the floor of the system */
  --fs-mini:10.5px;   /* mono captions, tags, sub-rows */
  --fs-xs:11.5px;     /* meta chips, hints, secondary mono */
  --fs-sm:12.5px;     /* notes, small body */
  --fs-md:13.5px;     /* dense UI text, table cells, buttons */
  --fs-base:15px;     /* body */
  --fs-lg:17px;
  --fs-xl:19px;
  --fs-2xl:22px;
  --fs-3xl:26px;
  --fs-4xl:32px;
  --fs-5xl:40px;
  /* Per-component hero numbers (the crash multiplier, the limbo climb) stay on
     their own clamp() — they are tuned against a specific box, not to a scale. */

  /* ── spacing ─────────────────────────────────────────────────
     A 4/6/8/10/12/14/16/20/26/34 ladder: dense at the bottom because this UI is
     dense at the bottom, and it is the ladder the existing values already
     cluster on. */
  --sp-1:4px; --sp-2:6px; --sp-3:8px; --sp-4:10px; --sp-5:12px;
  --sp-6:14px; --sp-7:16px; --sp-8:20px; --sp-9:26px; --sp-10:34px;

  /* ── radius ──────────────────────────────────────────────────
     Six steps for twenty-one values. --r-1 is the 2–3px bar cap, --r-5 the card,
     --r-6 the sheet. Cards move 12px → 14px, which is the only visible change. */
  --r-1:2px; --r-2:4px; --r-3:7px; --r-4:10px; --r-5:14px; --r-6:20px;
  --r-pill:999px;

  /* ── elevation ───────────────────────────────────────────────
     Four levels. Nothing that animates gets one of these: a large blur on a
     moving element is the single most expensive thing on this page, and the
     floor was taken from 25.3ms to 3.9ms a frame by removing exactly that class
     of effect. Glows are a component's own business and stay local. */
  --sh-1:0 1px 3px rgba(var(--shade-rgb),.4);      /* pressed-in / seated */
  --sh-2:0 10px 30px rgba(var(--shade-rgb),.5);    /* popover, toast */
  --sh-3:0 18px 48px rgba(var(--shade-rgb),.6);    /* modal */
  --sh-4:0 30px 90px rgba(var(--shade-rgb),.62);   /* full-screen sheet */

  /* ── motion ──────────────────────────────────────────────────
     Five durations for thirty-seven. Coordinated timing is most of what
     separates an interface that feels built from one that feels assembled —
     when every hover on the page settles at the same moment, the page reads as
     one object. Long ambient loops (the 52s ticker, the 2.6s brand pulse) are
     not on this scale; they are not responses to anything. */
  --dur-1:120ms;  /* press / tactile — must beat the finger */
  --dur-2:180ms;  /* hover, colour, border */
  --dur-3:260ms;  /* small position and size changes */
  --dur-4:400ms;  /* entrances */
  --dur-5:600ms;  /* bars and meters filling */
  --ease:cubic-bezier(.16,1,.3,1);         /* decelerate hard — arrivals */
  --ease-2:cubic-bezier(.4,0,.2,1);        /* standard — state changes */
  --ease-smooth:cubic-bezier(.2,.8,.25,1); /* flips and long travels */
  --ease-spring:cubic-bezier(.34,1.56,.64,1); /* overshoot — things landing */

  /* ── layout constants other files need ───────────────────────
     .rail, .obledger and the chat dock all stick under the header, and all
     three had 56px typed into them separately. */
  --hdr-h:56px;
  --shell-w:1240px;
  --shell-pad:24px;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--txt);min-height:100vh;
  font:var(--fs-base)/1.5 var(--sans);font-feature-settings:"cv02","cv03","cv04";
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}

/* ── keyboard focus, once, for everything ──────────────────────
   Nine of the ten interactive controls on this site are <button>, and every
   stylesheet that styles one also sets `outline:0` or `outline:none` on its
   focus state — so a keyboard player had no visible focus anywhere except the
   audio slider. :focus-visible only fires for keyboard and assistive input, so
   this costs the mouse player nothing.

   An outline rather than a box-shadow ring: it follows border-radius, it cannot
   be clipped by an ancestor's overflow:hidden (the game rail, the results strip
   and the case reel are all clipping scrollers), and it is not a paint-heavy
   shadow on something that may be mid-transform. --acc is 7.58:1 on --bg and
   6.91:1 on --surface-2, comfortably past the 3:1 a focus indicator owes.

   !important, and this is the case it exists for. Five stylesheets each kill the
   outline on their own inputs — `.slip input:focus`, `.modal input:focus`,
   `.crx-autoin:focus`, `.obshell input:focus`, `.pdchat-input:focus`, plus
   `outline:none` in floor.css's `.stakein` base rule. Those are two-class
   selectors; `:where()` contributes no specificity, so without this the ring
   loses to every one of them and the six most-typed-into fields on the site
   still have no visible focus. A system-level accessibility guarantee cannot be
   something the tenth stylesheet gets to opt out of by accident. Anything that
   wants a different focus treatment can still add a box-shadow on top — which is
   exactly what audio.css's volume slider does, and it still works. */
:where(a,button,input,select,textarea,summary,[tabindex],[role="button"]):focus-visible{
  outline:2px solid var(--acc) !important;
  outline-offset:2px !important;
}
/* Boards are clicked, not tabbed, but they are still reachable, and a ring that
   lands inside a canvas edge is invisible. Push it out. */
:where(.pk,.row,.mft,.ttile,.rl,.crx-chip,.chip):focus-visible{outline-offset:3px !important}
/* faint telemetry grid + grain, so flat panels have some tooth */
body::before{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:0;opacity:.5;
  background-image:
    linear-gradient(rgba(var(--light-rgb),.014) 1px,transparent 1px),
    linear-gradient(90deg,rgba(var(--light-rgb),.014) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(120% 90% at 50% 0%,#000 20%,transparent 78%);
}
::selection{background:var(--acc);color:var(--on-acc)}
.wrap{max-width:var(--shell-w);margin:0 auto;padding:0 var(--shell-pad) 120px;position:relative;z-index:1}
h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.022em}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.02em}

/* ── header ───────────────────────────────────────────────── */
header{position:sticky;top:0;z-index:40;background:var(--glass);
  backdrop-filter:blur(20px) saturate(1.5);border-bottom:1px solid var(--line)}
/* min-height, not height. floor.css lets this bar wrap below 700px, but the
   fixed 56px stayed — so at 375px the bar's own content measured 162px tall
   inside a 56px box and painted straight over the ledger, the hero and the
   first card. Everything else on mobile was downstream of this one word. */
.bar{max-width:var(--shell-w);margin:0 auto;padding:0 var(--shell-pad);
  min-height:var(--hdr-h);display:flex;align-items:center;gap:var(--sp-7)}
.brand{display:flex;align-items:center;gap:9px;font-weight:600;font-size:var(--fs-base);letter-spacing:-.03em}
.brand .dot{width:7px;height:7px;border-radius:var(--r-pill);background:var(--acc);
  box-shadow:0 0 0 3px var(--acc-soft);animation:pulse 2.6s var(--ease-2) infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 0 3px var(--acc-soft)}50%{box-shadow:0 0 0 7px transparent}}
.brand b{font-weight:600}.brand span{color:var(--dim);font-weight:400}
.spacer{flex:1}
.meta-chip{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim);letter-spacing:-.01em;white-space:nowrap}
.meta-chip b{color:var(--txt-2);font-weight:500}
.acct{display:flex;align-items:center;gap:10px;font-size:var(--fs-md);white-space:nowrap}
.acct .h{color:var(--txt-2)}
.acct .b{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--txt);font-size:var(--fs-md)}
.streak{font-family:var(--mono);font-size:var(--fs-xs);color:var(--acc);border:1px solid var(--acc-line);
  padding:1px 6px;border-radius:var(--r-2)}
.walletchip{font-family:var(--mono);font-size:var(--fs-xs);padding:4px 9px;border-radius:var(--r-3);
  background:transparent;border:1px solid var(--line-2)}
.walletchip.ok{color:var(--up);border-color:rgba(var(--up-rgb),.3)}
.walletchip.ok:hover{background:rgba(var(--up-rgb),.08);color:var(--up)}
.walletchip.warn{color:var(--acc);border-color:var(--acc-line);background:var(--acc-soft)}
.walletchip.warn::before{content:"⚠ ";}
.walletchip.warn:hover{background:rgba(var(--acc-rgb),.2);color:var(--acc)}

button{font-family:inherit;font-size:var(--fs-md);font-weight:500;letter-spacing:-.01em;cursor:pointer;
  border-radius:var(--r-3);padding:7px 14px;border:1px solid transparent;background:var(--acc);color:var(--on-acc);
  transition:background var(--dur-2) var(--ease-2),border-color var(--dur-2),color var(--dur-2),transform var(--dur-1) var(--ease)}
button:hover:not(:disabled){background:var(--acc-hi)}
button:active:not(:disabled){transform:scale(.975)}
button:disabled{opacity:.3;cursor:not-allowed}
button.ghost{background:transparent;color:var(--txt-2);border-color:var(--line-2)}
button.ghost:hover:not(:disabled){background:var(--surface-2);color:var(--txt);border-color:var(--line-3)}
button.quiet{background:transparent;color:var(--dim);border-color:transparent;padding:6px 10px}
button.quiet:hover:not(:disabled){color:var(--txt);background:var(--surface-2)}

/* ── the way back in ──────────────────────────────────────────
   Injected by app.js next to Play and shown only while signed out. Quieter than the
   primary on purpose: it is not the action for a first visit, it is the action for
   somebody who already had an account and cannot get to it. Recessive, and present.

   It is allowed to shrink to its label and no further — a header that wraps to three
   rows on a phone was a real regression here once, so this never grows the row it is
   on and it drops its border rather than its presence at 700px. */
.recoverbtn{white-space:nowrap;flex:0 0 auto;font-size:var(--fs-sm);padding:6px 11px}
@media(max-width:700px){
  .recoverbtn{border-color:transparent;color:var(--dim);padding:6px 4px}
}

/* The Account tab, signed out. It used to be one flat sentence with nothing to press. */
.acctout-btns{display:flex;gap:10px;flex-wrap:wrap}

/* The sentence directly under the paying board's heading. It is the answer to "which of
   these boards is the real one", so it sits above the table rather than under it, where
   the scoring rule already lives. */
.rs-lead{border-bottom:1px solid var(--line)}

/* ── HAPPY MINUTE, AT REST ────────────────────────────────────
   The event has a banner and the banner exists for 60 seconds at a time, so between
   events the whole feature was invisible and a player could finish a session never
   knowing it was there. happy.js injects this chip into the header permanently.

   Deliberately recessive. The header was cut from nine items to five on the test "does
   this number change while I watch it", and this one does not, so it reads as standing
   context in the same weight as the coin count rather than as another button. It never
   grows the bar and it stands down on a phone, where the header is already two rows and
   the live banner is the introduction anyway.

   Here rather than in happy.css on purpose: that file is measured by a test that bans
   the effects the floor's performance pass removed, and it is the stylesheet for a thing
   that animates. Nothing here animates. */
.hpmc-chip{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;white-space:nowrap;
  background:transparent;border:1px solid var(--line-2);color:var(--dim);
  font-family:var(--mono);font-size:var(--fs-xs);font-weight:400;letter-spacing:-.01em;
  padding:4px 9px;border-radius:var(--r-3)}
.hpmc-chip:hover:not(:disabled){background:var(--surface-2);color:var(--txt-2);border-color:var(--line-3)}
.hpmc-chip .hpmc-x{color:var(--txt-2);font-weight:500}
.hpmc-dot{width:5px;height:5px;border-radius:var(--r-pill);background:var(--line-3);flex:0 0 auto}
/* Warning and live. A colour change and nothing else: the banner is already the event,
   and a second thing pulsing in the header during the loudest sixty seconds on the site
   is noise on top of noise. */
.hpmc-chip[data-phase="warn"]{border-color:var(--acc-line);color:var(--acc)}
.hpmc-chip[data-phase="warn"] .hpmc-x,
.hpmc-chip[data-phase="live"] .hpmc-x{color:var(--acc)}
.hpmc-chip[data-phase="warn"] .hpmc-dot,
.hpmc-chip[data-phase="live"] .hpmc-dot{background:var(--acc)}
.hpmc-chip[data-phase="live"]{border-color:var(--acc-line);color:var(--acc);background:var(--acc-soft)}
@media(max-width:700px){ .hpmc-chip{display:none} }

/* The live bar opens the same panel, which is the only route to it on a phone. */
.hpm-bar{cursor:pointer}

/* The panel. Borrows .modal and .card from above; everything below is just the list. */
.hpmc-sheet .card{max-width:520px;max-height:82vh;overflow:auto}
.hpmc-lead{color:var(--txt-2);font-size:var(--fs-md);line-height:1.6;margin:0 0 10px}
.hpmc-note{color:var(--dim);font-size:var(--fs-sm);line-height:1.6;margin:0 0 16px}
.hpmc-k{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim-2);margin:16px 0 8px}
.hpmc-list{margin:0;padding-left:18px;color:var(--txt-2);font-size:var(--fs-sm);line-height:1.65}
.hpmc-list li{margin-bottom:5px}
.hpmc-row{display:flex;align-items:baseline;gap:10px;font-family:var(--mono);
  font-size:var(--fs-xs);color:var(--dim);padding:6px 0;border-top:1px solid var(--line)}
.hpmc-row b{color:var(--acc);font-weight:500}
.hpmc-row em{font-style:normal;color:var(--txt-2)}
.hpmc-row i{font-style:normal;margin-left:auto;color:var(--dim-2)}
.hpmc-close{width:100%;margin-top:18px}

/* ── hero ─────────────────────────────────────────────────── */
.hero{padding:64px 0 40px;max-width:760px}
.eyebrow{font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.14em;text-transform:uppercase;
  color:var(--acc);margin-bottom:18px;display:flex;align-items:center;gap:9px}
.eyebrow::before{content:"";width:22px;height:1px;background:var(--acc)}
.hero h1{font-size:clamp(34px,5.4vw,58px);line-height:1.02;letter-spacing:-.04em;font-weight:600}
.hero h1 .q{color:var(--dim-2)}
.hero p{margin:22px 0 0;color:var(--txt-2);font-size:var(--fs-lg);line-height:1.62;max-width:56ch}
.hero p b{color:var(--txt);font-weight:500}

/* ── pot strip ──────────────────────────────────────────────
   `.rail` twice. `paintStrip()` twice. `.warn` twice. And `.strip` twice: this
   file declares it as the four-cell pot grid, floor.css declares it as the game
   floor's flex results row, and floor.css loads second. The pot strip has
   therefore been `display:flex` — so both of the responsive rules below, which
   only ever set grid-template-columns, did nothing at all, and at 375px the four
   cells were a 291px-tall squeeze with the labels overlapping each other.

   Scoped to #strip, which index.html already puts on the element. An id beats a
   class from any file in any order, which is the only thing that reliably
   settles a shared flat namespace — a fourth stylesheet can declare `.strip`
   tomorrow and this stays correct. The floor's own `.strip` is untouched. */
#strip{display:grid;grid-template-columns:auto auto 1fr auto;gap:0;align-items:stretch;
  border:1px solid var(--line);border-radius:var(--r-5);background:var(--surface);overflow:hidden;margin:8px 0 22px}
#strip>div{padding:16px 22px;border-right:1px solid var(--line);display:flex;flex-direction:column;
  justify-content:center;gap:5px;min-width:0}
#strip>div:last-child{border-right:0}
.k{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.13em;text-transform:uppercase;color:var(--dim-2)}
.v{font-family:var(--mono);font-size:var(--fs-3xl);font-weight:500;letter-spacing:-.035em;line-height:1}
.v.acc{color:var(--acc)}
#strip .lead{min-width:0}
.lead-row{display:flex;align-items:center;gap:9px;font-size:var(--fs-md);min-width:0}
.lead-row .pos{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);width:15px;flex:none}
.lead-row .nm{color:var(--txt-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lead-row .amt{font-family:var(--mono);color:var(--up);font-size:var(--fs-sm);margin-left:auto;flex:none}
.splitmeter{display:flex;height:3px;border-radius:var(--r-1);overflow:hidden;background:var(--line);margin-top:3px}
.splitmeter i{display:block;height:100%}
.splitmeter .a{background:var(--acc)}.splitmeter .b{background:var(--line-3)}
.splitnote{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim)}

/* ── ticker ───────────────────────────────────────────────── */
.tick{border-top:1px solid var(--line);border-bottom:1px solid var(--line);height:36px;
  overflow:hidden;position:relative;margin-bottom:34px;
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.tick .rail{display:flex;gap:34px;align-items:center;height:100%;white-space:nowrap;
  animation:roll 52s linear infinite;font-family:var(--mono);font-size:var(--fs-sm);color:var(--dim)}
.tick:hover .rail{animation-play-state:paused}
@keyframes roll{to{transform:translateX(-50%)}}
.tick em{font-style:normal;color:var(--txt-2)}
.tick b{color:var(--acc);font-weight:500}

/* ── nav ──────────────────────────────────────────────────────
   THE TAB STRIP FOLLOWS YOU DOWN THE PAGE, and this is the single change that
   fixes "hard to move around".

   Measured before: the Games tab is 5,038px tall signed in at 1280 and 7,693px
   at 375. The tab strip sat at y=881 and y=1,148 and then scrolled away, so from
   the moment you were actually playing a game there was no route to the Pot, the
   Leaderboard, your Account or How it works at all. Getting to any of them meant
   scrolling a thousand pixels back up, finding the strip, clicking, and landing
   somewhere in the middle of the next tab. On a phone it was worse, because the
   header stops sticking at 700px, so past the first screen the page carried no
   navigation of any kind.

   Sticky, and directly under the two bars that already stick. --nav-top is
   measured at runtime in app.js rather than typed, because what is above it
   changes: the header stops sticking below 700px and the ledger can be absent
   entirely. The fallback below is the desktop sum (56 header + 44 ledger) so a
   stylesheet that arrives before its script is still roughly right.

   A FLAT BACKGROUND, NOT --glass. The header and the ledger are both
   backdrop-filter, and a third blurred layer is a third full-width filter pass on
   every scrolled frame. This one is opaque and costs nothing. */
nav{position:sticky;top:var(--nav-top,100px);z-index:32;
  display:flex;gap:2px;margin-bottom:26px;border-bottom:1px solid var(--line);overflow-x:auto;
  background:var(--bg);scrollbar-width:none}
nav::-webkit-scrollbar{display:none}
nav button{background:none;border:0;border-bottom:1.5px solid transparent;border-radius:0;
  color:var(--dim);padding:11px 15px;font-size:var(--fs-md);white-space:nowrap;margin-bottom:-1px}
nav button:hover{color:var(--txt-2);background:none;transform:none}
nav button.on{color:var(--txt);border-bottom-color:var(--acc)}
/* WHICH TAB AM I ON, at a glance rather than by comparing five greys. The
   underline alone is 1.5px of accent on a strip you are no longer looking at by
   the time you have scrolled to it. */
nav button.on{background:var(--acc-soft);font-weight:600}
/* The five tabs measure 372px at 375, so the strip scrolls sideways and How is
   off the edge on the landing view — a whole destination a phone player never
   sees. Letting them share the row costs nothing: the longest label is
   "Leaderboard" and it still fits. */
@media(max-width:520px){
  nav{gap:0}
  /* `1 1 auto`, not `1 1 0`. Equal fifths of 343px is 69px each and "Leaderboard"
     measures 78, so the one destination with a long name was the one that got cut.
     Sizing from content and sharing out what is left over gives it 98px and still
     fills the row. */
  nav button{flex:1 1 auto;min-width:0;padding:11px 6px;text-align:center;
    font-size:var(--fs-sm);white-space:nowrap}
}

/* ── crumb ────────────────────────────────────────────────────
   For a view that is not a tab. There is one of them (the eligibility table, off How
   it works) and it used to leave the strip pointing at a tab you were no longer on
   with no way back. The name of the thing you are looking at, and the door. */
.crumb{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 16px}
.crumb-back{background:none;border:1px solid var(--line-2);border-radius:var(--r-pill);
  color:var(--dim);padding:6px 14px;font-size:var(--fs-sm);min-height:34px;
  transition:border-color var(--dur-1),color var(--dur-1)}
.crumb-back::before{content:"←";margin-right:8px}
.crumb-back:hover{border-color:var(--line-3);color:var(--txt);background:none;transform:none}
.crumb-at{font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim-2)}

/* ── section head ─────────────────────────────────────────── */
.sec{display:flex;align-items:baseline;gap:12px;margin:34px 0 14px}
.sec h2{font-size:var(--fs-md);font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}
.sec .rule{flex:1;height:1px;background:var(--line)}
.sec .cnt{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim-2)}

/* ── cards ────────────────────────────────────────────────── */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(370px,1fr));gap:14px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-5);padding:0;
  transition:border-color var(--dur-3) var(--ease-2),transform var(--dur-3) var(--ease);position:relative;overflow:hidden;
  animation:rise .5s var(--ease) backwards}
@keyframes rise{from{opacity:0;transform:translateY(9px)}}
.card:hover{border-color:var(--line-2)}
.card.stack{grid-column:1/-1}
.chead{display:flex;align-items:center;gap:9px;padding:13px 16px;border-bottom:1px solid var(--line);
  flex-wrap:wrap}
.cbody{padding:14px 16px}
.tag{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);border:1px solid var(--line-2);padding:2.5px 7px;border-radius:var(--r-2)}
.tag.live{color:var(--acc);border-color:var(--acc-line);background:var(--acc-soft)}
.tag.run{color:var(--txt-2);border-color:var(--line-3)}
.tag.done{color:var(--dim-2)}
.tag.t-even{color:var(--info);border-color:rgba(var(--info-rgb),.3)}
.tag.t-spicy{color:var(--warn);border-color:rgba(var(--warn-rgb),.3)}
.tag.t-degen{color:var(--down);border-color:rgba(var(--down-rgb),.35);background:rgba(var(--down-rgb),.07)}
.ttl{font-size:var(--fs-base);font-weight:550;letter-spacing:-.02em}
.timer{font-family:var(--mono);font-size:var(--fs-sm);color:var(--txt-2);margin-left:auto;
  font-variant-numeric:tabular-nums}
.timer.urgent{color:var(--acc)}

/* ── pulse ────────────────────────────────────────────────── */
.psub{display:flex;align-items:flex-end;gap:13px;margin-bottom:3px}
.psub .tk{font-size:var(--fs-2xl);font-weight:600;letter-spacing:-.035em}
.psub .mv{font-family:var(--mono);font-size:var(--fs-2xl);font-weight:500;letter-spacing:-.04em;line-height:1.1}
.psub .bd{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim);margin-left:auto;padding-bottom:3px}
.spark{width:100%;height:34px;display:block;margin:9px 0 2px;overflow:visible}
.spark path{fill:none;stroke-width:1.4;vector-effect:non-scaling-stroke}
.spark .area{stroke:none;opacity:.10}

.gauge{position:relative;height:38px;margin:12px 0 14px;border-radius:var(--r-3);overflow:hidden;
  background:var(--bg-1);border:1px solid var(--line)}
.gauge .z{position:absolute;top:0;bottom:0}
.gauge .zd{left:0;background:linear-gradient(90deg,rgba(var(--down-rgb),.20),rgba(var(--down-rgb),.02))}
.gauge .zu{right:0;background:linear-gradient(270deg,rgba(var(--up-rgb),.20),rgba(var(--up-rgb),.02))}
.gauge .edge{position:absolute;top:0;bottom:0;width:1px;background:var(--line-3)}
.gauge .lab{position:absolute;top:50%;transform:translateY(-50%);font-family:var(--mono);
  font-size:var(--fs-micro);color:var(--dim-2);letter-spacing:.04em}
.gauge .pin{position:absolute;top:-1px;bottom:-1px;width:2px;background:var(--txt);border-radius:var(--r-1);
  box-shadow:0 0 14px rgba(var(--txt-rgb),.6);transition:left var(--dur-5) var(--ease)}
.gauge .val{position:absolute;bottom:4px;transform:translateX(-50%);font-family:var(--mono);
  font-size:var(--fs-mini);font-weight:500;transition:left var(--dur-5) var(--ease);white-space:nowrap;
  text-shadow:0 1px 5px #000}

.picks{display:grid;grid-template-columns:repeat(3,1fr);gap:7px}
.pk{position:relative;border:1px solid var(--line);border-radius:var(--r-4);padding:11px 9px;text-align:center;
  cursor:pointer;background:var(--bg-1);overflow:hidden;
  transition:border-color var(--dur-2),background var(--dur-2),transform var(--dur-2) var(--ease)}
.pk:hover{transform:translateY(-2px);border-color:var(--line-3)}
.pk .lb{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.11em;color:var(--dim);text-transform:uppercase}
.pk .mu{font-family:var(--mono);font-size:var(--fs-xl);font-weight:500;letter-spacing:-.04em;margin:5px 0 3px}
.pk .st{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2)}
.pk .load{position:absolute;left:0;bottom:0;height:2px;opacity:.6;transition:width var(--dur-5) var(--ease)}
.pk.up:hover .lb,.pk.up.on .lb{color:var(--up)} .pk.up .load{background:var(--up)}
.pk.down:hover .lb,.pk.down.on .lb{color:var(--down)} .pk.down .load{background:var(--down)}
.pk.flat:hover .lb,.pk.flat.on .lb{color:var(--hold)} .pk.flat .load{background:var(--hold)}
.pk.on{background:var(--surface-2);border-color:var(--line-3);box-shadow:inset 0 0 0 1px var(--line-3)}
.pk.won{border-color:var(--acc);background:var(--acc-soft)}
.pk .kbd{position:absolute;top:6px;right:7px;font-family:var(--mono);font-size:var(--fs-micro);color:var(--dim-2);
  border:1px solid var(--line-2);border-radius:var(--r-1);padding:0 3px;opacity:0;transition:opacity var(--dur-2)}
.pk:hover .kbd{opacity:1}

/* ── race rows ────────────────────────────────────────────── */
.rows{display:flex;flex-direction:column}
.row{position:relative;display:grid;grid-template-columns:18px 1fr 68px 62px 52px;gap:11px;
  align-items:center;padding:9px 4px;cursor:pointer;border-bottom:1px solid var(--line);
  transition:background var(--dur-2)}
.row:last-child{border-bottom:0}
/* Share of pool. This used to be a full-height block behind the row, which read as
   a muddy orange overlay rather than as data — a staircase of brown rectangles that
   looked like a rendering artifact. A thin underline says "bar chart" immediately
   and stops fighting the text for contrast. */
.row .bg{position:absolute;left:0;bottom:0;height:2px;background:var(--acc);opacity:.75;
  transition:width var(--dur-5) var(--ease);z-index:0;border-radius:var(--r-1)}
.row.won .bg{background:var(--up);opacity:1}
.row>*{position:relative;z-index:1}
.row:hover{background:var(--surface-2)}
.row.on{background:var(--surface-2);box-shadow:inset 2px 0 0 var(--acc)}
.row.won .sym{color:var(--acc)}
.row .pos{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim-2);text-align:right}
.row .sym{font-size:var(--fs-md);font-weight:550;letter-spacing:-.015em}
.row .sub{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);margin-top:1px}
.row .pc{font-family:var(--mono);font-size:var(--fs-md);text-align:right;font-variant-numeric:tabular-nums}
.row .mu{font-family:var(--mono);font-size:var(--fs-sm);color:var(--txt-2);text-align:right}
.row .sk{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);text-align:right}
.row .mini{width:52px;height:16px}
.up{color:var(--up)}.down{color:var(--down)}.zero{color:var(--dim)}

/* ── slip ─────────────────────────────────────────────────── */
.slip{display:flex;align-items:center;gap:7px;padding:12px 16px;border-top:1px solid var(--line);
  background:var(--bg-1);flex-wrap:wrap}
.slip input{background:var(--surface);border:1px solid var(--line-2);color:var(--txt);border-radius:var(--r-3);
  padding:7px 11px;width:88px;font-family:var(--mono);font-size:var(--fs-md);transition:border-color var(--dur-2)}
.slip input:focus{outline:0;border-color:var(--acc-line)}
.chips{display:flex;gap:3px}
.chips button{padding:6px 9px;font-family:var(--mono);font-size:var(--fs-xs);background:transparent;
  color:var(--dim);border-color:var(--line)}
.chips button:hover{color:var(--txt);border-color:var(--line-3);background:var(--surface)}
.est{flex:1;min-width:150px;font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim);text-align:right}
.est b{color:var(--txt);font-weight:500}
.mine{padding:10px 16px;border-top:1px solid var(--line);font-family:var(--mono);font-size:var(--fs-xs);
  color:var(--dim);background:var(--bg-1)}
.mine b{color:var(--txt-2);font-weight:500}
.mine.live{background:linear-gradient(90deg,var(--acc-soft),transparent 60%);
  border-left:2px solid var(--acc)}
.mine-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.mine-val{font-size:var(--fs-xl);font-weight:600;letter-spacing:-.03em;color:var(--txt);
  transition:color var(--dur-3)}
.mine-pnl{font-size:var(--fs-sm);font-weight:600}
.mine-legs{margin-left:auto;color:var(--dim-2);font-size:var(--fs-mini)}
@keyframes flash{0%{color:var(--acc)}100%{}}
.mine-val.bump{animation:flash .6s}
.foot{padding:9px 16px;border-top:1px solid var(--line);font-family:var(--mono);font-size:var(--fs-mini);
  color:var(--dim-2);display:flex;gap:14px;flex-wrap:wrap}
.foot b{color:var(--txt-2);font-weight:500}

/* ── tables ───────────────────────────────────────────────── */
table{width:100%;border-collapse:collapse;font-size:var(--fs-md)}
th{text-align:left;font-family:var(--mono);font-weight:400;font-size:var(--fs-mini);letter-spacing:.11em;
  text-transform:uppercase;color:var(--dim-2);padding:10px 12px;border-bottom:1px solid var(--line)}
td{padding:10px 12px;border-bottom:1px solid var(--line);font-variant-numeric:tabular-nums}
tbody tr{transition:background var(--dur-1)}
tbody tr:hover{background:var(--surface-2)}
tr:last-child td{border-bottom:0}
td.m,th.m{font-family:var(--mono)}
.r{text-align:right}
.note{color:var(--dim);font-size:var(--fs-sm);line-height:1.65}
.note b{color:var(--txt-2);font-weight:500}
.prose{max-width:70ch}
.prose h4{font-size:var(--fs-md);color:var(--txt);margin:22px 0 7px;letter-spacing:-.01em}
.prose p{margin:0 0 4px}
.empty{padding:40px 16px;text-align:center;color:var(--dim-2);font-size:var(--fs-md)}
.stats{display:flex;gap:34px;flex-wrap:wrap;padding:16px}
.stat{display:flex;flex-direction:column;gap:5px}
.stat .v{font-size:var(--fs-2xl)}

/* ── overlays ─────────────────────────────────────────────────
   THE STACK, IN ORDER, AND WHY IT MOVED.

   The modal was written at z-index 50 when the tallest thing on the page was the
   header at 40. Six full-screen surfaces have arrived since and every one of them
   went above it: the tray menu and the onboarding veil and the season ladder at 60,
   the happy banner at 100, the profile overlay at 120. Each was correct on its own
   and together they made the modal the lowest overlay on the site.

   That is not cosmetic, it is a dead button. profile.js's "Share this profile" hands
   the sheet to app.js's share modal and does not close its own overlay first, so the
   modal opened at 50 underneath the profile at 120 and the click did nothing at all,
   every time. Reproduced.

   A modal is the surface that says "deal with this before anything else", so it goes
   above everything that is merely open, and the toast goes above the modal because
   half the toasts on this site are the receipt for a button inside one ("code
   copied"). The two floor overlays stay higher still at 200 and 210, which is right:
   both are pointer-events:none and neither is something you act on. */
.toast{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);z-index:140;
  background:var(--surface);border:1px solid var(--line-2);border-left:2px solid var(--acc);
  color:var(--txt);padding:12px 20px;border-radius:var(--r-4);font-size:var(--fs-md);
  box-shadow:var(--sh-3);animation:slidein var(--dur-4) var(--ease)}
.toast.err{border-left-color:var(--down)}
.toast.win{border-left-color:var(--up);font-size:var(--fs-base)}
@keyframes slidein{from{opacity:0;transform:translate(-50%,16px)}}
.modal{position:fixed;inset:0;background:var(--scrim);backdrop-filter:blur(10px);
  display:grid;place-items:center;z-index:130;padding:24px;animation:fade var(--dur-3) var(--ease)}
@keyframes fade{from{opacity:0}}
.modal .card{max-width:390px;width:100%;padding:26px;animation:rise .4s var(--ease)}
.modal h3{font-size:var(--fs-xl);letter-spacing:-.03em;margin-bottom:6px}
.modal input{width:100%;margin:16px 0 14px;background:var(--bg-1);border:1px solid var(--line-2);
  color:var(--txt);border-radius:var(--r-3);padding:11px 13px;font-size:var(--fs-base);font-family:var(--mono)}
.modal input:focus{outline:0;border-color:var(--acc-line)}
.steps{display:flex;gap:6px;margin-bottom:16px}
.steps i{height:2px;flex:1;background:var(--line-2);border-radius:var(--r-1);transition:background var(--dur-3)}
.steps i.on{background:var(--acc)}
/* THE SAME BUG AS `.rail`, STILL LIVE. `.warn` is the seed-phrase disclosure
   block in the signup modal — a 10px-padded red box. It was unscoped, and the
   header's wallet button is `class="walletchip warn"` (app.js:387), so it also
   matched. Equal specificity, and `.warn` is declared later, so for as long as
   both have existed the header chip has been rendering with the disclosure
   box's padding, font-size, line-height and radius: 120×41px in a 56px bar
   instead of 120×25px, which is a good part of why the phone header wrapped to
   three rows at all. The chip's own colours survived only because
   `.walletchip.warn` is two classes.

   Scoped to the modal it lives in rather than renamed, because the markup
   belongs to app.js. It is the only place it is used — grep says one <div> in
   index.html and that one button. */
.modal .warn{border:1px solid rgba(var(--down-rgb),.28);background:rgba(var(--down-rgb),.06);
  border-radius:var(--r-3);padding:10px 12px;margin-top:12px;font-size:var(--fs-sm);
  line-height:1.55;color:var(--txt-2)}
.modal .warn b{color:var(--down)}
.share{background:transparent;border:1px solid var(--line-2);color:var(--dim);padding:6px 11px;
  font-size:var(--fs-sm);border-radius:var(--r-3)}
.share:hover{color:var(--acc);border-color:var(--acc-line);background:var(--acc-soft)}
.wins{display:flex;gap:9px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.wins::-webkit-scrollbar{display:none}
.wincard{flex:none;min-width:212px;border:1px solid var(--line);border-radius:var(--r-4);padding:12px 14px;
  background:var(--surface);cursor:pointer;transition:border-color var(--dur-2),transform var(--dur-2) var(--ease)}
.wincard:hover{border-color:var(--acc-line);transform:translateY(-2px)}
.wincard .amt{font-family:var(--mono);font-size:var(--fs-2xl);color:var(--acc);letter-spacing:-.03em}
.wincard .who{font-size:var(--fs-sm);color:var(--txt-2);margin-top:2px}
.wincard .mk{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);margin-top:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.refbox{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:10px}
.refbox code{font-family:var(--mono);font-size:var(--fs-sm);background:var(--bg-1);border:1px solid var(--line-2);
  border-radius:var(--r-3);padding:8px 11px;color:var(--txt-2);flex:1;min-width:200px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
#confetti{position:fixed;inset:0;pointer-events:none;z-index:70}
.dots{display:inline-block;width:11px;height:11px;border:1.5px solid var(--line-3);
  border-top-color:var(--acc);border-radius:50%;animation:sp .75s linear infinite;vertical-align:-1px}
@keyframes sp{to{transform:rotate(360deg)}}

@media(max-width:900px){
  #strip{grid-template-columns:1fr 1fr}
  #strip>div:nth-child(2n){border-right:0}
  #strip>div{border-bottom:1px solid var(--line)}
}
@media(max-width:640px){
  .wrap{padding:0 16px 90px}.bar{padding:0 16px}
  .hero{padding:40px 0 28px}
  .grid{grid-template-columns:1fr}
  .row{grid-template-columns:16px 1fr 60px 50px}
  .row .sk{display:none}
  #strip{grid-template-columns:1fr}
  #strip>div{border-right:0}
  .acct .h{display:none}
}
/* This catch-all is what actually covers the ten stylesheets — the per-file
   `prefers-reduced-motion` blocks in floor/crash/arcade/audio/onboarding are
   refinements on top of it, and meta.css, chat.css, profile.css and invite.css
   have none of their own and rely on it entirely. Verified by emulation rather
   than assumed: every animation and transition on the page reports a computed
   duration of 0.01ms with the setting on. */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  /* Duration alone does not cover programmatic scrolling. meta.css's reward
     ladder sets scroll-behavior:smooth and JS scrolls it, which the rule above
     cannot reach — a smooth scroll is exactly the motion this setting is about.
     :root as well as *, because scroll-behavior on the scrolling element is
     read from html rather than inherited to it. */
  html{scroll-behavior:auto!important}
}

/* ══════════ THE HEADER, NARROWING ═════════════════════════════
   Measured, not guessed, and at two widths because it broke differently at each.

   AT 768px THE PAGE SCROLLED SIDEWAYS. The bar is a nowrap flex row and its
   content — brand, coin count, token link, rigs, account block, bonus, sound and
   the profile button another agent added this afternoon — measures 1109px. Flex
   items with text will not shrink below their content, so the document itself
   became 1133px wide inside a 753px viewport: a horizontal scrollbar on every
   tab and every game, sourced entirely from the header. It only ever wrapped
   below 700px, so the whole tablet band had nowhere to put the overflow.

   Two things fix it, and both are needed: let the bar wrap from 900px down, and
   drop the two items that are context rather than control. The coin count and
   the funding-token link are read once and are both still on the How tab; they
   are not things anyone reaches for mid-round. Identity, balance, the rig
   collector and the primary button stay. */
@media(max-width:900px){
  .bar{flex-wrap:wrap;row-gap:var(--sp-2);padding-block:var(--sp-2)}
  #uniChip,#tokenChip{display:none}
}

/* ══════════ AND ON A PHONE ═══════════════════════════════════
   At 375px even the stripped bar is three rows and 150px of sticky chrome — a
   fifth of the viewport, permanently, above the game. */
@media(max-width:700px){
  .bar{gap:var(--sp-3)}
  .brand{font-size:var(--fs-md)}
  /* The spacer is a flex filler for a single row. On a wrapped bar it eats a
     whole line, which is where two of the four rows came from. */
  .bar>.spacer{display:none}
  /* floor.css sets .acct{flex-wrap:wrap} at this width and loads after this
     file, so this needs the extra element to win. Wrapping the account block
     internally is what turned two header rows into three. */
  header .acct{margin-left:auto;flex-wrap:nowrap;min-width:0}
  header .acct .walletchip{min-width:0;flex:0 1 auto}

  /* THE HEADER STOPS STICKING. Even stripped it is two or three rows on a
     phone, and there is a purpose-built 40px bar directly under it —
     onboarding.css's .obledger — that already carries the points balance and
     the SOL prize and was designed to be the thing that follows you down the
     page. Two stacked sticky bars is how you end up with a third of a phone
     screen permanently spent on chrome. One sticky element, and it is the one
     built for the job. The header scrolls away like the hero does.
     (.obledger's own top offset is corrected in onboarding.css.) */
  header{position:static}
}

/* ══════════ TOUCH TARGETS ═════════════════════════════════════
   45 controls measured under 32px in either axis at 375px, the smallest a 25px
   stake chip. WCAG 2.2 AA sets the floor at 24×24, so most were legal and none
   were comfortable — and the stake chips are the most-tapped controls on the
   site. Height only, via min-height and block padding: touching the width would
   reflow the wrapping rows these all sit in.

   Scoped to width alone rather than to (pointer:coarse) on purpose — a 375px
   window on a desktop is still a 375px layout, and a media feature that cannot
   be reproduced in a browser pane is a media feature nobody will ever check. */
@media(max-width:700px){
  .qs,.chips button,.smod,.share,.tag,.obled-help,.mta-btn.mta-sm,
  .crx-quick button,.crx-autotog,.seg button,.rigbuy,.grigchip,.walletchip{
    min-height:34px;padding-block:var(--sp-2)
  }
  /* A 16px-tall range track is a 16px-tall drag target. The thumb is the thing
     being grabbed, so the padding goes on the input rather than the track. */
  .arc-slider,#ouslider{min-height:34px;padding-block:var(--sp-3)}
  /* Icon-only buttons have no text to pad around, so they get a floor in both
     axes — these are the ones a thumb misses. */
  .sndbtn,.obhint-x,.pdchat-icon,.idlechip{min-width:36px;min-height:36px}
  /* The one-tap toggle: the input is 13px and invisible, the label is the target. */
  .qtoggle{min-height:36px}
}

/* ── round missions ─────────────────────────────────────── */
.missions{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:9px;
  margin:0 0 26px;align-items:stretch}
.mz{border:1px solid var(--line);border-radius:var(--r-4);padding:11px 13px;background:var(--surface);
  transition:border-color var(--dur-2),background var(--dur-2)}
.mz.ready{border-color:var(--acc-line);background:var(--acc-soft)}
.mz.done{opacity:.42}
.mz-top{display:flex;align-items:baseline;gap:8px}
.mz-l{font-size:var(--fs-md);font-weight:600;letter-spacing:-.02em}
.mz-r{margin-left:auto;font-family:var(--mono);font-size:var(--fs-xs);color:var(--acc)}
.mz-d{font-size:var(--fs-xs);color:var(--dim);margin:4px 0 8px;line-height:1.45}
.mz-bar{height:3px;background:var(--line);border-radius:var(--r-1);overflow:hidden}
.mz-bar i{display:block;height:100%;background:var(--acc);transition:width var(--dur-5) var(--ease)}
.mz-p{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);margin-top:5px}
.mz-claim{align-self:center;height:100%;min-height:64px;font-weight:600}
/* Sits exactly where the claim button would, so a finished board never looks empty while
   the round's wager gate is unmet. See missions.mjs MISSION_STAKE_GATE. */
.mz-gate{align-self:center;min-height:64px;display:flex;align-items:center;
  font-size:var(--fs-xs);color:var(--dim);line-height:1.45;padding:0 10px}

/* ── cash out ───────────────────────────────────────────── */
.sell{margin-left:12px;padding:5px 12px;font-size:var(--fs-sm);font-weight:600;
  background:var(--up);color:var(--on-up);border-radius:var(--r-3)}
.sell:hover:not(:disabled){background:var(--up-hi)}
/* White on --down measures 3.24:1 — under the 4.5:1 this 10px uppercase tag
   needs by a wide margin, and it is a label on the most urgent state the market
   has. --on-down is the same red with dark ink: 6.02:1, and it reads as a
   filled tag rather than a browser default. */
.tag.blitz{color:var(--on-down);background:var(--down);border-color:var(--down);
  animation:blitzpulse 1.1s ease-in-out infinite}
@keyframes blitzpulse{0%,100%{opacity:1}50%{opacity:.62}}
.card.blitzcard{border-color:rgba(var(--down-rgb),.45)}

/* ── quick bet bar ──────────────────────────────────────── */
.quickbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:11px 16px;
  border:1px solid var(--line);border-radius:var(--r-4);background:var(--surface);margin-bottom:16px;
  transition:border-color var(--dur-3),background var(--dur-3)}
.quickbar.armed{border-color:var(--acc-line);background:linear-gradient(90deg,var(--acc-soft),var(--surface) 55%)}
.qtoggle{display:flex;align-items:center;gap:9px;cursor:pointer;font-size:var(--fs-md);user-select:none}
.qtoggle input{position:absolute;opacity:0;pointer-events:none}
.qtoggle span{width:34px;height:19px;border-radius:var(--r-5);background:var(--line-2);position:relative;
  transition:background var(--dur-3) var(--ease-2);flex:none}
.qtoggle span::after{content:"";position:absolute;top:2px;left:2px;width:15px;height:15px;
  border-radius:50%;background:var(--txt-2);transition:transform var(--dur-3) var(--ease),background var(--dur-3)}
.qtoggle input:checked + span{background:var(--acc)}
.qtoggle input:checked + span::after{transform:translateX(15px);background:var(--on-acc)}
.qtoggle b{font-weight:600;letter-spacing:-.01em}
.qhint{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim)}
.qstakes{display:flex;gap:4px;margin-left:auto}
.qs{font-family:var(--mono);font-size:var(--fs-sm);padding:6px 12px;background:transparent;
  color:var(--dim);border:1px solid var(--line-2)}
.qs:hover{color:var(--txt);border-color:var(--line-3);background:var(--surface-2)}
.qs.on{background:var(--acc);color:var(--on-acc);border-color:var(--acc);font-weight:600}

/* action feedback */
@keyframes hitflash{
  0%{box-shadow:0 0 0 0 rgba(var(--acc-rgb),.55);border-color:var(--acc)}
  100%{box-shadow:0 0 0 14px rgba(var(--acc-rgb),0);border-color:var(--line)}
}
.card.hit{animation:hitflash .7s var(--ease)}
.pk,.row{-webkit-tap-highlight-color:transparent}
.quickbar.armed ~ #view .pk:active,.quickbar.armed ~ #view .row:active{transform:scale(.97)}

@media(max-width:640px){
  .qstakes{margin-left:0;width:100%}
  .qs{flex:1}
  .qhint{display:none}
}

/* ── live race rail ─────────────────────────────────────────
   The round you are competing in used to live on another tab, which meant you could
   not see yourself moving — the single biggest reason a round felt like nothing was
   happening. That is why it is here, above the tabs, on the landing view. It matters
   more now than it did: the round is thirty minutes rather than fifteen, and twice the
   span with no visible movement is twice the problem this element exists to solve.

   IT NO LONGER STICKS, and it had already stopped working before this. It stuck at
   top:56 at z-index 30, and .obledger sticks at top:57 at z-index 39 and is 44px
   tall — so 45 of the rail's 75px were painting underneath the ledger and all that
   ever showed was a 30px sliver of the standings with the clock cut off. Nobody had
   seen the stuck state of this element in its working form.

   Fixing the offset instead was the other option and it is the wrong one: header 57
   plus ledger 44 plus rail 75 plus the tab strip is 217px of permanent chrome on a
   720px screen. The tab strip is navigation and earns its place; a leaderboard
   summary is reference and does not. Below 760px it never stuck anyway. */
.rail{position:relative;z-index:30;display:grid;
  grid-template-columns:170px 1fr;gap:0;align-items:stretch;margin:0 0 12px;
  border:1px solid var(--line);border-radius:var(--r-5);overflow:hidden;
  /* Opaque, and the blur came out with the stickiness. A backdrop-filter is only
     ever worth its cost over content that scrolls beneath it, and nothing does any
     more. It also pulsed on every `.rail.push` frame, which was a full-width filter
     pass on an animating element. */
  background:var(--surface);
  transition:border-color var(--dur-4),box-shadow var(--dur-4)}
.rail-clock{padding:12px 16px;border-right:1px solid var(--line);display:flex;
  flex-direction:column;justify-content:center;gap:3px}
.rail-cd{font-family:var(--mono);font-size:var(--fs-3xl);font-weight:600;letter-spacing:-.04em;line-height:1}
.rail-push{font-size:var(--fs-mini)}
.pushtag{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.08em;color:var(--down);font-weight:700}
.rail-board{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:0 2px;padding:8px 10px;align-content:center}
.rr{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);padding:2px 6px;border-radius:var(--r-2);
  font-variant-numeric:tabular-nums;transition:background var(--dur-3)}
.rr.empty{color:var(--dim-2);grid-column:1/-1;justify-content:center;padding:10px}
.rr-p{font-family:var(--mono);color:var(--dim-2);width:14px;flex:none}
.rr-m{width:9px;flex:none;font-size:8px;color:transparent}
.rr.up .rr-m{color:var(--up)} .rr.down .rr-m{color:var(--down)}
.rr.up{background:rgba(var(--up-rgb),.09)} .rr.down{background:rgba(var(--down-rgb),.07)}
.rr-h{color:var(--txt-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.rr-n{font-family:var(--mono);color:var(--up);margin-left:auto;font-size:var(--fs-xs);flex:none}
.rr-z{font-family:var(--mono);color:var(--acc);font-size:var(--fs-mini);width:38px;text-align:right;flex:none}
.rr.me{background:var(--acc-soft);box-shadow:inset 0 0 0 1px var(--acc-line)}
.rr.me .rr-h{color:var(--txt);font-weight:600}
.rail-you{grid-column:1/-1;border-top:1px solid var(--line);padding:8px 16px;
  display:flex;align-items:center;gap:10px;font-size:var(--fs-sm);background:var(--bg-1)}
.rail-you b{font-family:var(--mono);font-size:var(--fs-base)}
.rr-gap{font-family:var(--mono);color:var(--dim);font-size:var(--fs-xs)}
.rr-def{font-family:var(--mono);color:var(--dim-2);font-size:var(--fs-xs);margin-left:auto}
.rr-prize{font-family:var(--mono);color:var(--acc);font-size:var(--fs-xs)}

.rail.push{border-color:rgba(var(--down-rgb),.55);box-shadow:0 0 26px rgba(var(--down-rgb),.14)}
.rail.push .rail-cd{color:var(--down);animation:railpulse 1s ease-in-out infinite}
@keyframes railpulse{0%,100%{opacity:1}50%{opacity:.55}}

@media(max-width:760px){
  .rail{grid-template-columns:1fr;top:0}
  .rail-clock{border-right:0;border-bottom:1px solid var(--line);flex-direction:row;
    align-items:baseline;gap:10px}
  .rail-board{grid-template-columns:1fr 1fr}
}

/* ── the closing seconds ────────────────────────────────────
   A market resolving is the only genuinely tense moment in the loop, and it used to
   pass without any signal at all. */
.card.ending{border-color:rgba(var(--down-rgb),.6);animation:endingpulse .9s ease-in-out infinite}
@keyframes endingpulse{
  0%,100%{box-shadow:0 0 0 0 rgba(var(--down-rgb),.28)}
  50%{box-shadow:0 0 0 8px rgba(var(--down-rgb),0)}
}
.card.ending .timer{color:var(--down);font-weight:700}
.card.ending .gauge .pin{box-shadow:0 0 20px rgba(var(--light-rgb),.9)}
/* Was `var(--flat, var(--warn))`. `--flat` has never existed in any stylesheet, so
   this had been running on its fallback since it was written — the fallback is
   the only reason it was amber rather than inherited. The near-miss amber is now
   --warn, which is a real token; --hold is the flat-price grey and is a
   different thing, which is probably what --flat was reaching for. */
.miss{color:var(--warn);font-weight:600}
.tk-rank{color:var(--acc)!important}
.tk-rank em{font-style:normal;color:var(--txt)}

/* ── recovery code ──────────────────────────────────────── */
.codebox{font-family:var(--mono);font-size:var(--fs-2xl);letter-spacing:.06em;text-align:center;
  padding:18px;margin:16px 0;border:1px dashed var(--acc-line);border-radius:var(--r-4);
  background:var(--acc-soft);color:var(--acc);user-select:all}

/* ── ROCKET ─────────────────────────────────────────────────
   Almost empty on purpose. One enormous number that is literally your payout, one
   fuse, one button. The density everywhere else is what stopped any single number
   from feeling like it mattered. */
.card.rkt{grid-column:1/-1;background:
  radial-gradient(120% 140% at 50% 120%, rgba(var(--acc-rgb),.10), transparent 60%), var(--surface);
  border-color:var(--acc-line)}
.rkt-tag{color:var(--acc)!important;border-color:var(--acc-line)!important;background:var(--acc-soft)}
.rkt-body{padding:26px 20px 20px;text-align:center}
.rkt-mult{font-family:var(--mono);font-size:clamp(56px,11vw,104px);font-weight:700;
  letter-spacing:-.06em;line-height:.95;color:var(--acc);
  text-shadow:0 0 44px rgba(var(--acc-rgb),.35);font-variant-numeric:tabular-nums}
.rkt-mult i{font-style:normal;font-size:.42em;opacity:.5;margin-left:2px}
.rkt-mult.dead{color:var(--down);text-shadow:0 0 44px rgba(var(--down-rgb),.4)}
.rkt-sub{font-family:var(--mono);font-size:var(--fs-sm);color:var(--dim);margin-top:8px}
.rkt-sub b{color:var(--down)}

/* the fuse: how close the coin is to rugging the round */
.fuse{height:6px;border-radius:var(--r-2);background:var(--line);overflow:hidden;
  margin:18px auto 6px;max-width:520px}
.fuse i{display:block;height:100%;border-radius:var(--r-2);
  background:linear-gradient(90deg,var(--up),var(--acc) 55%,var(--down));
  transition:width var(--dur-5) var(--ease)}
.rkt-fuseline{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim-2)}

.rkt-me{display:flex;align-items:center;justify-content:center;gap:10px;margin-top:20px;
  font-family:var(--mono);font-size:var(--fs-md);color:var(--dim);flex-wrap:wrap}
.rkt-me b{color:var(--txt);font-size:var(--fs-base)}
.rkt-worth{color:var(--acc);font-size:var(--fs-lg);font-weight:600}
.rkt-eject{background:var(--up);color:var(--on-up);font-weight:700;padding:10px 22px;font-size:var(--fs-base)}
.rkt-eject:hover:not(:disabled){background:var(--up-hi)}
.rkt-board{margin-top:20px}
.rkt-go{padding:12px 30px;font-size:var(--fs-base);font-weight:700}

.card.rkt.crashed{border-color:var(--down);
  background:radial-gradient(120% 140% at 50% 120%, rgba(var(--down-rgb),.14), transparent 60%), var(--surface);
  animation:rktboom .5s var(--ease)}
@keyframes rktboom{
  0%{transform:scale(1.015);box-shadow:0 0 0 0 rgba(var(--down-rgb),.5)}
  100%{transform:scale(1);box-shadow:0 0 0 30px rgba(var(--down-rgb),0)}
}
.card.rkt.done{opacity:.72}

.rkt-nodeadline{margin-left:auto;font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim-2)}
.rkt-mult{transition:none}   /* streamed at 60fps; a transition would smear it */

/* ── rocket history ─────────────────────────────────────────
   Every crash game shows the last dozen results. Without it each round is an
   isolated coin flip; with it you can see the distribution and the next launch
   becomes a judgement rather than a guess. */
.rkt-hist{display:flex;gap:5px;justify-content:center;flex-wrap:wrap;margin-bottom:18px}
.rh{font-family:var(--mono);font-size:var(--fs-xs);padding:3px 8px;border-radius:var(--r-6);
  border:1px solid var(--line-2);color:var(--dim)}
.rh.good{color:var(--up);border-color:rgba(var(--up-rgb),.32);background:rgba(var(--up-rgb),.07)}
.rh.bad{color:var(--down);border-color:rgba(var(--down-rgb),.30);background:rgba(var(--down-rgb),.07)}

/* ── rocket curve ───────────────────────────────────────────
   The number alone was a readout. A curve is a thing you watch — it has shape,
   momentum, and a visible history of the ride you are still on. */
.rkt-chart{position:relative;height:200px;margin:0 auto 6px;max-width:640px}
.rkt-chart svg{width:100%;height:100%;display:block;overflow:visible}
.rkt-chart svg.dead .rc-line{stroke:var(--down)}
.rkt-chart svg.dead .rc-fill{fill:rgba(var(--down-rgb),.16)}
.rkt-chart svg.dead .rc-dot{fill:var(--down)}
.rc-line{filter:drop-shadow(0 0 10px rgba(var(--acc-rgb),.55))}
.rc-dot{filter:drop-shadow(0 0 8px rgba(var(--light-rgb),.9))}
.rc-grid{position:absolute;inset:0;pointer-events:none;border-bottom:1px solid var(--line);
  background-image:linear-gradient(var(--line) 1px,transparent 1px);
  background-size:100% 50px;opacity:.5}
.card.rkt .rkt-mult{margin-top:-12px}
@media(max-width:640px){ .rkt-chart{height:150px} }

/* ── instant games ──────────────────────────────────────────
   Two ways to earn points that resolve on click. Everything else on the site waits
   for a window; these are where you sit. */
.gstake{display:flex;align-items:center;gap:12px;padding:11px 16px;margin-bottom:6px;
  border:1px solid var(--line);border-radius:var(--r-4);background:var(--surface)}
.hl-idle{text-align:center;padding:26px 20px}
.hl-idle button{margin-top:14px}
.hl{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;padding:26px 18px}
.hl-side{text-align:center}
.hl-sym{font-size:var(--fs-2xl);font-weight:650;letter-spacing:-.03em}
.hl-val{font-family:var(--mono);font-size:36px;font-weight:600;letter-spacing:-.04em;margin-top:6px}
.hl-val.hidden{color:var(--dim-2)}
.hl-meta{font-family:var(--mono);font-size:var(--fs-xs);color:var(--dim-2);margin-top:4px}
.hl-vs{font-family:var(--mono);font-size:var(--fs-sm);color:var(--dim-2);letter-spacing:.2em}
.hl-hi{background:var(--up);color:var(--on-up);font-weight:700;padding:10px 22px}
.hl-lo{background:var(--down);color:var(--on-down);font-weight:700;padding:10px 22px}
.hl-hi:hover:not(:disabled){background:var(--up-hi)}
.hl-lo:hover:not(:disabled){background:var(--down-hi)}

.mf-mines{display:flex;align-items:center;gap:10px;justify-content:center;margin-top:14px}
.mf-mines .qs{padding:6px 12px}
.mfgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(88px,1fr));gap:8px;padding:16px}
.mft{aspect-ratio:1;border:1px solid var(--line-2);border-radius:var(--r-4);background:var(--bg-1);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  cursor:pointer;transition:transform var(--dur-1) var(--ease),border-color var(--dur-2),background var(--dur-2)}
.mft:hover{transform:translateY(-3px);border-color:var(--acc-line);background:var(--surface-2)}
.mft-q{font-family:var(--mono);font-size:var(--fs-2xl);color:var(--dim-2)}
.mft-sym{font-size:var(--fs-md);font-weight:650;letter-spacing:-.02em}
.mft-chg{font-family:var(--mono);font-size:var(--fs-xs)}
.mft.safe{border-color:rgba(var(--up-rgb),.4);background:rgba(var(--up-rgb),.07);cursor:default}
.mft.mine{border-color:var(--down);background:rgba(var(--down-rgb),.13);cursor:default;
  animation:hitflash .6s var(--ease)}
.mft.safe:hover,.mft.mine:hover{transform:none}
@media(max-width:640px){
  .hl{grid-template-columns:1fr;gap:8px}
  .hl-vs{display:none}
  .mfgrid{grid-template-columns:repeat(4,1fr);gap:6px}
  .mft-sym{font-size:var(--fs-xs)}
}

/* ── over / under ───────────────────────────────────────── */
.ou{padding:22px 18px;text-align:center}
.ou-line{display:flex;align-items:center;justify-content:center;gap:18px;flex-wrap:wrap}
.ou-val{font-family:var(--mono);font-size:44px;font-weight:600;letter-spacing:-.04em;
  min-width:150px;color:var(--acc)}
.ou-val i{font-style:normal;font-size:.45em;opacity:.55}
.ou-dir{background:transparent;border:1px solid var(--line-2);color:var(--dim);padding:10px 18px}
.ou-dir.on[data-dir="over"]{background:var(--up);color:var(--on-up);border-color:var(--up);font-weight:700}
.ou-dir.on[data-dir="under"]{background:var(--down);color:var(--on-down);border-color:var(--down);font-weight:700}
#ouslider{width:100%;max-width:460px;margin:18px 0 8px;accent-color:var(--acc)}
.ou-hint{font-family:var(--mono);font-size:var(--fs-sm);color:var(--dim)}
.ou-hint b{color:var(--txt)}
.ou-last{font-family:var(--mono);font-size:var(--fs-sm);margin-top:14px;padding-top:12px;
  border-top:1px solid var(--line)}

/* ── crash chart axes ───────────────────────────────────────
   Labelled ticks are most of why a reference crash chart reads as an instrument
   rather than decoration — without a scale there is nothing to judge the climb
   against, which is why it looked flat however steep it actually was. */
.rc-axis line{stroke:var(--line);stroke-width:1}
.rc-axis text{fill:var(--dim-2);font-family:var(--mono);font-size:var(--fs-xs)}
.rc-axis .xt{fill:var(--dim-2);font-size:var(--fs-mini)}
.rkt-chart{height:250px}
.rkt-chart svg{overflow:visible}
.rc-line{stroke-width:3.5}

/* Three prediction markets, one row. A wall of full-width cards buried them. */
.grid{grid-template-columns:repeat(3,1fr)}
.card.rkt{grid-column:1/-1}
@media(max-width:1000px){ .grid{grid-template-columns:repeat(2,1fr)} }
@media(max-width:680px){ .grid{grid-template-columns:1fr} .rkt-chart{height:190px} }

/* three instant games side by side, same rhythm as the markets row */
.gamegrid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;align-items:start}
.gamegrid .card{margin-bottom:0}
.gamegrid .hl{grid-template-columns:1fr;gap:6px;padding:18px 14px}
.gamegrid .hl-vs{display:none}
.gamegrid .hl-val{font-size:var(--fs-3xl)}
.gamegrid .ou-val{font-size:32px;min-width:110px}
.gamegrid .mfgrid{grid-template-columns:repeat(4,1fr);gap:5px;padding:12px}
.gamegrid .mft{font-size:var(--fs-xs)}
.gamegrid .mft-sym{font-size:var(--fs-mini)}
@media(max-width:1000px){ .gamegrid{grid-template-columns:1fr} }

/* ═══ INSTANT GAMES ═════════════════════════════════════════
   Rebuilt from text-swaps into things with a reveal moment. The research on crash
   UIs is blunt about three things and all three were missing: anticipation before a
   result, instant tactile response to every press, and a cash-out control that is
   impossible to miss under stress. */

.game{display:flex;flex-direction:column;overflow:hidden}
.g-head{display:flex;align-items:center;gap:9px;padding:12px 15px;border-bottom:1px solid var(--line)}
.g-name{font-size:var(--fs-md);font-weight:650;letter-spacing:-.02em}
.g-tag{font-family:var(--mono);font-size:var(--fs-mini);letter-spacing:.09em;text-transform:uppercase;
  color:var(--dim-2);border:1px solid var(--line-2);padding:2px 7px;border-radius:var(--r-2)}
.g-mult{margin-left:auto;font-family:var(--mono);font-size:var(--fs-xl);font-weight:600;
  color:var(--acc);letter-spacing:-.03em}
.g-mult.dead{color:var(--down)}
.g-streak{margin-left:auto;font-family:var(--mono);font-size:var(--fs-xs);color:var(--acc);
  border:1px solid var(--acc-line);background:var(--acc-soft);padding:2px 7px;border-radius:var(--r-2)}
.g-body{padding:16px 15px;flex:1;display:flex;flex-direction:column;justify-content:center}
.g-intro{align-items:center;text-align:center;gap:14px;min-height:190px}
.g-introtxt{font-size:var(--fs-md);color:var(--txt-2);line-height:1.6}
.g-foot{display:flex;align-items:center;gap:10px;padding:12px 15px;
  border-top:1px solid var(--line);background:var(--bg-1)}
.g-res{font-family:var(--mono);font-size:var(--fs-sm);color:var(--dim)}
.g-res b{font-size:var(--fs-lg);font-weight:600}
.g-res.up{color:var(--up)} .g-res.down{color:var(--down)}

/* every control answers the press before the network does */
.g-cta,.g-hi,.g-lo,.g-collect{font-weight:700;letter-spacing:-.01em;
  transition:transform var(--dur-1) var(--ease-2),filter var(--dur-1),background var(--dur-1)}
.g-cta:active:not(:disabled),.g-hi:active:not(:disabled),
.g-lo:active:not(:disabled),.g-collect:active:not(:disabled){transform:scale(.955)}
.g-cta{margin-left:auto;padding:9px 18px}
.busy{opacity:.55;pointer-events:none}
.g-hi,.g-lo{flex:1;padding:13px 0;font-size:var(--fs-md);font-family:var(--mono);letter-spacing:.06em}
.g-hi{background:var(--up);color:var(--on-up)} .g-hi:hover:not(:disabled){background:var(--up-hi)}
.g-lo{background:var(--down);color:var(--on-down)} .g-lo:hover:not(:disabled){background:var(--down-hi)}

/* ── higher / lower: the flip IS the game ── */
.g-ladder{display:flex;gap:4px;padding:0 15px 2px}
.rung{flex:1;text-align:center;font-family:var(--mono);font-size:var(--fs-mini);padding:3px 0;
  border-radius:var(--r-2);color:var(--dim-2);background:var(--bg-1);transition:var(--dur-4) var(--ease)}
.rung.on{color:var(--on-acc);background:var(--acc);font-weight:700}
.hl2{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;min-height:190px}
.hl-mid{font-family:var(--mono);font-size:var(--fs-mini);color:var(--dim-2);letter-spacing:.16em}
.hlcard,.hlface{border:1px solid var(--line-2);border-radius:var(--r-5);background:var(--bg-1);
  padding:16px 8px;text-align:center;min-height:150px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}
.hl-t{font-family:var(--mono);font-size:var(--fs-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--dim-2)}
.hl-s{font-size:var(--fs-base);font-weight:650;letter-spacing:-.02em}
.hl-s.dim{color:var(--dim-2)}
.hl-n{font-family:var(--mono);font-size:var(--fs-3xl);font-weight:600;letter-spacing:-.04em}
.hl-q{font-family:var(--mono);font-size:40px;color:var(--dim-2)}

.hlflip{position:relative;min-height:150px;perspective:1000px}
.hlflip .hlface{position:absolute;inset:0;backface-visibility:hidden;
  transition:transform var(--dur-5) var(--ease-smooth)}
.hlflip .back{transform:rotateY(0deg)}
.hlflip .front{transform:rotateY(180deg)}
.hlflip.on .back{transform:rotateY(-180deg)}
.hlflip.on .front{transform:rotateY(0deg)}
.hlface.front.win{border-color:var(--up);background:rgba(var(--up-rgb),.10);
  box-shadow:0 0 30px rgba(var(--up-rgb),.18)}
.hlface.front.lose{border-color:var(--down);background:rgba(var(--down-rgb),.10)}

/* ── over / under: draw the distribution, do not assert the odds ── */
.ouchart{position:relative;height:120px;margin-bottom:6px}
.oubars{display:flex;align-items:flex-end;gap:1px;height:100%;
  border-bottom:1px solid var(--line)}
.oubars i{flex:1;background:var(--line-2);border-radius:2px 2px 0 0;
  transition:background var(--dur-2),height var(--dur-3) var(--ease)}
.oubars i.in{background:var(--acc)}
.ouline{position:absolute;top:-4px;bottom:0;width:2px;background:var(--txt);
  transition:left var(--dur-1) linear;pointer-events:none}
.ouline span{position:absolute;top:-18px;left:50%;transform:translateX(-50%);
  font-family:var(--mono);font-size:var(--fs-mini);color:var(--txt);white-space:nowrap}
.oumark{position:absolute;bottom:-2px;transform:translateX(-50%);
  font-family:var(--mono);font-size:var(--fs-micro);padding:2px 5px;border-radius:var(--r-2);white-space:nowrap;
  animation:drop var(--dur-5) var(--ease-spring)}
.oumark.win{background:var(--up);color:var(--on-up)} .oumark.lose{background:var(--down);color:var(--on-down)}
@keyframes drop{from{transform:translate(-50%,-26px);opacity:0}to{transform:translate(-50%,0);opacity:1}}
#ouslider{width:100%;accent-color:var(--acc);margin:6px 0 10px}
.oudirs{display:flex;gap:8px}
.oud{flex:1;padding:10px 0;font-family:var(--mono);font-size:var(--fs-sm);letter-spacing:.06em;
  background:transparent;border:1px solid var(--line-2);color:var(--dim)}
.oud.on[data-dir="over"]{background:var(--up);color:var(--on-up);border-color:var(--up);font-weight:700}
.oud.on[data-dir="under"]{background:var(--down);color:var(--on-down);border-color:var(--down);font-weight:700}

/* ── minefield: tiles turn over, they do not blink ── */
.mfgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.mft{position:relative;aspect-ratio:1;perspective:600px;cursor:pointer}
.mfface{position:absolute;inset:0;border-radius:var(--r-4);border:1px solid var(--line-2);
  background:var(--bg-1);display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:2px;backface-visibility:hidden;
  transition:transform var(--dur-4) var(--ease-smooth),border-color var(--dur-2),background var(--dur-2)}
.mfface.back{font-family:var(--mono);font-size:var(--fs-lg);color:var(--dim-2)}
.mfface.front{transform:rotateY(180deg)}
.mft.flipped .back{transform:rotateY(-180deg)}
.mft.flipped .front{transform:rotateY(0deg)}
.mft:not(.flipped):hover .back{border-color:var(--acc-line);background:var(--surface-2);
  transform:translateY(-2px)}
.mft:not(.flipped):active .back{transform:scale(.94)}
.mft.safe .front{border-color:rgba(var(--up-rgb),.45);background:rgba(var(--up-rgb),.09)}
.mft.mine .front{border-color:var(--down);background:rgba(var(--down-rgb),.16);
  animation:mineshock .5s var(--ease)}
@keyframes mineshock{
  0%{box-shadow:0 0 0 0 rgba(var(--down-rgb),.6)}
  100%{box-shadow:0 0 0 16px rgba(var(--down-rgb),0)}
}
.mft-s{font-size:var(--fs-xs);font-weight:650;letter-spacing:-.02em}
.mft-c{font-family:var(--mono);font-size:var(--fs-micro)}
.mfsel{display:flex;gap:5px;justify-content:center;flex-wrap:wrap}

/* the collect button is the most important control on the board */
.g-collect{margin-left:auto;background:var(--up);color:var(--on-up);padding:12px 20px;
  font-size:var(--fs-md);font-family:var(--mono);letter-spacing:.03em;
  box-shadow:0 0 0 0 rgba(var(--up-rgb),.5);animation:collectpulse 1.8s ease-in-out infinite}
.g-collect:hover:not(:disabled){background:var(--up-hi)}
.g-collect:disabled{animation:none;background:var(--line-2);color:var(--dim)}
@keyframes collectpulse{
  0%,100%{box-shadow:0 0 0 0 rgba(var(--up-rgb),.42)}
  50%{box-shadow:0 0 0 9px rgba(var(--up-rgb),0)}
}
@media(prefers-reduced-motion:reduce){
  .g-collect{animation:none}
  .hlflip .hlface,.mfface{transition:none}
}

/* ══════════════════════ THE CELEBRATION ══════════════════════
   Owned by public/games.js. The `.bigwin` overlay and its two original tiers live in
   floor.css beside the rest of the game floor; what is here is the third tier above
   them and the room line, both added by the pass that turned a big win from a toast
   into a moment.

   The performance rule the floor established and this obeys: nothing that MOVES may
   carry a shadow, a filter or a backdrop-filter, and every animation is transform or
   opacity only, so it runs on the compositor and never triggers layout or paint. The
   floor went from 25.3ms a frame to a fifth of a millisecond by deleting exactly those
   things, and a celebration is the obvious place to put them back.

   The one exception is the static text-shadow on the overlay's number, which is the
   pattern already set by `.bw-mult` in floor.css: it is set once on an element that is
   only ever transformed, so it is rasterised once and composited from then on. */

/* ── the top tier ──
   500x and up. Deliberately rare: the floor's own paytables can reach it, but on most
   games only through the single slot that pays for all the others, which is precisely
   what makes it worth building a look for. */
.bigwin.max{animation-duration:3.2s}
.bigwin.max .bw-mult{
  color:var(--acc);
  font-size:clamp(76px,19vw,220px);
  text-shadow:0 0 130px rgba(var(--acc-rgb),.7);
}
.bigwin.max .bw-pay{color:var(--acc);font-size:clamp(20px,3.4vw,34px)}

/* ── the room line ──
   One line above the ticker saying what just landed on this floor, to whoever it
   landed on. Height is reserved by the grid rather than animated, so the ticker under
   it does not jump when a notice arrives: it is opacity and transform only, and the
   element keeps its box whether or not it is showing. */
.groom{
  display:flex;align-items:center;gap:8px;
  margin:0 12px 6px;padding:7px 12px;
  border:1px solid rgba(var(--acc-rgb),.34);
  border-radius:var(--r-3);
  background:rgba(var(--acc-rgb),.09);
  font-size:var(--fs-xs);color:var(--txt-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  /* Out of the flow until it has something to say. `visibility` rather than `display`
     so the transition below has two states to move between. */
  opacity:0;transform:translateY(-6px);visibility:hidden;
  transition:opacity var(--dur-3,240ms) var(--ease-2,ease),
             transform var(--dur-3,240ms) var(--ease-2,ease),
             visibility 0s linear var(--dur-3,240ms);
}
.groom.on{
  opacity:1;transform:translateY(0);visibility:visible;
  transition:opacity var(--dur-4) var(--ease-spring),
             transform var(--dur-4) var(--ease-spring),
             visibility 0s;
}
.groom b{color:var(--txt);font-weight:650}
.groom em{font-style:normal;color:var(--acc);font-weight:700;letter-spacing:-.02em}
.groom u{text-decoration:none;color:var(--up);font-weight:650;margin-left:auto}
.groom-game{color:var(--dim)}
.groom-dot{
  flex:0 0 auto;width:6px;height:6px;border-radius:50%;background:var(--acc);
  animation:groom-dot 1.4s ease-in-out infinite;
}
/* Scale and opacity only. A pulsing box-shadow here is a repaint of the row on every
   frame of a live game canvas, which is the class of effect the floor's pass deleted. */
@keyframes groom-dot{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.55);opacity:.55}}

/* A ticker chip that cleared the big-win line. Static border and colour, no animation:
   thirty of these are on screen at once and the strip scrolls. */
.tk.big{border-color:rgba(var(--acc-rgb),.45);background:rgba(var(--acc-rgb),.08)}
.tk.big i{color:var(--acc);font-weight:700}

/* ── reduced motion ──
   Genuinely off, not softened. The overlay and the room line still APPEAR, because
   both carry information somebody asked for, and the number is the whole point of the
   celebration. Nothing moves to deliver it. The screenshake and the sparks are refused
   in games.js rather than here, because they are canvas and script rather than CSS and
   a stylesheet cannot switch them off. */
@media(prefers-reduced-motion:reduce){
  .bigwin.max{animation:none}
  .groom{transition:none}
  .groom-dot{animation:none}
}
