/* ===== IDENTITY LAYER ===== */
/* ============================================================
   QUIZ NIGHT — the arcade cabinet.
   Replaces the CONTOUR sheet. Dark shell, chunky cards that sit on
   a solid drop (0 Npx 0 rather than a blur), one warm gold for
   anything you can act on. Archivo carries the headings, DM Sans
   the prose, IBM Plex Mono every small caps label.

   The palette is per-mode: daily green, unlimited blue, higher or
   lower rust, party purple. Each colour ships with its own shadow
   so the drop reads as the same block in shadow, not a grey haze.
   ============================================================ */
/* THE FONTS ARE REQUESTED FROM <head>, NOT HERE. An @import has to precede
   every other rule in its stylesheet; this file has one <style> block and
   this point is some 26,000 characters and several hundred rules into it,
   so the browser discarded it and the page has been rendering in system
   fallbacks — Archivo, DM Sans and Plex Mono never arrived. Proof, before
   the fix: document.fonts held 0 faces here and 35 on leaderboards.html,
   which asks with a <link>. Do not move the request back into the CSS. */

:root{
  --ink:#1B1828; --ink-2:#14121F; --ink-3:#100E19; --page:#14121F;
  /* The card's own colour as components, so a gradient can fade to it
     at zero alpha. See .cat-marquee::before. */
  --ink-rgb:27,24,40;
  --gold:#B8E62B; --gold-sh:#4E7A16; --gold-dim:#8FA85E;
  /* HOVER AND TINT, DERIVED FROM THE ACCENT rather than typed out again.
     Every warm literal below used to be the old gold — #f0b25f on the Lock in
     hover, #ffc978 on link hovers, rgba(var(--gold-rgb),a) on eight washes — so the
     palette changed everywhere except the moment you touched something, which
     is exactly when a stale colour is most visible.
     --gold-rgb exists because a wash needs its own alpha at each call site and
     rgba() cannot take a hex token. */
  --gold-hi:#CBF04E;
  --gold-rgb:184,230,43;
  /* THE CAP'S OWN THREE COLOURS, so the mark can invert without dragging the
     accent with it. Concept 2c ships both treatments: a lime face with an ink
     glyph at hero size, and an ink face with a lime glyph for the small
     lockups. Light mode wants the second — the accent darkens to hold its own
     on cream, and a dark glyph on a dark-green cap is the one combination the
     sheet never uses. Separate tokens rather than reusing --ink-2, which also
     feeds --bg2 and would repaint half the page to fix a logo. */
  --cap-face:var(--gold); --cap-lip:var(--gold-sh); --cap-ink:#14121F;
  /* 2c's second colour: the tagline, the small caps labels. */
  --amber:#F0B23C;
  --rust:#C25A3A; --rust-sh:#8C3A22;
  /* THE SAME RUST, LIGHTENED, FOR THE FIVE PLACES IT IS TEXT. Hue and
     saturation are held exactly (14 degrees, 54%) and only lightness moves,
     49% -> 62%, so it still reads as the same colour rather than as a
     different one. --rust itself is untouched because it is a BACKGROUND
     everywhere else — the live pill, the guess bar, the rank ring — and
     lightening those would have dragged the white text on the pill down with
     it. 4.24:1 -> 6.29:1 on the page, and 3.05 -> 4.53 on --sheet-2, which is
     where .lvl-chip actually sits. */
  --rust-text:#D2826A;
  --mint:#57B894; --mint-sh:#2F7359;

  --m-daily:#0E5F53;  --m-daily-sh:#073F37;
  --m-unl:#1B4E7A;    --m-unl-sh:#0E3252;
  --m-hilo:#8A3B22;   --m-hilo-sh:#5C2413;
  /* Gauntlet Mode. A deep amber rather than a bright yellow, because the other
     four are all dark and desaturated with a shadow about two thirds their
     lightness, and a card that shouts would read as a warning next to them.

     CHOSEN BY CONTRAST, NOT BY EYE. The first amber tried here looked right and
     measured worst of the five — white on it was 5.0:1 for the title and 3.7:1
     for the button, against 7.6 and 5.1 on the daily. This one is 7.6:1 and
     5.1:1: the same numbers as the card above it, so the text carries exactly
     as well. (The button sits on rgba(255,255,255,.16) over the card, so its
     figure is measured against that composite, not against the card.) */
  --m-gaunt:#6B4F12;  --m-gaunt-sh:#47340C;
  --m-party:#5B3E86;  --m-party-sh:#3C265C;
  /* Gauntlet Live. Chosen the way the amber above it was — by contrast rather
     than by eye. White on it is 8.2:1 for the title and 5.7:1 for the button
     over its composite, which sits inside the range the other five occupy
     (7.5-8.7 and 5.1-5.7), so the type carries exactly as well as it does on
     the cards beside it. A red because it is the one that is on a clock. */
  --m-live:#8E2B3C;   --m-live-sh:#5E1C28;
  /* NFL Mode, and it is a GREEN because green is the one hue the other six do
     not use. They run teal (171), blue (207), amber (41), rust (16), purple
     (267) and red (349); this is 136, which is the only wide gap left and also
     happens to be the colour of the thing the mode is about. It shipped on the
     amber, which put two brown cards one above the other and made them read as
     one card with a fold in it.

     CHOSEN BY CONTRAST, like the two above. White on it is 7.9:1 for the title
     and 5.3:1 for the button over its composite, which sits inside the range
     the other six occupy (7.6-8.7 and 5.1-5.7), so the type carries exactly as
     well as it does on the cards beside it. The shadow is two thirds of its
     lightness, which is the relationship every other pair here holds. */
  --m-nfl:#245C31;    --m-nfl-sh:#183C20;
  /* GauntletGuesser. Amber, because amber is the mode's own signal — a guess
     that FITTED the clues and was still not the country is the state this game
     is about, and .gu-g.fit is that colour. The card and the clue accent are
     the same hue for that reason rather than for variety.

     NOT RE-CUT FOR LIGHT MODE, like every mode colour above it: these are the
     identity of each mode and a card that changed colour with the theme would
     stop being recognisable. */
  --m-guesser:#8A5A12; --m-guesser-sh:#5C3B0B;

  /* The two Higher or Lower answer buttons. Same hues as --m-hilo and --m-unl
     above, taken about a tenth darker so the white label punches harder — they
     are the most important thing on that screen and were reading dim.
     Separate tokens rather than a change to --m-hilo / --m-unl, because those
     also paint the home-screen mode cards, which carry small descriptive print
     that does not want a darker bed. Unchanged across themes: these keep their
     colour in light mode, which is why their label stays --on-accent white. */
  --hl-up:#7A3119;    --hl-down:#153F66;

  --sheet:rgba(255,255,255,.08);
  --sheet-2:rgba(255,255,255,.12);
  --sheet-3:rgba(255,255,255,.16);
  --hair:rgba(255,255,255,.09);

  /* the names the base sheet, the duel layer and the arena all read */
  --bg:var(--page); --bg2:var(--ink-2);
  --panel:var(--ink); --panel-2:#182A2E; --panel-3:#1E3237;
  --border:rgba(255,255,255,.12); --border-strong:rgba(255,255,255,.22);
  --text:#fff; --text-muted:#8FA6A6;
  --accent:var(--gold);
  --green:var(--mint); --yellow:#E8C44C; --orange:var(--rust); --red:#D2503F;
  --shelf:var(--gold); --deep:var(--gold); --abyss:#fff; --snow:var(--ink);
  --radius:14px;

  /* The two greys below the muted one. They were literals in ~27 places, which
     was survivable while there was one palette and is not now: a hard #B4C6C4
     is a light grey, and a light grey on the white sheet of light mode is
     nothing at all. */
  --text-soft:#B4C6C4;
  /* --text-faint IS GONE, August 2026. It was #5E7A78, which measured
     3.25:1 on the page and 2.87:1 on a sheet — under AA everywhere it was
     used, in both themes. Every value that would have fixed it landed on
     --text-muted to within a shade, because there is not room for four
     readable tiers between #fff and #14121F: "faint but still legible" and
     "muted" are the same colour once you require both halves. So the tier is
     gone rather than renamed, and its 27 uses now read --text-muted. */

  /* Text that sits on a SATURATED surface — a mode card, a Higher/Lower
     button, a rust badge — as opposed to text on the page or a panel. Those
     surfaces keep their colour in both themes, so their label stays white in
     both. It is a variable rather than a literal #fff purely so the difference
     is legible: `var(--on-accent)` says "white because of what is behind it",
     which is exactly the thing a light mode must not touch. */
  --on-accent:#fff;

  /* Tinted strips (top bar, mode banner, the Higher/Lower bar) and text fields.
     Both were literal rgba(0,0,0,…) — a black wash, which is a darkener on a
     dark sheet and a grey smear on a light one. */
  --bar-tint:rgba(0,0,0,.22);
  --field:rgba(0,0,0,.28);
  --field-lock:rgba(0,0,0,.45);
  /* Behind a centred overlay. Lighter in light mode — a heavy black wash over
     a white page reads as the lights going out rather than as focus. */
  --scrim:rgba(0,0,0,.58);
  /* The fill of anything that floats ABOVE the page — the auth modal, the
     player card, the level-up popup. Its own token rather than --panel because
     it must stay exactly #16262B in dark (the value it has always been) while
     going white in light. */
  --overlay:#16262B;

  --font:'Space Grotesk',system-ui,sans-serif;
  --display:'Archivo Black','Archivo',system-ui,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,monospace;

  /* How big the QUESTION reads, everywhere one is asked — the single-player
     and daily prompt (.qtext), the duel/battle/party prompt (.dx-qtext) and
     the Higher or Lower metric (.hl-metric). A multiplier rather than a size,
     because those three start at deliberately different sizes: one is the only
     thing on the screen, one shares a card with a clock and a scoreboard, and
     one is a heading over two cards. Scaling keeps that relationship while
     moving all three together.
     Every size it multiplies is a px value, including the ones inside the
     narrow-screen media queries below, so the phone tiers scale too — which is
     where unreadable actually happens.
     The admin console's Appearance tab writes this (see UI_SIZES there); it is
     an ordinary CSS variable, so applyUiConfig sets it with no special case.
     1 is the shipped size. */
  --q-scale:1;
}

/* ===========================================================================
   LIGHT MODE
   ---------------------------------------------------------------------------
   Dark is the shipped look and stays the default: no attribute on <html> means
   the palette above, exactly as before. Light is an OVERRIDE of the tokens and
   nothing else — there is not one duplicated rule below, and adding a component
   costs nothing here as long as it reads variables rather than hex.

   WHAT DOES NOT FLIP, and why the file has three separate text tokens:

     --on-accent   text on a mode card, a Higher/Lower button, a rust badge.
                   Those surfaces keep their colour in both themes, so their
                   label stays white in both. Flipping it is how you end up
                   with dark grey lettering on a dark green card.
     --m-*         the mode colours themselves, for the same reason: they are
                   the identity of each mode, not part of the sheet.

   The accents ARE re-cut rather than reused. #E8A44C gold is 2.1:1 on white,
   which is fine for a 52px number and unreadable for a 12px label, and the
   same gold is doing both jobs — so light mode gets a darker gold, rust and
   mint that hold up at small sizes.

   The theme is set by ggTheme() near the boot code, which writes
   data-theme="light" on <html> and remembers it. Everything below hangs off
   that one attribute.
   =========================================================================== */
html[data-theme="light"]{
  --ink:#FFFFFF; --ink-2:#F3F6F7; --ink-3:#EFEDE6; --page:#F7F4EC;
  --ink-rgb:255,255,255;

  /* Darkened for contrast on white — see the note above. The -sh shadows stay
     dark: they are the 3D lip under a button, not a surface.

     DARKENED AGAIN, AUGUST 2026, BECAUSE #5C8A0E DID NOT ACTUALLY CLEAR AA.
     The note above says this was chosen for contrast on white, and it was —
     but against the wrong thing. It was measured as a SURFACE, and it is also
     the background of the most important button in the game: LOCK IN is
     --ink-2 (#F3F6F7) on this token, which came to 3.79:1 where normal text
     needs 4.5. Bold 16px is not "large text" — that starts at 18.66px bold —
     so the exemption people reach for here does not apply.

     ONE TOKEN, THREE FIXES, and that is why it is a token change rather than a
     rule change. The same pair appears on .deck-chip.on and on .ac-item.active
     (the highlighted autocomplete row, which is part of the guess flow), and
     all three were failing by the same margin for the same reason.

     AND IT CARRIES THE TEXT USES WITH IT, unavoidably: `color:var(--gold)`
     appears 76 times and was 3.24:1 on the darkest light surface. There is no
     way to darken the button face without darkening those too, short of
     splitting the token in two — and a second gold that must be kept in step
     with the first by hand is a worse thing to own than a slightly deeper
     green. Both now clear: 5.48:1 on the button, 4.68:1 as text.

       white on it   3.79 -> 5.48
       it as text    3.24 -> 4.68   (on --sheet-2, the worst backdrop it lands on) */
  --gold:#4A6E0B; --gold-sh:#314A08; --gold-dim:#6E8A3E;
  /* Hover goes DARKER on cream, not lighter: the accent is already dark here
     so it can hold white label text, and lightening it on hover would walk it
     towards the page. Kept at the same ratio to --gold as before, so the hover
     step is the same size it always was rather than collapsing to nothing. */
  --gold-hi:#3D5A09;
  /* Follows --gold, or every wash built from it drifts off the accent. */
  --gold-rgb:74,110,11;
  /* 2c's inverted lockup — ink cap, lime glyph. See the note in the dark block. */
  --cap-face:#14121F; --cap-lip:#000000; --cap-ink:#B8E62B;
  --amber:#9A6B12;
  /* Light mode needed a smaller push than dark, but it did need one. #B04728
     reads 5.06:1 on the page and looked fine — but .lvl-chip sits on
     --sheet-2, where the same colour is 4.37:1, and the page is not the
     surface that decides. Two steps darker in lightness, hue and saturation
     untouched: 42% -> 40%, which clears every surface it lands on (4.78:1 on
     --sheet-2) and is not a visible change in colour.

     The test asserts against --sheet-2 for exactly this reason; measuring
     against the page is how the original 4.37 got written down as passing. */
  --rust-text:#A64326;
  --rust:#B04728; --rust-sh:#82301A;
  --mint:#1B7D5A; --mint-sh:#125940;

  /* The four sheets invert from white-on-dark to ink-on-white. Alphas are not
     mirrored 1:1 — a .08 white veil on near-black reads far stronger than a
     .08 black veil on white, so the light ones are pulled down. */
  --sheet:rgba(16,30,34,.045);
  --sheet-2:rgba(16,30,34,.075);
  --sheet-3:rgba(16,30,34,.11);
  --hair:rgba(16,30,34,.11);

  --bg:var(--page); --bg2:var(--ink-2);
  --panel:#FFFFFF; --panel-2:#F3F6F7; --panel-3:#E8EDEE;
  --border:rgba(16,30,34,.15); --border-strong:rgba(16,30,34,.30);

  --text:#0D1A1E; --text-muted:#54696C;
  --text-soft:#28393C;
  --abyss:#0D1A1E; --snow:#FFFFFF;

  --bar-tint:rgba(16,30,34,.05);
  --field:#FFFFFF;
  --field-lock:rgba(16,30,34,.07);
  --scrim:rgba(16,30,34,.34);
  --overlay:#FFFFFF;
}
/* The wrap is the app's card. On the dark sheet it separates itself by being
   lighter than the page; white on white has nothing to separate with, so it
   borrows a hairline and a soft shadow instead. */
html[data-theme="light"] .wrap{
  border:1px solid rgba(16,30,34,.10);
  box-shadow:0 1px 3px rgba(16,30,34,.06),0 10px 34px rgba(16,30,34,.05);
}
/* Every button in the cabinet is drawn with a hard 3D lip — `0 5px 0 <dark>`.
   Against white those read as heavy black bars, so the generic ones are
   softened. The mode cards and Higher/Lower buttons keep theirs: they set it
   from their own --m-*-sh, which is part of the colour. */
html[data-theme="light"] .deck-card,
html[data-theme="light"] .share-btn.ghost{
  box-shadow:0 4px 0 rgba(16,30,34,.13);
}
html[data-theme="light"] .deck-card:hover{box-shadow:0 6px 0 rgba(16,30,34,.13)}
html[data-theme="light"] .deck-card:active{box-shadow:0 2px 0 rgba(16,30,34,.13)}
/* The avatar disc keeps its dark fill in both themes (its initials are
   --on-accent), but the ring around a ranked player was tuned against black. */
html[data-theme="light"] .av[data-rank="black"]{box-shadow:0 0 0 2px #3A4A4D}
/* The autocomplete panels drop a `0 14px 30px rgba(0,0,0,.55)` — a shadow cast
   on nothing, because unlike a modal these have no scrim under them. On the
   dark sheet it never showed; over white it is a grey smear the width of the
   list. Softened rather than removed: the panel now shares --overlay with the
   page it floats over, so the shadow is the only thing lifting it off. */
html[data-theme="light"] .ac,
html[data-theme="light"] .fr-ac{box-shadow:0 10px 26px rgba(16,30,34,.14)}

/* ---- the toggle itself ---- */
.theme-btn{background:none;border:0;padding:8px 0;cursor:pointer;
  font-family:var(--font);font-size:13.5px;font-weight:700;
  color:var(--text-muted);display:inline-flex;align-items:center;gap:6px}
/* `background:none` and `transform:none` are not redundant. The superseded
   first stylesheet at the top of this file still carries a generic
   `button:hover{background:#2c3c68;transform:translateY(-1px)}`, and nothing in
   the current sheet overrides it — every other button here happens to set its
   own background, so this is the first one to notice. */
.theme-btn:hover{color:var(--text);background:none;transform:none}
.theme-btn:focus-visible{outline:2px solid var(--gold);outline-offset:3px;
  border-radius:6px}
.theme-btn .ti{font-size:14px;line-height:1}

/* small-caps label, used everywhere a field is named */
.k,.rlbl,.score-lbl,.mode-go,.deck-go,.hof-sub,.arch-date,.sr-lbl,
.hl-cap,.hl-stat,.final-lbl,.aw-lbl,.deck-lbl,.hof-date{
  font-family:var(--mono);font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;
}

body{
  color:var(--text);font-family:var(--font);font-size:16px;
  background:var(--page);
  background-image:none;
  padding:22px 18px 60px;
}
.wrap{max-width:1240px;margin:0 auto;background:var(--ink);
  border-radius:16px;overflow:hidden;position:relative}

/* ---------- top bar ---------- */
.authbar{display:flex;align-items:center;gap:26px;padding:15px 32px;
  background:var(--bar-tint);text-align:left;font-size:13.5px;color:var(--text-muted);
  font-family:var(--font);letter-spacing:normal;text-transform:none}
.authbar a{color:var(--gold);cursor:pointer;font-weight:700;text-decoration:none}
.authbar a:hover{color:var(--gold-hi)}
.brand{display:flex;align-items:center;gap:10px;cursor:pointer;text-decoration:none}
/* THE MARK — concept 2c, "Stacked Cap", copied at its own proportions.

 Two stacked rounded rects and a flex-centred Archivo Black "?", exactly as
 the concept sheet draws it. Every measurement below is 2c's own, divided by
 its 96px cap and written in em, so the whole thing scales from one number:
 set the badge's width and font-size together and the lip, the radius and
 the glyph all follow.

     container 106/96   lip top 18/96   lip 88/96
     face 92/96         radius 22/96    glyph 58/96

 The glyph is REAL TEXT, not a traced path. A path was the first attempt and
 it was visibly off-centre — hand-fitting a "?" to an optical centre is a
 thing type designers do properly and I did not. Letting the font do it, in
 a flex box, is both correct and what the sheet actually specifies.

 The -2px nudge is 2c's too: a "?" has more mass below its bowl than above
 the dot, so centring it geometrically leaves it sitting low. */
.brand-badge{position:relative;display:block;width:38px;font-size:38px;
  height:1.1042em;flex:none;transition:transform .12s ease}
.brand-badge i{position:absolute;left:0;width:100%;border-radius:.2292em}
.brand-badge .cap-lip{top:.1875em;height:.9167em;background:var(--cap-lip)}
.brand-badge .cap-face{top:0;height:.9583em;background:var(--cap-face);
  display:flex;align-items:center;justify-content:center}
.brand-badge .cap-face b{display:block;font:400 .6042em/1 'Archivo Black',var(--display);
  color:var(--cap-ink);transform:translateY(-.0345em)}
.brand:hover .brand-badge{transform:translateY(-1px)}
.brand:active .brand-badge{transform:translateY(2px)}
  @media(prefers-reduced-motion:reduce){
  .brand-badge{transition:none}
  .brand:hover .brand-badge,.brand:active .brand-badge{transform:none}
  }
.brand-name{font:900 20px/1 var(--display);letter-spacing:-.01em;color:var(--text);
  white-space:nowrap}
.topnav{display:flex;gap:22px;font-size:14px;font-weight:700;color:var(--text-muted)}
.topnav a{color:var(--text-muted);text-decoration:none;padding:8px 0;cursor:pointer;
  border-bottom:3px solid transparent}
.topnav a:hover{color:var(--text)}
.topnav a.on{color:var(--text);border-bottom-color:var(--gold)}
.bar-right{margin-left:auto;display:flex;align-items:center;gap:12px}
/* `#authUser` wraps the chip, Friends and Sign out. The base sheet had a
   " · " between each; the bar spaces them instead, so it has to be a flex
   row of its own. JS clears the inline display to reveal it, which is why
   the display lives here rather than on the element. */
#authUser{display:inline-flex;align-items:center;gap:14px}
#authGuest{white-space:nowrap}
.who-wrap{display:inline-flex}
.who-wrap .av{width:28px;height:28px;font-size:11px}
.user-chip{display:inline-flex;align-items:center;gap:8px;
  background:var(--sheet-2);border-radius:999px;padding:5px 14px 5px 5px;cursor:pointer}
.user-chip:hover{background:var(--sheet-3)}
.who{font-size:13.5px;font-weight:700;color:var(--text)}

/* the masthead the old sheet used is folded into the bar above */
header{display:none}

/* ---------- hero ---------- */
/* THE TITLE SITS CENTRED between the ticker above it and the daily button
   below. Both gaps are built from more than one rule — the ticker's own bottom
   padding and this padding-top above, this padding-bottom and .mode-hero's
   padding-top below — so the numbers here are chosen against a measurement
   rather than derived: 50px above and 30px below became 40 and 40.
   Ten points moved from one side to the other, so the total height of the
   block is exactly what it was and nothing below shifted. */
.hero{text-align:center;padding:24px 40px 10px}

/* THE CATEGORY TICKER — every category, drifting left to right across the
   full width of the card.

   Mono, uppercase, wide-tracked: the treatment every other label on the site
   wears (.mode-no, .asof, .tagpill), just larger. Quiet on purpose — this runs
   above the title and must not out-shout it. It used to take --text-faint for
   that; --text-muted is now the quietest tier there is, because faint was
   below AA in both themes and collapsed into muted rather than being tuned to
   a value that was muted in all but name.

   HOW THE LOOP IS SEAMLESS. The track holds the list TWICE and slides from
   -50% to 0. At -50% the second copy occupies the window; at 0 the first copy
   sits exactly where the second one was, and the two are identical, so the
   jump back is invisible. It is one CSS animation with no JavaScript timer at
   all — the earlier one-word-at-a-time version needed an interval, and this
   needs nothing but a repaint the compositor does on its own.

   -50% to 0 rather than 0 to -50%, which is the direction. Names enter at the
   left edge and travel right.

   The mask fades both ends so a word dissolves at the edge instead of being
   guillotined by the card's corner. */
/* Off screen, not display:none — a hidden element is not read out either. The
   only thing on the home screen that names the categories to a screen reader,
   now that the tagline under the title is gone. */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.cat-marquee{position:relative;overflow:hidden;padding:26px 0 6px}
/* THE ENDS FADE WITH PAINT, NOT WITH A MASK.

   It was a mask-image, and a mask on an overflow container with a wide
   animated child is one of the oldest intermittent-paint bugs on mobile
   Safari — the layer is dropped under memory pressure and rebuilt a moment
   later. "Loads in, gone after a refresh, in and out after that" is what that
   looks like from the outside. Making the mask correct did not help, because
   the mask itself was the problem.

   Two gradients painted over the ends need no mask and no second compositing
   layer on the thing that moves. They cover the track rather than deleting
   parts of it, so the worst failure available to them is being the wrong
   colour, which is visible and fixable rather than blank.

   --ink because that is what .wrap paints behind this strip in both themes,
   and rgba(--ink-rgb,0) rather than `transparent` at the far end: transparent
   is transparent BLACK, which can haze grey across the middle of a gradient. */
.cat-marquee::before,.cat-marquee::after{
  content:"";position:absolute;top:0;bottom:0;width:9%;
  pointer-events:none;z-index:1}
.cat-marquee::before{left:0;background:linear-gradient(90deg,
  rgba(var(--ink-rgb),1) 0,rgba(var(--ink-rgb),0) 100%)}
.cat-marquee::after{right:0;background:linear-gradient(270deg,
  rgba(var(--ink-rgb),1) 0,rgba(var(--ink-rgb),0) 100%)}
.cat-track{display:flex;align-items:center;width:max-content;
  animation:catmarq 44s linear infinite}
.cat-track span{flex:0 0 auto;padding:0 34px;
  font:700 38px/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;
  color:var(--text-muted)}
.cat-track i{flex:0 0 auto;width:7px;height:7px;border-radius:50%;
  background:var(--hair)}
@keyframes catmarq{
  from{transform:translateX(-50%)}
  to{transform:translateX(0)}
}
/* 25px is judged against a 1240px card. On a phone the same size fits barely
   two names and reads heavier than the nav above it, so it comes down with
   the screen — about four names across, which is what makes it read as a
   ticker rather than as a headline that happens to slide. */
@media(max-width:700px){
  .cat-marquee{padding:18px 0 4px}
  .cat-track span{font-size:24px;letter-spacing:.11em;padding:0 22px}
}
/* Asked not to animate: the track stops and JS renders ONE copy, which wraps
   as a plain block of category names rather than a frozen half-loop.

   AFTER the width rule on purpose. Both match on a phone with Reduce Motion
   on, and whichever comes last wins the size — with this block first, eight
   names wrapped down a narrow column at the ticker's full size. Reduced
   motion is the more specific intent, so it goes last. */
@media(prefers-reduced-motion:reduce){
  .cat-track{animation:none;width:100%;justify-content:center;flex-wrap:wrap;
    gap:2px 0}
  .cat-track span{font-size:19px;letter-spacing:.12em;padding:0 14px}
}
@media(prefers-reduced-motion:reduce) and (max-width:700px){
  .cat-track span{font-size:15px;letter-spacing:.1em;padding:0 10px}
}
.hero-live{display:inline-flex;align-items:center;gap:9px;background:var(--rust);
  border-radius:999px;padding:9px 18px;font:700 11.5px/1 var(--mono);
  letter-spacing:.12em;box-shadow:0 3px 0 var(--rust-sh);color:var(--on-accent)}
.hero-live i{width:8px;height:8px;border-radius:50%;background:var(--on-accent);
  animation:ggbulb 1.6s ease-in-out infinite}
@keyframes ggbulb{0%,100%{opacity:1}50%{opacity:.35}}
.hero-h{font:900 50px/1.02 var(--display);margin:16px 0 0;letter-spacing:-.03em}

/* ---------- modes ---------- */
.modes{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;
  padding:30px 40px 10px;border:0;border-radius:0;background:none;overflow:visible}
/* The other three, under the hero. Same tiles, one column narrower each. */
.modes-rest{grid-template-columns:repeat(3,1fr);padding-top:14px}
/* TALLER THAN THE HEROES, AND THE NAME IN THE MIDDLE OF IT. These three hold
   one word each — the sentence under them is gone again (see index.html) — so
   the card is mostly the colour it is painted, which is the point of it. The
   name sits centred in the space rather than pinned to a corner with the call
   to action a long way under it.

   THE CALL TO ACTION COMES OUT OF THE FLOW so the name can centre on the BOX
   rather than on the space left above it. In flow it took ~44px off the
   bottom, which put the name 22px high in a 170px card — close enough to look
   like a mistake rather than a decision.

   THAT IS ALSO WHY THE SENTENCE CANNOT COME BACK WITHOUT THIS GOING FIRST: an
   absolutely positioned button leaves no room behind it, so a description
   restored under these rules runs underneath it. The two halves are one
   change. It was made, reverted, and made again on the same day; if a third
   person wants the sentences back, take these rules out in the same commit.

   WIDER THAN ITS TEXT, NARROWER THAN THE CARD. Sized to the word it holds the
   button read as a caption; edge to edge it read as a bar across the bottom.
   62% is wide enough to look pressable and short enough to stay a button. */
.modes-rest .mode-card{min-height:170px;align-items:stretch;position:relative;
  text-align:center;padding:22px 20px 18px;gap:10px}
/* THE TITLE SITS AT THE TOP, where it lines up with the two hero cards above,
   so all five names start on the same edge and the row reads as one set. */
.modes-rest .mode-name{flex:0 0 auto;margin:14px 0 0;text-align:center}
.modes-rest .mode-go{position:absolute;left:50%;transform:translateX(-50%);
  bottom:16px;margin:0;text-align:center;white-space:nowrap;
  width:62%;padding:9px 0;border-radius:10px;background:rgba(0,0,0,.16)}
.mode-hero{padding:30px 40px 0}
/* The hero lays out sideways: title and description on the left, the call to
   action as a block on the right. Its own grid rather than a stretched tile,
   because a 250px-tall card the full width of the page is a billboard. */
/* width:100% is load-bearing. The tile is a <button>, and a form control
   shrink-to-fits its content no matter what display it is given — as a grid
   container it still came out 611px inside a 1158px row. */
/* minmax(0,auto) ON THE CTA COLUMN, not a bare `auto`. `auto` is
   minmax(min-content, max-content): a column that can never be narrower than
   its widest unbreakable run, so one long label pushes the whole grid past the
   card it is drawn in. The floor of 0 lets it give, and the text column is
   already free to shrink for the same reason. */
.mode-hero .mode-card{display:grid;width:100%;
  grid-template-columns:minmax(0,1fr) minmax(0,auto);
  grid-template-areas:"no cta" "name cta" "desc cta";
  align-items:center;gap:4px 32px;min-height:0;padding:24px 28px}
.mode-hero .mode-card > *{min-width:0}
.mode-hero .mode-no{grid-area:no}
/* min-width AND overflow-wrap ARE THE NEVER-AGAIN NET, not the fix.
   A grid column given minmax(0,1fr) may be narrower than the word inside it,
   and TEXT DOES NOT STOP AT ITS CELL — it paints straight over the next one.
   "GauntletGuesser" is one unbreakable 15-character word, so it cannot wrap
   the way "Gauntlet Live" does, and at 1280 it hung 28px across its own PLAY
   NOW. The bands below size the cards so this never has to fire; this is what
   happens if a future title outgrows them anyway. A word broken in the wrong
   place is ugly and legible. A word printed over a button is neither. */
.mode-hero .mode-name{grid-area:name;font-size:30px;line-height:1.05;
  display:flex;align-items:center;gap:10px;min-width:0;overflow-wrap:anywhere}
/* In the hero the badge is a flex item beside the title rather than an inline
   box inside its line, which is what keeps the row gap at 4px. */
.mode-hero .mode-name .dd-new{margin-left:0;flex:none}
.mode-hero .mode-desc{grid-area:desc;max-width:52ch;margin-top:2px}
/* `.mode-hero .mode-card.daily .mode-go`, not `.mode-hero .mode-go`. The base
   sheet styles this button through `.mode-card.daily .mode-go` at 0-3-0, so
   the shorter selector at 0-2-0 lost and the padding here never applied — the
   button rendered at `13px 0`, zero horizontal, with "Play now" touching both
   edges. That is the gap this rule is meant to create. */
/* `.live` IS IN THIS LIST AND WAS MISSING FROM IT — the same omission
   responsive.css:90 already carries a note about, in a second list that has to
   agree with this one. Without it `.mode-card.live .mode-go` never takes its
   grid area, so it falls to auto-placement and lands in a cell the title is
   already drawn in. It happens to be covered from 701px up by the .mode-pair
   blocks at the foot of this file, which is why nothing showed; take those
   away and the button prints across the name. A list of mode classes is the
   defect this file keeps repeating — see the sweep note below. */
.mode-hero .mode-card.daily .mode-go,
.mode-hero .mode-card.nfl .mode-go,
.mode-hero .mode-card.guesser .mode-go,
.mode-hero .mode-card.live .mode-go,
.mode-hero .mode-card.gauntlet .mode-go{grid-area:cta;align-self:center;
  margin-top:0;padding:18px 44px;font-size:14px;white-space:nowrap}
.mode-card{background:var(--m-unl);border:0;border-radius:18px;
  padding:26px 24px 24px;display:flex;flex-direction:column;gap:11px;
  cursor:pointer;box-shadow:0 7px 0 var(--m-unl-sh);min-height:250px;
  text-align:left;color:var(--on-accent);transition:transform .12s,box-shadow .12s;
  font-family:var(--font)}
.mode-card:hover{transform:translateY(-2px);box-shadow:0 9px 0 var(--m-unl-sh)}
.mode-card:active{transform:translateY(4px);box-shadow:0 3px 0 var(--m-unl-sh)}
.mode-card::before{display:none}
.mode-card.daily{background:var(--m-daily);box-shadow:0 7px 0 var(--m-daily-sh)}
.mode-card.gauntlet{background:var(--m-gaunt);box-shadow:0 7px 0 var(--m-gaunt-sh)}
.mode-card.gauntlet:hover{box-shadow:0 9px 0 var(--m-gaunt-sh)}
.mode-card.gauntlet:active{box-shadow:0 3px 0 var(--m-gaunt-sh)}
.mode-card.daily:hover{box-shadow:0 9px 0 var(--m-daily-sh)}
.mode-card.daily:active{box-shadow:0 3px 0 var(--m-daily-sh)}
.mode-card.unlimited{background:var(--m-unl);box-shadow:0 7px 0 var(--m-unl-sh)}
.mode-card.hilo{background:var(--m-hilo);box-shadow:0 7px 0 var(--m-hilo-sh)}
.mode-card.hilo:hover{box-shadow:0 9px 0 var(--m-hilo-sh)}
.mode-card.hilo:active{box-shadow:0 3px 0 var(--m-hilo-sh)}
.mode-card.live{background:var(--m-live);box-shadow:0 7px 0 var(--m-live-sh)}
.mode-card.live:hover{box-shadow:0 9px 0 var(--m-live-sh)}
.mode-card.live:active{box-shadow:0 3px 0 var(--m-live-sh)}
.mode-card.nfl{background:var(--m-nfl);box-shadow:0 7px 0 var(--m-nfl-sh)}
.mode-card.nfl:hover{box-shadow:0 9px 0 var(--m-nfl-sh)}
.mode-card.nfl:active{box-shadow:0 3px 0 var(--m-nfl-sh)}
/* Without these three the card silently falls back to --m-unl and looks like
   Unlimited — which is the one failure on this page that nothing reports. */
.mode-card.guesser{background:var(--m-guesser);box-shadow:0 7px 0 var(--m-guesser-sh)}
.mode-card.guesser:hover{box-shadow:0 9px 0 var(--m-guesser-sh)}
.mode-card.guesser:active{box-shadow:0 3px 0 var(--m-guesser-sh)}
/* THE LIVE CALL TO ACTION IS THE ONLY VARIABLE-LENGTH ONE ON THIS SCREEN.
   "Play now" and "Play today's daily" are written down; this one is built from
   the room's state — "Join the lobby &middot; 3 waiting", "Back to the lobby",
   "Watch for the next one", "Back to the lobby" — and the longest of those is
   three times the shortest. So it does NOT get `white-space:nowrap` the way
   its two neighbours do: a nowrap box in a grid column sized to its own
   content is a box that grows until it leaves the card, which is exactly what
   the longest label did. It wraps instead, and the padding is narrower to give
   it somewhere to go before it has to. */
.mode-hero .mode-card.live .mode-go{grid-area:cta;align-self:center;
  margin-top:0;padding:16px 26px;font-size:14px;white-space:normal;
  line-height:1.2;max-width:100%;min-width:0}
/* THE CLOCK IS THE POINT OF THE CARD, so it sits where the number would and is
   set at the number's size — a countdown at caption size is something you have
   to go looking for. `tabular-nums` because it changes every second and a
   proportional 1 makes the whole line jump. */
.mode-live-when{grid-area:no;display:flex;align-items:baseline;gap:8px;
  font:900 13px/1 var(--display);letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.72)}
.mode-live-when b{font-size:19px;letter-spacing:.02em;color:#fff;
  font-variant-numeric:tabular-nums}
.mode-card.multiplayer{background:var(--m-party);box-shadow:0 7px 0 var(--m-party-sh)}
.mode-card.multiplayer:hover{box-shadow:0 9px 0 var(--m-party-sh)}
.mode-card.multiplayer:active{box-shadow:0 3px 0 var(--m-party-sh)}
.mode-card.distance{background:var(--m-daily);box-shadow:0 7px 0 var(--m-daily-sh)}
.mode-no{font:900 13px/1 var(--mono);letter-spacing:.14em;color:rgba(255,255,255,.65)}
.mode-icon{display:none}
.mode-name{font:900 24px/1.05 var(--display);letter-spacing:-.015em;
  text-transform:none;color:var(--on-accent)}
.mode-desc{font-size:13px;line-height:1.5;font-weight:500;
  color:rgba(255,255,255,.88);grid-column:auto}
/* The base sheet tints each mode's call to action a different colour and
   packs the card to the left. Here the call is a block on the card's own
   colour, so both get overridden by name rather than by !important. */
.mode-card,.mode-card.daily,.mode-card.hilo,.mode-card.multiplayer{align-items:stretch}
.mode-go,
.mode-card.daily .mode-go,
.mode-card.gauntlet .mode-go,
.mode-card.unlimited .mode-go,
.mode-card.hilo .mode-go,
.mode-card.nfl .mode-go,
.mode-card.multiplayer .mode-go{
  background:rgba(255,255,255,.16);font:900 13px/1 var(--display);
  letter-spacing:.04em;padding:13px 0;border-radius:10px;text-align:center;
  cursor:pointer;color:var(--on-accent);text-transform:uppercase;
  /* Pinned to the BOTTOM of the card, not floated under the text. The cards
     are already equal height, but the descriptions are not — "Today's curated
     10..." runs to three lines where "Ten random questions..." takes two — so
     a button that simply followed the text sat 20px higher on two of the four.
     margin-top:auto eats the slack above it instead. */
  margin-top:auto}
.mode-card:hover .mode-go{background:rgba(255,255,255,.24)}
.mode-desc{min-height:0}

/* What to play next, after a daily. Two tiles rather than two more buttons in
   the row below: they are a different KIND of offer from "back to modes", and
   a row of four equal buttons is the choice-paralysis this change exists to
   reduce. */
.end-more{margin-top:22px;padding-top:18px;border-top:1px solid var(--hair)}
.end-more-t{font:700 10px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:10px}
.end-more-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.end-more-btn{display:flex;flex-direction:column;gap:4px;text-align:left;
  background:var(--sheet);border:1px solid var(--border);border-radius:12px;
  padding:13px 15px;cursor:pointer;color:var(--text);font-family:var(--font);
  transition:border-color .12s,background .12s}
.end-more-btn:hover{background:var(--sheet-2);border-color:var(--border-strong)}
.end-more-btn:disabled{opacity:.55;cursor:default}
.end-more-btn b{font:900 15px/1.1 var(--display)}
.end-more-btn i{font-style:normal;font-size:12px;color:var(--text-muted);line-height:1.4}
@media(max-width:560px){ .end-more-row{grid-template-columns:1fr} }

/* ---------- home panels: career board, party call, decks ---------- */
.home-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:20px 40px 34px}
.panel{background:var(--sheet);border-radius:16px;padding:18px 22px}
.panel-h{display:flex;justify-content:space-between;align-items:baseline;
  margin-bottom:10px;gap:12px}
.panel-t{font:900 15px/1 var(--display);letter-spacing:.02em;color:var(--text)}
.panel-link{font-size:12px;font-weight:700;color:var(--gold);cursor:pointer;
  text-decoration:none;white-space:nowrap}
.panel-link:hover{color:var(--gold-hi)}
.panel-sub{font-size:13.5px;line-height:1.5;color:var(--text-soft);font-weight:500}
.panel-foot{font:700 10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--text-muted);margin-top:10px}
.career-row{display:grid;grid-template-columns:20px 26px 1fr auto;gap:9px;
  align-items:center;padding:6px 0;border-bottom:1px solid var(--hair);font-size:13.5px}
.career-row:last-child{border-bottom:0}
.career-rank{font-weight:700;color:var(--text-muted)}
.career-name{font-weight:700;color:var(--text);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.career-n{font-weight:700;color:var(--gold);font-variant-numeric:tabular-nums}
.leaders{display:flex;flex-direction:column}
/* The three rows FILL the panel rather than bunching at the top: the slot
   takes the leftover height beside the career board, the card fills the slot,
   and the rows share what is left. A minimum keeps the panel from collapsing
   on a deck with only one score. */
.lead-slot{flex:1;display:flex;min-height:132px}
.lead-card{animation:leadIn .32s ease both;flex:1;display:flex;
  flex-direction:column;min-height:0}
@keyframes leadIn{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
.lead-deck{font:700 10px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);display:block;margin-bottom:8px;flex:none}
/* Every row grows to take its share of the slack. First place gets a little
   more of it than the other two, which stay identical to each other. */
.lead-row{display:flex;align-items:center;gap:10px;flex:1 1 0;min-height:0}
.lead-win{flex:1.25 1 0}
/* Second and third step back so the podium reads at a glance instead of as
   three equal lines. */
.lead-row:not(.lead-win){opacity:.62}
.lead-rank{font:900 11px/1 var(--mono);color:var(--text-muted);width:11px;flex:none}
.lead-who{font:800 14.5px/1.2 var(--font);color:var(--text);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lead-score{font:900 15px/1 var(--display);color:var(--gold);flex:none;
  font-variant-numeric:tabular-nums}
/* NOT :first-of-type. The deck heading above is a <span> too, so it is the
   first span in the card and the winner's row is the second — the rule
   silently matched nothing and all three rendered the same size. */
.lead-win .lead-who{font:900 17px/1.2 var(--display)}
.lead-win .lead-score{font-size:21px}
.lead-none{font-size:13px;color:var(--text-muted)}
.lead-dots{display:flex;gap:5px;margin-top:12px}
.lead-dots i{width:16px;height:3px;border-radius:2px;background:var(--hair);
  cursor:pointer;transition:background .2s}
.lead-dots i.on{background:var(--gold)}
.deck-strip{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.deck-chip{background:var(--sheet-2);border:0;border-radius:999px;padding:9px 16px;
  font-size:13.5px;font-weight:700;color:var(--text);cursor:pointer;font-family:var(--font)}
.deck-chip:hover{background:var(--sheet-3)}
.deck-chip.on{background:var(--gold);color:var(--ink-2)}

.hof-btn{font:900 13px/1 var(--display);letter-spacing:.04em;text-transform:uppercase;
  background:var(--sheet-2);border:0;border-radius:12px;color:var(--text);padding:16px;
  cursor:pointer;width:100%;display:block;text-align:center;text-decoration:none}
.hof-btn:hover{background:var(--sheet-3)}



/* ===========================================================================
   A LITTLE MORE CABINET, ON TOP OF WHAT IS ALREADY THERE

   THE PRESS WAS ALREADY ARCADE and none of it is repeated here: .mode-card has
   carried a hard 7px offset shadow, a lift to 9px on hover and a drop to 3px on
   press since long before this block, with a shadow colour per card. That IS
   the cabinet button. Adding a second shadow system on top of it — which the
   first draft of this change did, in base.css, where theme.css promptly
   overrode every line of it — makes the page no more arcade and the stylesheet
   considerably worse.

   SO THIS IS THE LETTERING, which is the half that was still office software.

   THE CALL TO ACTION IS A LABEL ON A MACHINE: mono, upper case, letter-spaced.
   "Play now" set in the body face at 14px reads as a hyperlink; PLAY NOW in
   spaced mono reads as something screen-printed onto plastic. Size and padding
   are untouched, so no card changes shape.

   AND THE DAILY'S BLINKS, once. `steps(1,end)` not a fade: a cabinet's attract
   mode switches a lamp on and off, it does not cross-fade, and an eased opacity
   ramp here would read as a notification badge. One card only — the one the
   page wants pressed first — because four blinking labels is a fruit machine.
   =========================================================================== */
/* THE SMALL TILES GET IT TOO, at 0-2-0. The bare `.mode-go` is outranked
   somewhere in the sheets that load after this one, so every rule here names
   its card — one selector shape, all six buttons, no hunting. */
.mode-card .mode-go{font-family:var(--mono);letter-spacing:.14em;
  text-transform:uppercase}
/* AT 0-3-0, WHICH IS WHAT THE THREE HERO BUTTONS ARE ALREADY STYLED AT further
   up this file. The bare `.mode-go` rule above sets the family and loses it on
   these three; matching the existing selector is cheaper than hunting the sheet
   that outranks it, and it keeps all the hero-button type in one place. */
.mode-hero .mode-card.daily .mode-go,
.mode-hero .mode-card.nfl .mode-go,
.mode-hero .mode-card.gauntlet .mode-go{font-family:var(--mono);
  font-size:12px;letter-spacing:.16em;text-transform:uppercase}
/* NO BLINK. This card's call to action pulsed like a cabinet's attract mode,
   which is a nice idea on a machine nobody is sitting at and a distraction on a
   page somebody is reading. The lettering is what makes it arcade; a label that
   fades in and out just looks like something failing to load. */

/* THE TOP EDGE CATCHES THE LIGHT. One inset hairline, white at 12%, so the
   card reads as moulded rather than printed. It is inset so it cannot disturb
   the offset shadow underneath, and it is on the card only — the small tiles
   share .mode-card, and that is deliberate: they are the same object. */
.mode-card{box-shadow:0 7px 0 var(--m-unl-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.daily{box-shadow:0 7px 0 var(--m-daily-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.gauntlet{box-shadow:0 7px 0 var(--m-gaunt-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.hilo{box-shadow:0 7px 0 var(--m-hilo-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.live{box-shadow:0 7px 0 var(--m-live-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.nfl{box-shadow:0 7px 0 var(--m-nfl-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}
.mode-card.unlimited{box-shadow:0 7px 0 var(--m-unl-sh),
  inset 0 1px 0 rgba(255,255,255,.14)}




/* ===========================================================================
   THE LIVE CARD AT HALF WIDTH

   THE HERO GRID IS "TEXT LEFT, BUTTON RIGHT" and it was written when a hero was
   the full width of the card — one per row, about 1150px. Two to a row it is
   567px, and the Gauntlet Live card is the one with four things in it: a
   countdown, a title, a badge, a blurb and a call to action whose label is
   built from the room ("Join the lobby · 0 waiting"). That button needs ~280px
   of the ~479px between the padding, which left the title 200px — so
   "Gauntlet Live" broke across two lines, the blurb broke across two more, and
   the card grew to nearly 300px tall and dragged NFL Mode's half-empty box up
   to match it.

   SO THIS ONE CARD STACKS. Clock, name, blurb, button — each on its own full
   width row, which is the layout the phone has always used for it and for the
   same reason: there is not enough width for two columns once the button is
   this wide. Nothing wraps that should not, and the card comes down to about
   the height of the pair beside it.

   ONLY THE LIVE CARD. The other three heroes hold a name and a button and
   nothing else, so two columns still fits them at 567px and they keep the
   layout in the screenshot — title left, button right.
   =========================================================================== */
@media (min-width:701px){
  /* BETWEEN 701 AND 1300 THE LIVE CARD STACKS, and the arithmetic says why it
     has to. Side by side it needs 246px of title, 24 of gap and 238 of button
     — 508 inside the padding, so a 564px card. At a 1280 viewport the card is
     567 and it just fits; at 1024 it is 453 and the title column collapses to
     135, which put "Gauntlet Live" back on two lines. No type size rescues
     that: even at 20px the title plus its badge is 218 against 135 available.

     So below 1300 it goes back to one column — countdown, title, button, each
     on its own full-width row — and the four cards take the taller height
     together. Above 1300 it is the side-by-side card that was asked for. */
  .mode-pair .mode-card.live{
    grid-template-columns:minmax(0,1fr) minmax(0,auto);
    grid-template-areas:"name when" "cta cta";
    align-items:center;align-content:center;gap:7px 24px}
  /* THE COUNTDOWN IS ON THE RIGHT IN THIS BAND TOO, on the title's own row.
     The card is too narrow here for the button to sit beside the title as well
     — 214 of title, 24 of gap and 238 of button is 476 into a 397px card at
     1024 — but the CLOCK is only 153, and 214 + 24 + 153 is 391, which fits.
     So the clock keeps its place at the top right and only the button drops to
     a row of its own. Three rows became two, and the card came down from 153px
     to about 126. */
  .mode-pair .mode-card.live .mode-live-when{grid-area:when;justify-self:end}
  .mode-pair .mode-card.live .mode-go{grid-area:cta;justify-self:stretch;
    align-self:start;margin-top:3px;text-align:center;white-space:normal;
    font-size:12px;letter-spacing:.06em;padding:14px 16px}
  /* 30px, THE SAME AS THE OTHER THREE. It was 25 for one commit, to buy the
     28px the row was short of while the title still carried a "New" badge —
     58px of badge and 10 of gap. The badge is gone, the title needs 214 instead
     of 282, and 214 + 24 of gap + 238 of button is 476 into 516. So the reason
     for the odd size out went with the badge, and all four titles match. */
  /* ONE HEIGHT FOR ALL FOUR IN THIS BAND TOO, and it is the Live card that
     sets it: measured with the floor taken off, the two top cards want 119px
     and Live wants 127 — a title row and a button row against the others'
     single row. 127 is that number, so nothing is stretched further than the
     tallest card actually needs. The wide block at the foot of this file sets
     its own, lower, figure for the side-by-side card. */
  .mode-pair .mode-card{min-height:127px}
  /* NOT PINNED TO THE TOP. The three cards beside it centre their contents in
     whatever height the row settles on; this one now does too, so a short
     Live card and a short NFL card sit on the same optical line. */
  .mode-pair .mode-card.nfl,
  .mode-pair .mode-card.daily,
  .mode-pair .mode-card.gauntlet{align-content:center}
}

/* ===========================================================================
   THE WIDE SCREEN GETS THE SIDE-BY-SIDE LIVE CARD
   Everything above lays the Live card out in one column, which is what fits
   from 701px up. From 1300 the card is wide enough for the shape that was
   asked for: title on the left, countdown and button down the right.
   =========================================================================== */
@media (min-width:1200px){
  /* THE LIVE CARD IS THE SAME SHAPE AS THE OTHER THREE NOW: name on the left,
     the things you act on down the right. Its right column holds two — the
     countdown above the button — where theirs holds one, and that is the only
     difference between the four cards in the two rows.

     "name when" / "name cta" — the title spans both rows so it stays centred
     against a right column that is taller than one line. It was a stacked
     card for exactly one commit: that fixed the wrapping but left Live at
     189px against the top row's 96, which is the thing this replaces. */
  .mode-pair .mode-card.live{
    grid-template-columns:minmax(0,1fr) minmax(0,auto);
    grid-template-areas:"name when" "name cta";
    align-items:center;align-content:center;gap:8px 24px}
  .mode-pair .mode-card.live .mode-live-when{grid-area:when;justify-self:end;
    align-self:end}
  /* ONE SIZE STEP DOWN, AND IT IS THE 28px THE ROW WAS SHORT BY.

     Measured: the title needs 282px on one line — 214 of "Gauntlet Live" at
     30px, a 58px badge and the 10px between them. The button needs 238. With
     24px of gap that is 544 into 516, so the title wrapped to two lines and
     broke mid-name, which is what it was doing.

     At 25px the title is 246 and everything sits on one line with room to
     spare. This is the only hero carrying THREE things — a title, a countdown
     and a button — where the other three carry a title and a button, so it is
     also the only one that has to pay for the space. Next to 30px neighbours
     the step is not visible; a title broken across two lines is. */

  /* THE BUTTON HAS TO FIT BESIDE THE TITLE, and the arithmetic is the whole
     rule. The card is 572px, 516 inside its padding. "Gauntlet Live" plus its
     badge needs 238 on one line and the gap is 24, so the button gets 254 —
     and it was taking 321, because this one CTA was left at 14px with .14em of
     letter-spacing while the other three heroes went to 12px/.16em. 26
     characters at that size is 269px of text before its padding.

     At 12px with .06em it is about 234, which leaves the title 258 and one
     line. Tighter tracking than its siblings on purpose: theirs say "PLAY NOW"
     and this one says "JOIN THE LOBBY · 12 WAITING", so the same tracking buys
     three times as much width here.

     white-space STAYS normal. It fits on one line today for every label the
     room produces, and a label nobody has thought of should wrap inside the
     card rather than push the grid open — see the note further up. */
  .mode-pair .mode-card.live .mode-go{grid-area:cta;justify-self:end;
    align-self:start;margin-top:0;white-space:normal;text-align:center;
    font-size:12px;letter-spacing:.06em;padding:14px 16px}

  .mode-pair .mode-card{min-height:117px}
}

/* ===========================================================================
   THE HERO TITLES, AND THE ARITHMETIC THAT DECIDES WHICH SHAPE FITS
   Added 27 Aug 2026, after "GauntletGuesser" was found printed across its own
   PLAY NOW at every width from 1024 up, and "Play today's daily" and "Gauntlet
   Mode" doing the same at 820.

   THE CAUSE IS ONE LINE OF ARITHMETIC AND IT IS WORTH WRITING DOWN. A hero
   card is `minmax(0,1fr) minmax(0,auto)`: the button takes its max-content and
   the title gets the rest. The floor of 0 is deliberate — it stops one long
   label pushing the grid wider than the card — but it also means the title's
   column can be narrower than the title, and a word with no space in it has
   nowhere to wrap, so it paints over the button instead. "Gauntlet Live"
   escapes by wrapping onto two lines. "GauntletGuesser" is one 15-character
   word and could not — which is how this was found.

   THE CARD THAT FOUND IT IS GONE. GauntletGuesser was moved into the Gauntlet
   Mode menu in the same session, so nothing here styles it any more and the
   rules below name only the three heroes that remain. The bug was never its
   own: "Play today's daily" was over its edge by 6px at 820 and "Gauntlet
   Mode" by 29, both with no long word in them at all — a title column of 109px
   is too narrow for any of these names. Deleting the mode's card fixed one
   card. This fixes the shape.
   =========================================================================== */
@media (min-width:701px) and (max-width:1199px){
  /* BELOW 1200 NO HERO IS WIDE ENOUGH FOR TITLE-BESIDE-BUTTON, so none of them
     tries. This is the shape the Live card has had in this band all along; the
     other three now match it rather than each finding their own way to fail.
     At 820 the first row's cards are 380px, which left the title 109 — three
     lines of "Play today's daily" and still 6px over the edge. Full width they
     have 324 and need 250. */
  .mode-hero .mode-card.daily,
  .mode-hero .mode-card.gauntlet,
  .mode-hero .mode-card.nfl{
    grid-template-columns:minmax(0,1fr);
    grid-template-areas:"no" "name" "desc" "cta";
    align-items:center;align-content:center;gap:7px}
  /* AND ONE STEP DOWN IN TYPE, because full width alone is not enough here.
     At 820 the stacked column is 302px, which "Play today's daily" fills at
     30px with nothing to spare. At 24 it wants 250. That completes the ramp
     30 → 24 → 20, the last of which responsive.css has always applied below
     701. Every hero steps together: one card at 24 beside three at 30 is the
     visible mistake the Live card's own note warns about. */
  .mode-hero .mode-name{font-size:24px}
  .mode-hero .mode-card.daily .mode-go,
  .mode-hero .mode-card.gauntlet .mode-go,
  .mode-hero .mode-card.nfl .mode-go{grid-area:cta;justify-self:stretch;
    align-self:start;margin-top:3px;text-align:center;white-space:normal;
    font-size:12px;letter-spacing:.06em;padding:14px 16px}
}


/* ---- the two doors in the top bar --------------------------------------
   "Sign in · Create account". The separator is a real element rather than a
   ::before on the second link, because the whole span is swapped out for the
   user chip once somebody signs in and a pseudo-element on a hidden link is a
   thing that has to be remembered. aria-hidden: it is punctuation, and a
   screen reader announcing "middle dot" between two links is noise. */
.auth-sep{margin:0 8px;color:var(--hair);font-weight:600}
/* THE SECOND DOOR IS THE LOUDER ONE, because the people who need an account
   are exactly the ones who cannot sign in. Not a filled button: this bar is
   navigation, and a solid call to action up here competes with the mode cards
   that are the actual thing to do. */
.nav-cta{font-weight:700;color:var(--accent);
  text-decoration:underline;text-decoration-thickness:2px;
  text-underline-offset:3px;text-decoration-color:var(--accent-soft,var(--accent))}
.nav-cta:hover{text-decoration-color:var(--accent)}
