/* =========================================================
   Debatable shared UI primitives
   Source of truth for colors, typography, and component styles
   used across landing, high-school, debate-ai, learn.
   Mirrors the main app (app/index.html) aesthetic so every page
   reads as the same product.
   ========================================================= */

@import url('/css/wordmark.css');

@import url('https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&family=Geist+Mono:wght@400..700&family=Inter:wght@400..900&family=Source+Serif+4:opsz,wght@8..60,400;8..60,600&display=swap');

/* No decorative italics site-wide. The Crimson Pro/Fraunces italic flourishes
   (red emphasis words, italic nav, slanted pull-quotes) read as
   inconsistent against the upright brand face. Emphasis is weight +
   color, not slant. Neutralizes bare <em>/<i> defaults; explicit
   per-page italic rules were converted to upright in the same pass.
   (2026-06-15) */
em, i { font-style: normal; }

/* ── Type system — the Arena system, sitewide (the founder, 2026-08-19:
   "universal font changes should be universal"). Display voice is
   INTER (headings, via the h1-h6 force below) — back on 2026-10-12,
   "bring back the TED talks font": ted.com computes to Inter on every
   surface, and Inter was our heading pick from 2026-08-19 until the
   DM Sans ("Google Sans look") detour of 2026-08-22, now retired and
   no longer requested. The 08-19 brief stands: "professional easy to
   read not confusing or unique". 2026-08-20: Inter now carries BODY
   and interface too, and the figure face is GEIST MONO. That pairing
   is not a taste call, it is a match: Polymarket computes to `inter`
   on body and headings alike and sets its prices, percentages and
   volume in Geist Mono, and the founder asked for that look by name. We were
   already on their display face and did not know it, so the real
   difference was body (Archivo) and the numbers (the system mono
   stack). Archivo stays loaded for legacy page rules and pages that pin
   it directly. Source Serif 4 is still the judge's written reasoning
   (ballots, RFDs, editorial quotes) via --font-judge. Inter loads
   400-900, so every
   pinned display weight renders as drawn. Per-page
   `var(--font-display)` / `var(--font-body)` uses stay valid. */
:root{
  --font-display:'Inter','Archivo',system-ui,-apple-system,sans-serif;
  --font-body:'Inter','Archivo',system-ui,-apple-system,sans-serif;
  --font-judge:'Source Serif 4',Georgia,'Times New Roman',serif;
  --font-mono:'Geist Mono',ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;
  --font-legacy-serif:'Archivo',system-ui,-apple-system,sans-serif;
}

/* ── Tokens — three canonical themes: GREY (dark, default) /
   CRIMSON (red on black) / LIGHT (warm off-white).
   Source of truth lives here; landing.html mirrors the same palette so
   every page reads as one product. Selectors support both conventions:
   landing uses `[data-theme="X"]` on <html>, the older /app + /high-school
   code uses `body.X-theme`. Keeping both lets us migrate page-by-page
   without breaking either side.
   2026-05-10: dropped the bare `body` selector from this default block.
   It was unconditionally setting GREY tokens on every <body>, which
   shadowed `[data-theme="light"]` / `[data-theme="crimson"]` set on
   <html> (body's own scope wins inside body's subtree). Result: light
   theme was rendering dark backdrops with light-theme text colors —
   nearly-black `.tier-name` on a `#111` bg on /pricing, etc. The
   legacy `body.crimson-theme` / `body.light-theme` selectors below
   still work; they each set their OWN tokens explicitly. */
:root,
[data-theme="grey"]{
  --bg:#111;
  --bg-card:rgba(255,255,255,.03);
  --bg-elev:rgba(20,20,24,.55);
  /* Opaque elevation for dropdowns/sheets that float over page content.
     --bg-elev is translucent by design (topbar frosted glass), but a
     descendant of the blurred topbar can't backdrop-blur the page behind
     it (ancestor backdrop root), so menus using --bg-elev let text bleed
     through. Menus use this solid token instead. (2026-07-19) */
  --bg-elev-solid:#17171b;
  --border:rgba(255,255,255,.08);
  --border-strong:rgba(255,255,255,.18);
  --text:#fff;
  --text-dim:rgba(255,255,255,.68);
  --text-ghost:rgba(255,255,255,.68);
  --accent:#ef4444;
  --accent-text:#f87171;
  --accent-solid:#b91c1c;
  --danger-text:#fca5a5;
  --success-text:#4ade80;
  --accent-hover:#f87171;
  --accent-soft:rgba(239,68,68,.08);
  --accent-border:rgba(239,68,68,.25);
  --accent-glow:rgba(200,30,30,.35);
  --accent-glow2:rgba(80,20,20,.25);
  /* Radius scale bumped up to feel less boxy. Old values felt sharp-cornered
     on cards / form rows; new values lean toward "soft / circular" without
     going full pill. Pages that want a rounder vibe should use --radius-lg
     or --radius-xl. */
  --radius-sm:10px;
  --radius:14px;
  --radius-lg:22px;
  --radius-xl:30px;
  --radius-pill:999px;
  --shadow-sm:0 2px 10px rgba(0,0,0,.2);
  --shadow:0 6px 18px rgba(0,0,0,.35);
  --shadow-lg:0 20px 60px rgba(0,0,0,.45);
  --ease:cubic-bezier(.2,.65,.3,.9);
}
[data-theme="light"],
body.light-theme{
  /* Warm off-white instead of pure white so it doesn't glare on retina
     displays; deeper red (#dc2626) reads as a confident link/CTA on
     light backgrounds rather than looking radioactive. Mirrors the
     landing-page light theme exactly. */
  --bg:#fafaf7;
  --bg-card:rgba(0,0,0,.03);
  --bg-elev:rgba(255,255,255,.8);
  --bg-elev-solid:#ffffff;
  --border:rgba(0,0,0,.08);
  --border-strong:rgba(0,0,0,.18);
  --text:#1a1a1f;
  --text-dim:rgba(0,0,0,.68);
  --text-ghost:rgba(0,0,0,.64);
  --accent:#b91c1c;
  --accent-text:#b91c1c;
  --accent-solid:#b91c1c;
  --danger-text:#b91c1c;
  --success-text:#166534;
  --accent-hover:#b91c1c;
  --accent-soft:rgba(220,38,38,.08);
  --accent-border:rgba(220,38,38,.25);
  --accent-glow:rgba(220,38,38,.18);
  --accent-glow2:rgba(220,38,38,.10);
}
[data-theme="crimson"],
body.crimson-theme{
  --bg:#000;
  --bg-card:rgba(255,40,40,.03);
  --bg-elev:rgba(30,10,10,.55);
  --bg-elev-solid:#1a0a0a;
  --border:rgba(239,68,68,.12);
  --border-strong:rgba(239,68,68,.28);
  --text:#fff;
  --text-dim:rgba(255,255,255,.68);
  --text-ghost:rgba(255,255,255,.68);
  --accent:#ef4444;
  --accent-text:#f87171;
  --accent-solid:#b91c1c;
  --danger-text:#fca5a5;
  --success-text:#4ade80;
  --accent-hover:#f87171;
  --accent-soft:rgba(239,68,68,.08);
  --accent-border:rgba(239,68,68,.3);
  --accent-glow:rgba(239,68,68,.4);
  --accent-glow2:rgba(239,68,68,.2);
}

/* ── color_scheme_v1 (2026-10-23) ──────────────────────────────────
   Two of the four arms are token overrides on a base theme, keyed on
   BOTH attributes so the override only ever paints on the base it was
   assigned with. The landing <head> script and topbar.js set
   data-scheme; a saved theme toggle changes data-theme and the override
   falls away on its own. Retire an arm by zeroing its weight in
   landing.html; this block is harmless with no data-scheme set. */
[data-theme="light"][data-scheme="paper"]{
  --bg:#f4eee3;
  --bg-card:rgba(60,40,20,.045);
  --bg-elev:rgba(252,248,241,.86);
  --bg-elev-solid:#fbf7f0;
  --border:rgba(60,40,20,.11);
  --border-strong:rgba(60,40,20,.22);
  --text:#1c1612;
  --text-dim:rgba(28,22,18,.7);
  --text-ghost:rgba(28,22,18,.64);
  --accent:#a8201a;
  --accent-text:#a8201a;
  --accent-solid:#a8201a;
  --accent-hover:#8f1a15;
  --accent-soft:rgba(168,32,26,.09);
  --accent-border:rgba(168,32,26,.26);
  --accent-glow:rgba(168,32,26,.16);
  --accent-glow2:rgba(168,32,26,.08);
}
[data-theme="light"][data-scheme="paper"] body{background:#f4eee3}
[data-theme="crimson"][data-scheme="ink"]{
  --bg:#0e0d0b;
  --bg-card:rgba(255,245,230,.035);
  --bg-elev:rgba(24,22,19,.6);
  --bg-elev-solid:#1a1815;
  --border:rgba(255,245,230,.1);
  --border-strong:rgba(255,245,230,.22);
  --text:#f4ede2;
  --text-dim:rgba(244,237,226,.7);
  --text-ghost:rgba(244,237,226,.66);
  --accent:#f0433a;
  --accent-text:#f87066;
  --accent-solid:#d7261d;
  --accent-hover:#f87066;
  --accent-soft:rgba(240,67,58,.1);
  --accent-border:rgba(240,67,58,.28);
  --accent-glow:rgba(215,38,29,.35);
  --accent-glow2:rgba(90,20,16,.25);
}
[data-theme="crimson"][data-scheme="ink"] body{background:#0e0d0b}

/* ── Base ─────────────────────────────────────────────────── */
*{box-sizing:border-box}
/* html background tracks the theme so the cross-page fade
   (page-transition.js drops body to opacity:0) never flashes white
   between a dark and a light page. (2026-06-15) */
html{scroll-behavior:smooth;background:var(--bg);transition:background .4s}
body{
  margin:0;
  font-family:var(--font-body) !important;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  background:var(--bg);color:var(--text);
  font-size:16px;line-height:1.55;
  transition:background .4s,color .4s;
}
h1,h2,h3,h4,h5,h6{
  font-family:var(--font-display) !important;
}
/* 2026-08-19, same day: the Expanded display grammar (h1 at 125%/800,
   h2 112%, wordmark 118%) shipped and was REVERTED within the hour —
   the founder, off a /spar screenshot: "too spread out and robotic". The
   variable Archivo load stays (the width axis costs nothing unused).
   Don't re-add font-stretch display rules without a new call. */
a{color:inherit}
/* Form controls do NOT inherit the page font, so a bare <button> or
   <input> renders in the browser's own sans and punches a hole in the
   all-Crimson surface. Family only: per-component size/weight still apply. */
button,input,select,textarea{font-family:inherit}
/* Headlines never strand a single word on their last line; body text
   avoids awkward rag. Both are no-ops on browsers that lack text-wrap. */
h1,h2,h3{text-wrap:balance}
p{text-wrap:pretty}
/* Live values (timers, vote %, scores, odds) keep digits on a fixed
   grid so a 39%→41% flip doesn't shift the layout. Substring class
   matches over-apply harmlessly: tabular-nums only affects digits. */
time,table,[class*="timer"],[class*="score"],[class*="count"],[class*="stat"],[class*="odds"],[class*="pct"],[class*="clock"]{font-variant-numeric:tabular-nums lining-nums}
::selection{background:var(--accent-solid,#b91c1c);color:#fff}

/* ── Beta strip (fixed, top of every page) ───────────────── */
/* HEIGHT IS PINNED AND THE TEXT NEVER WRAPS, and both halves of that
   are load-bearing rather than tidy. body.has-beta-strip reserves
   exactly 32px below, and this strip had no height and no nowrap, so
   the moment the copy was a few characters too long for the viewport it
   wrapped to two lines, stood ~45px tall, and overflowed its own
   reservation. What a visitor saw was the SECOND line, starting
   mid-word: "ebatable Open · Free to enter..." with the prize and the
   date, the two facts the strip exists to carry, scrolled off above the
   top of the bar. Measured on production 2026-08-22.

   So: one line, always, clipped at the END. (Since 2026-08-26 the
   Open strip runs as a ticker instead and scrolls rather than
   truncating; the ellipsis path below is what it falls back to under
   prefers-reduced-motion, and what any other .ui-beta-strip gets.) The anchor is an
   inline-block capped at the strip width, which truncates from the tail
   with an ellipsis instead of centring an over-wide line and cutting
   both ends off it. The hook (prize, then date) is authored first
   precisely so it is the part that survives. */
.ui-beta-strip{
  position:fixed;top:0;left:0;right:0;z-index:10000;
  height:32px;
  display:flex;align-items:center;justify-content:center;
  padding:0 36px 0 14px;text-align:center;
  overflow:hidden;white-space:nowrap;
  font-size:max(10.5px,.72rem);color:#fff;font-weight:600;letter-spacing:.02em;
  /* Fully opaque — earlier alpha of `dd` let hero content bleed through when it scrolled under */
  background:#b91c1c;
  border-bottom:1px solid #00000040;
  font-family:var(--font-body);line-height:1.4;
  box-shadow:0 2px 8px rgba(0,0,0,.35);
}
.ui-beta-strip a{
  color:#fff;text-decoration:underline;font-weight:800;
  display:inline-block;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.ui-beta-strip-dismiss{
  position:absolute;right:8px;top:50%;transform:translateY(-50%);
  background:transparent;border:none;color:#fff;opacity:.7;
  cursor:pointer;font-size:1rem;line-height:1;padding:4px 6px;
}
.ui-beta-strip-dismiss:hover{opacity:1}
/* TRAP (measured 2026-08-31): this class rule OUT-SPECIFIES any page's
   own plain `body{padding-top:...}` topbar compensation, so a page that
   correctly reserved the fixed bar's 52px reads as broken the moment
   the strip mounts (chat and livedebates both shipped that way). A page
   compensating via body padding must state BOTH arms:
     body{padding-top:52px}
     body.has-beta-strip{padding-top:84px}
   And note this rule reserves ONLY the strip; nothing global reserves
   the 52px fixed .ui-topbar below it. Every page owns that offset. */
body.has-beta-strip{padding-top:32px}

/* ── The Open ticker: a Times Square zipper, not a banner ──────
   Aidan, 2026-08-26: "have this actually be red / white with green $
   symbols in a moving line like those screens on news station
   buildings in times square ... i want ppl to see the animated nature
   of that pop up at the top so ppl sign up."

   Scoped to .ui-beta-strip--ticker so the plain strip above is
   untouched and reverting is one class. Everything the base rule
   guarantees still holds and is load-bearing, not tidy: the strip is
   32px, one line, and never wraps, because body.has-beta-strip
   reserves exactly 32px and .ui-topbar / .ui-nav / .ui-topbar-sheet
   all offset off that number. A second line clips the wordmark
   underneath, which is the bug this file already carries a comment
   about. A marquee cannot wrap by construction, so the ticker
   actually makes that guarantee stronger than the ellipsis did, and
   it is why the mobile tail-hide is gone: the full message now fits
   every width because it scrolls rather than truncates.

   Direction is right-to-left, the way a real zipper runs: content
   enters at the right edge and travels left, so words arrive in
   reading order. Moving the track the other way would deliver each
   sentence backwards.

   Duration is set in JS from the measured run width for a constant
   px/second, so the speed does not change with viewport or copy
   length. The value below is the fallback if that measurement never
   lands. */
.ui-beta-strip--ticker{
  justify-content:flex-start;
  padding:0 40px 0 0;
  text-align:left;
  /* Faint horizontal scanlines, the LED-board texture. Sits under the
     text and over the red, at an alpha low enough to read as grain
     rather than as stripes. */
  background:
    repeating-linear-gradient(180deg,rgba(0,0,0,.16) 0 1px,transparent 1px 3px),
    #b91c1c;
}
.ui-beta-strip--ticker .ui-strip-link{
  display:block;width:100%;max-width:none;height:100%;
  overflow:hidden;text-overflow:clip;text-decoration:none;
  /* The message fades out before it reaches the dismiss control
     instead of sliding under it. */
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 46px),transparent calc(100% - 12px));
  mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 46px),transparent calc(100% - 12px));
}
.ui-beta-strip--ticker .ui-strip-link:hover{text-decoration:none}
.ui-beta-strip--ticker .ui-strip-track{
  display:flex;align-items:center;height:100%;width:max-content;
  animation:ui-strip-zip 44s linear infinite;
  will-change:transform;
}
/* Two identical runs, so translating the track by exactly half its
   width lands the second run where the first started and the loop has
   no seam. Any other offset shows a gap once per cycle. */
.ui-beta-strip--ticker .ui-strip-run{
  display:flex;align-items:center;flex:none;white-space:nowrap;
  font-family:var(--font-mono);
  font-size:max(10px,.7rem);font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:#fff;
}
.ui-beta-strip--ticker .ui-strip-seg{padding:0 14px;flex:none}
/* The green. Checked against the #b91c1c bar rather than picked by
   eye: #86efac is 4.6:1, which clears AA for text this small, and
   #4ade80 (the obvious "money green") is 3.7:1 and does not. */
.ui-beta-strip--ticker .ui-strip-money{
  color:#86efac;
  text-shadow:0 0 7px rgba(134,239,172,.5);
}
.ui-beta-strip--ticker .ui-strip-sep{
  flex:none;color:#86efac;opacity:.85;
  text-shadow:0 0 7px rgba(134,239,172,.45);
}
@keyframes ui-strip-zip{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* Readable and clickable while the pointer is on it, and not painting
   in a tab nobody is looking at. */
.ui-beta-strip--ticker:hover .ui-strip-track,
.ui-beta-strip--ticker.ui-strip-paused .ui-strip-track{animation-play-state:paused}
/* A line of text that never stops moving is a genuine problem for some
   people, so this degrades to the static line it replaced: run one
   starts at the left edge and the hook is authored first. */
@media (prefers-reduced-motion:reduce){
  .ui-beta-strip--ticker .ui-strip-track{animation:none;transform:none}
}

/* ── Neural constellation canvas (fixed bg) ──────────────── */
.ui-neural-canvas{
  position:fixed;top:0;left:0;width:100vw;height:100vh;
  /* z-index:0 so the constellation sits BEHIND content (which
     defaults to z-index:auto/0 but later in DOM, or explicitly
     z-index:1 in some pages). Was at 1, putting the canvas on
     top of cards/text on the Manage page and elsewhere. */
  z-index:0;pointer-events:none;opacity:.45;
  transition:opacity 1s ease;
}
body.crimson-theme .ui-neural-canvas{opacity:.8}
body.light-theme .ui-neural-canvas{opacity:.35}

/* ── Top bar ─────────────────────────────────────────────── */
.ui-topbar{
  position:fixed;top:32px;left:0;right:0;z-index:1000;
  padding:0 32px;height:52px;
  display:flex;align-items:center;justify-content:space-between;
  background:color-mix(in srgb,var(--bg) 92%,transparent);
  border-bottom:1px solid var(--border);
  /* 2026-05-27 perf: backdrop-filter dropped 16px -> 10px and the
     bg color-mix bumped 88% -> 92% so the slight visual loss from
     the smaller blur is compensated by a more opaque background.
     Chrome's gaussian-blur cost scales roughly with radius squared
     and the topbar's backdrop is re-rasterized every scroll frame.
     Visually indistinguishable on retina; meaningfully cheaper. */
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  /* Transform is not transitioned on purpose. The banner offset
     uses transform so it snaps to position on first paint instead
     of sliding in from y=0. The other listed properties retain
     their existing transitions. */
  transition:top .2s ease,background .4s,border-color .4s;
}
body:not(.has-beta-strip) .ui-topbar{top:0}
/* The bar is fixed, so a page that mounts it without its own top
   padding renders its first screen underneath it. Pages written before
   the topbar existed carry this class on the mount and get the 52px
   back in normal flow; the strip's own 32px is already handled by
   body.has-beta-strip above, and pages that always reserved their own
   clearance use the bare #daTopbar and are untouched. */
#daTopbar.ui-topbar-mount{height:52px}
/* Push the fixed topbar down by the founding-cohort banner height
   so the banner is actually visible (cohort-banner.js inserts an
   <aside> at the top of <body> in normal flow; the topbar is fixed
   at top:0 and was covering it). Using transform instead of `top`
   because something on this page suppresses inline/!important
   `top` overrides on .ui-topbar (verified in-browser: `top:47px
   !important` computed to 0px; `transform: translateY(47px)` moved
   the bar correctly). cohort-banner.js publishes --cohort-banner-h
   on :root with the banner's offsetHeight; collapses to 0px on
   dismiss, so the topbar slides back up. */
.ui-topbar{transform:translateY(var(--cohort-banner-h,0px))}
.ui-topbar-left{display:flex;align-items:center;gap:0;flex-shrink:0}
/* 2026-05-18: .ui-topbar-beta chip CSS removed alongside the element. */
.ui-topbar-logo{
  font-size:1.4rem;font-weight:900;letter-spacing:-.02em;
  color:var(--text);cursor:pointer;white-space:nowrap;line-height:1;
  text-decoration:none;display:inline-block;
}
.ui-topbar-logo span{color:var(--accent)}
.ui-topbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}
/* 2026-09-03, the founder, off a screenshot of the bar: "fix spacing at
   top too". More air between the controls where the bar has the width. */
@media(min-width:1200px){.ui-topbar-right{gap:20px}}
.ui-topbar-link{
  /* 2026-07-22: px, not rem, and a step up. Pages set their own root
     size (landing runs a 20px root, most others 16px), so the shared nav
     was rendering ~14.4px on one page and ~11.5px on the next off the
     same .72rem. Chrome should be one size everywhere; 15px is legible
     without crowding the 12-item rail. */
  font-size:15px;font-weight:500;line-height:18px;
  /* Ink follows --text, which every theme/lighting block declares
     alongside the --bg that paints this bar — the two can't split.
     The old approach keyed label color on data-lighting and bar bg
     on --bg/data-theme; any out-of-sync attribute combo rendered
     dark-on-dark (the invisible-tabs bug on dark landing). */
  color:color-mix(in srgb, var(--text, #fff) 86%, transparent);letter-spacing:.04em;
  text-decoration:none;background:transparent;border:none;
  padding:0;cursor:pointer;transition:color .2s;
  font-family:inherit;white-space:nowrap;
}
.ui-topbar-link:hover{color:var(--text)}
.ui-topbar-link.is-active{color:var(--accent);font-weight:700}
.ui-topbar-link.accent{color:var(--accent)}
.ui-topbar-link.accent:hover{color:var(--accent-hover)}
/* Some app surfaces intentionally combine data-theme="light" with
   data-lighting="dark": content tokens stay light-mode, while the
   fixed topbar is still a dark glass strip. Keep the bar ink tied to
   the strip, not the page content token. */
[data-lighting="dark"] .ui-topbar .ui-topbar-logo,
[data-lighting="dark"] .ui-topbar .ui-topbar-link{
  color:rgba(255,255,255,.86) !important;
}
[data-lighting="dark"] .ui-topbar .ui-topbar-link:hover{color:#fff !important}
/* Same dark-strip guarantee for the two icon/pill controls that carry
   their ink from theme tokens: the ghost Sign in button and the bell.
   On surfaces that pair light content tokens with a dark bar (e.g.
   /practice), both rendered dark-on-dark and vanished. */
[data-lighting="dark"] .ui-topbar .ui-btn-ghost{color:rgba(255,255,255,.78) !important;border-color:rgba(255,255,255,.24) !important}
[data-lighting="dark"] .ui-topbar .ui-btn-ghost:hover{color:#fff !important;border-color:rgba(255,255,255,.5) !important}
[data-lighting="dark"] .ui-topbar .ui-bell{color:rgba(255,255,255,.72) !important;border-color:rgba(255,255,255,.2) !important}
[data-lighting="dark"] .ui-topbar .ui-bell:hover{color:#fff !important}
[data-lighting="dark"] .ui-topbar .ui-bell.has-unread{color:var(--accent,#ef4444) !important;border-color:var(--accent,#ef4444) !important}
/* Light side of the same guarantee: the bell's var(--text-dim,#9aa)
   fallback resolves to #9aa on pages whose light tokens don't define
   it, which is ~2:1 on cream. */
[data-lighting="light"] .ui-topbar .ui-bell:not(.has-unread){color:rgba(0,0,0,.64) !important;border-color:rgba(0,0,0,.16) !important}
[data-lighting="light"] .ui-topbar .ui-bell:not(.has-unread):hover{color:rgba(0,0,0,.9) !important}
.ui-topbar-pill{
  font-size:.7rem;font-weight:500;padding:4px 12px;border-radius:999px;
  border:1px solid var(--border-strong);background:var(--bg-card);
  color:color-mix(in srgb, var(--text, #fff) 86%, transparent);
  cursor:pointer;letter-spacing:.04em;
  text-decoration:none;font-family:inherit;transition:.2s;
}
.ui-topbar-pill:hover{color:var(--text);border-color:var(--text)}
@media(max-width:640px){
  /* Mobile density: 14px root so rem-based sizing scales ~87.5%, fitting more per screen */
  html{font-size:14px}
  .ui-topbar{padding:0 12px;height:46px;top:28px}
  .ui-topbar-logo{font-size:1.15rem}
  .ui-topbar-right{gap:10px}
  .ui-topbar-link{font-size:12.5px}
  /* Keep the theme picker visible on phones so light-mode users can flip
     it on the device they actually browse from (was hidden until the
     three-theme system shipped). Trim the dots a hair so they fit
     beside the CTA without crowding the logo. */
  .ui-topbar .theme-dots{padding:0 2px;gap:4px}
  .ui-topbar .theme-dot{width:12px;height:12px;border-width:1px}
  /* SFX toggle shrinks alongside the theme dots on tablet so the
     topbar doesn't crowd the CTA. */
  .ui-topbar .sfx-toggle{width:24px;height:24px;padding:0}
  .ui-topbar .sfx-toggle svg{width:12px;height:12px}
}

/* Compact rail for tablets, split-screen windows, and narrow laptops.
   The full desktop link set is wider than the viewport below ~1280px,
   which used to push the logo off the left and clip Voice AI/Waitlist
   on the right. Keep the two orientation tabs plus the primary CTA in
   view; the hamburger sheet carries every other primary and More link. */
@media(max-width:1280px){
  .ui-topbar{padding-left:18px;padding-right:18px}
  .ui-topbar-right{gap:9px}
  .ui-topbar-right > .ui-topbar-link{display:none !important}
  .ui-topbar-right > .ui-topbar-link--compact-keep,
  .ui-topbar-right > .ui-topbar-link--mobile-keep{display:inline-flex !important}
  .ui-topbar-more{display:none}
  .ui-topbar-burger{display:inline-flex}
}
@media(max-width:720px){
  /* Phone-sized rails keep only the single primary Waitlist pill.
     LIVE and How it works remain the first two links in the menu. */
  .ui-topbar-right > .ui-topbar-link--compact-keep{display:none !important}
}

/* SFX mute toggle. Lives in the topbar between page links and the
   theme dots. Inline SVG speaker — strike-through line shown only
   when aria-pressed=true (muted state). Sized to match the cluster
   of theme dots beside it without dominating. Color is currentColor
   so the cascade decides (text-dim by default, text on hover, etc.).
   Defined here in ui.css instead of per-page because topbar.js
   renders to every page that uses the shared topbar; keeps the
   visual identical across surfaces. */
.ui-topbar .sfx-toggle{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;padding:0;border-radius:999px;
  background:transparent;border:1px solid var(--border-strong, rgba(255,255,255,.18));
  color:var(--text-dim, rgba(255,255,255,.62));
  cursor:pointer;font-family:inherit;
  /* 2026-05-26: secondary controls (SFX mute + theme toggle, see
     below) default to 0.55 opacity and reveal to 1.0 on individual
     hover OR when any part of the topbar is hovered. Per the founder's
     design brief — "auxiliary, not central" + "hide until hover."
     Keyboard focus also restores opacity so the control isn't
     hidden from accessibility tooling. */
  opacity:.55;
  transition:color .15s, background .15s, border-color .15s, opacity .2s;
  margin-right:6px;
}
.ui-topbar:hover .sfx-toggle,
.ui-topbar .sfx-toggle:hover,
.ui-topbar .sfx-toggle:focus-visible,
.ui-topbar .sfx-toggle[aria-pressed="true"]{opacity:1}
.ui-topbar .sfx-toggle:hover{
  color:var(--text, #fff);
  border-color:var(--text, #fff);
  background:rgba(255,255,255,.04);
}
[data-theme="light"] .ui-topbar .sfx-toggle{
  border-color:rgba(0,0,0,.18);
  color:rgba(0,0,0,.64);
}
[data-theme="light"] .ui-topbar .sfx-toggle:hover{
  color:#1a1a1f;border-color:#1a1a1f;background:rgba(0,0,0,.03);
}
.ui-topbar .sfx-toggle svg{width:14px;height:14px;display:block}
/* Strike line hidden in the un-muted (sound-on) state. */
.ui-topbar .sfx-toggle .sfx-strike{opacity:0;transition:opacity .15s}
/* When pressed (muted), show the strike line and dim the wave arcs
   so the icon clearly reads as "sound off." */
.ui-topbar .sfx-toggle[aria-pressed="true"]{
  color:var(--accent, #ef4444);
  border-color:var(--accent, #ef4444);
}
.ui-topbar .sfx-toggle[aria-pressed="true"] .sfx-strike{opacity:1}
.ui-topbar .sfx-toggle[aria-pressed="true"] .sfx-wave{opacity:.25}

/* Theme toggle — sun in dark themes, moon in light. Matches the
   .sfx-toggle shape (circle, 28px, 1px border, currentColor SVG)
   so the two icons read as a paired cluster in the topbar.
   The sun/moon swap is purely a CSS visibility flip keyed off
   the [data-theme] attribute on <html>; topbar.js doesn't have
   to re-render the SVG on click. */
.ui-topbar .theme-toggle{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;padding:0;border-radius:999px;
  background:transparent;border:1px solid var(--border-strong, rgba(255,255,255,.18));
  color:var(--text-dim, rgba(255,255,255,.62));
  cursor:pointer;font-family:inherit;
  /* 2026-10-24 (the founder: "make these blend in cleaner"): the
     dim-until-hover opacity made this one control fade while the bell
     and the gear beside it sat at full ink. One family now: same 32px
     circle, same border, same dim colour, full opacity, hover to ink. */
  opacity:1;
  transition:color .15s, background .15s, border-color .15s;
  position:relative;
}
.ui-topbar .theme-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.ui-topbar .theme-toggle:hover{
  color:var(--text, #fff);
  border-color:var(--text, #fff);
  background:rgba(255,255,255,.04);
}
/* 2026-10-23, the founder: "fix the coloring here to be black". In the
   light theme the moon reads at full ink like the people icon beside it,
   not as a dimmed hover-reveal. */
[data-theme="light"] .ui-topbar .theme-toggle{
  border-color:rgba(0,0,0,.18);
  color:#1a1a1f;opacity:1;
}
[data-theme="light"] .ui-topbar .theme-toggle:hover{
  color:#1a1a1f;border-color:#1a1a1f;background:rgba(0,0,0,.03);
}
.ui-topbar .theme-toggle svg{width:15px;height:15px;display:block;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);transition:opacity .15s}
/* Default (dark family): show sun, hide moon. */
.ui-topbar .theme-toggle .ti-sun{opacity:1}
.ui-topbar .theme-toggle .ti-moon{opacity:0}
/* Light theme: show moon, hide sun. */
[data-theme="light"] .ui-topbar .theme-toggle .ti-sun{opacity:0}
[data-theme="light"] .ui-topbar .theme-toggle .ti-moon{opacity:1}
@media(max-width:560px){
  .ui-topbar .theme-toggle{width:24px;height:24px}
  .ui-topbar .theme-toggle svg{width:12px;height:12px}
}
@media(max-width:560px){
  /* Secondary category links (College / High School / Adults) drop off
     the topbar below 560px. Phone users land on content-first; the same
     routes are reachable from the footer and body sections. Keeps logo
     + primary Debatable CTA thumb-reachable without overflow.
     !important is load-bearing: the "Live" link gets an inline
     display:inline-flex from topbar.js (so its red dot sits inline),
     which would otherwise beat this rule and leave Live leaking onto
     the bar — pushing the Voice AI CTA off the right edge. */
  .ui-topbar-right .ui-topbar-link{display:none !important}
  /* Keep one small discovery tab visible on phones: The Floor is the
     newest surface and otherwise hides behind the hamburger. */
  .ui-topbar-right .ui-topbar-link--mobile-keep{display:inline-flex !important}
  /* The Spar-live toggle on phones: hidden-while-off since 2026-08-24, a
     compact ring since 2026-10-23 (the founder: "bring back the available
     button"). notifications.js styles the compact off state; this file
     no longer hides it. */
  /* Tighten the icon cluster so the bell + lang flag + CTA never clip
     against the right edge once the links are gone. */
  .ui-topbar-right{gap:7px}
  /* Trim the CTA's inline 8px/18px padding (set in topbar.js) so the
     "Voice AI" pill clears the right edge on ~360px phones instead of
     getting sliced to "VOICE". !important beats the inline style. */
  .ui-topbar-right .ui-btn-primary{padding:8px 13px !important;letter-spacing:.02em}

  /* 2026-07-23 (the founder: "clean up top its too full"). Signed in, the bar
     was carrying wordmark + burger + Waitlist + bell + avatar + first
     name + Sign out, and the wordmark ended up touching the burger. Both
     of the account extras are already reachable one tap away: the name
     pill goes to /profile, which the avatar alone still does, and the
     sheet behind the burger already has its own Sign out row. So on
     phones the account slot collapses to just the avatar.
     !important throughout: topbar.js sets these inline. */
  .ui-topbar-right .ui-topbar-settings{display:none !important}
  /* 2026-07-23: the name hides unconditionally now. It used to survive
     for users with no photoURL, because without one the pill had nothing
     in it; DBAvatar.identity() guarantees a face, so that case is gone. */
  .ui-topbar-right .ui-topbar-username{display:none !important}
  /* With the name gone the pill is a lone avatar, so drop the text-side
     padding and the flex gap or it reads as an off-centre dot in a
     stretched capsule. 24px avatar + 3px ring = a 30px tap target. */
  .ui-topbar-right .ui-topbar-userpill:has(.ui-topbar-useravatar){
    padding:3px !important;gap:0 !important;
  }
  .ui-topbar-right .ui-topbar-useravatar{width:24px !important;height:24px !important}
  /* Guarantee daylight between the wordmark and the burger even when the
     right cluster is at its widest. */
  .ui-topbar-left{padding-right:10px}
}
@media(max-width:359px){
  /* Smallest phones (iPhone SE 1/2, older Androids): even with the
     trimmed cluster there isn't room for the sound + theme toggles
     alongside the bell, language flag, and the primary CTA. Drop the
     two utility toggles here only — bell (unread DMs), the language
     flag (≈80% of traffic is India), and the Voice AI CTA are the
     load-bearing controls. Both toggles stay on 360px+ phones. */
  .ui-topbar .sfx-toggle,
  .ui-topbar .theme-toggle,
  .ui-topbar-right .ui-topbar-link--mobile-keep{display:none !important}
}
@media(max-width:380px){
  /* Tightest phones (iPhone SE, small Android): trim padding + hide the
     trademark sup so the logo doesn't wrap into the CTA. */
  .ui-topbar{padding:0 10px}
  .ui-topbar-logo sup{display:none}
}

/* 2026-06-16: bigger thumb targets for the topbar icon cluster on phones.
   The icons stay visually compact (so the cluster still fits a ~360px bar),
   but an invisible ::after extends each one's TAPPABLE area to ~full bar
   height plus a few px sideways. The horizontal growth (6px total = 3px
   each side) stays inside the inter-icon gap so neighbors don't overlap.
   The big win is vertical: the bar is only 46px tall and the icons were
   14-34px, leaving dead zones above/below that ate taps. burger/bell/
   theme-toggle all use inline SVGs (no pseudo of their own), so ::after
   is free. Fixes the "hard to press the right buttons" complaint. */
@media(max-width:640px){
  .ui-topbar .ui-topbar-burger{position:relative}
  .ui-topbar .theme-toggle::after,
  .ui-topbar .ui-bell::after,
  .ui-topbar .ui-topbar-burger::after{
    content:'';position:absolute;top:50%;left:50%;
    transform:translate(-50%,-50%);
    width:calc(100% + 6px);height:44px;
  }
}

/* ── Nav tabs (pill row, uppercase) ──────────────────────── */
.ui-nav{
  display:flex;gap:16px;margin:0 auto 48px;padding:4px 32px;
  flex-wrap:nowrap;justify-content:center;align-items:center;
  max-width:100%;width:100%;
  position:sticky;top:calc(32px + 52px);z-index:999;
  overflow-x:auto;overflow-y:visible;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
}
body:not(.has-beta-strip) .ui-nav{top:52px}
.ui-nav::-webkit-scrollbar{display:none}
.ui-nav-btn{
  background:var(--bg-elev);border:1px solid var(--border);
  color:var(--text-dim);
  padding:13px 26px;border-radius:var(--radius-pill);
  font-size:.82rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  cursor:pointer;transition:all .2s var(--ease);
  font-family:inherit;white-space:nowrap;text-decoration:none;flex-shrink:0;
  box-shadow:var(--shadow-sm);
}
.ui-nav-btn:hover{
  color:var(--text);background:rgba(40,40,48,.75);
  border-color:var(--border-strong);transform:translateY(-1px);
  box-shadow:var(--shadow);
}
.ui-nav-btn.active{
  color:#fff;background:var(--accent-solid,#b91c1c);border-color:var(--accent-solid,#b91c1c);
  box-shadow:0 6px 24px var(--accent-glow);
}
@media(max-width:640px){
  .ui-nav{padding:12px 14px 10px;gap:8px;justify-content:flex-start}
  .ui-nav-btn{padding:9px 18px;font-size:.72rem}
}

/* ── Page shell / sections ───────────────────────────────── */
.ui-shell{
  position:relative;z-index:2;min-height:100vh;
  display:flex;flex-direction:column;align-items:center;
  width:100%;max-width:100vw;overflow-x:hidden;
  padding-top:96px; /* clear beta strip + topbar */
}
body:not(.has-beta-strip) .ui-shell{padding-top:64px}
.ui-section{padding:80px 24px;width:100%}
.ui-section-sm{padding:48px 24px;width:100%}
.ui-container{max-width:1100px;margin:0 auto;width:100%}
.ui-container-sm{max-width:760px;margin:0 auto;width:100%}
.ui-divider{height:1px;max-width:1100px;margin:0 auto;background:var(--border)}

/* ── Typography ──────────────────────────────────────────── */
.ui-eyebrow{
  display:inline-block;font-size:.72rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent);
  margin-bottom:20px;
}
.ui-h1{
  font-size:clamp(2.2rem,5vw,3.8rem);font-weight:900;
  text-transform:uppercase;letter-spacing:-.03em;line-height:.95;
  color:var(--text);margin:0 0 16px;
}
.ui-h1 .accent{color:var(--accent)}
.ui-h2{
  font-size:clamp(1.6rem,3.4vw,2.4rem);font-weight:800;
  letter-spacing:-.02em;line-height:1.1;color:var(--text);margin:0 0 14px;
}
.ui-h3{
  font-size:1.1rem;font-weight:700;letter-spacing:-.01em;
  line-height:1.25;color:var(--text);margin:0 0 8px;
}
.ui-lede{
  font-size:clamp(.95rem,1.4vw,1.1rem);color:var(--text-dim);
  line-height:1.65;max-width:620px;margin:0 auto 28px;font-weight:400;
}
.ui-p{font-size:.95rem;color:var(--text-dim);line-height:1.65;margin:0 0 14px}
.ui-muted{color:var(--text-dim)}

/* ── Buttons ─────────────────────────────────────────────── */
.ui-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:14px 32px;border-radius:var(--radius-pill);
  font-size:.82rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  font-family:inherit;cursor:pointer;text-decoration:none;
  border:1px solid transparent;transition:transform .2s var(--ease),background .2s,border-color .2s,box-shadow .2s;
  white-space:nowrap;
}
.ui-btn:hover{transform:translateY(-1px)}
.ui-btn-primary{
  background:var(--accent-solid,#b91c1c);color:#fff;border-color:var(--accent-solid,#b91c1c);
  box-shadow:0 6px 24px var(--accent-glow);
}
.ui-btn-primary:hover{background:#991b1b;border-color:#991b1b}
.ui-btn-secondary{
  background:var(--bg-elev);color:var(--text);border-color:var(--border-strong);
}
.ui-btn-secondary:hover{background:rgba(40,40,48,.75);border-color:var(--text)}
.ui-btn-ghost{
  background:transparent;color:var(--text-dim);border-color:var(--border);
}
.ui-btn-ghost:hover{color:var(--text);border-color:var(--border-strong)}
.ui-btn-sm{padding:10px 20px;font-size:.72rem}

/* Voice AI primary CTA. Solid brand red with a brighter halo so it
   still reads as "primary action" without the gold-amber gradient
   that drifted off-palette. 2026-05-19: orange stripped per user
   feedback. Pulsing white dot inside still signals "live, talk
   right now"; the white ring around the dot pops it against the red. */
.ui-btn-voice{
  display:inline-flex;align-items:center;gap:8px;
  background:#b91c1c;
  color:#fff;border:1px solid rgba(255,255,255,.18);
  font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  box-shadow:0 6px 22px rgba(239,68,68,.48),0 0 0 1px rgba(255,255,255,.08) inset;
  text-decoration:none;white-space:nowrap;
  transition:transform .2s var(--ease),box-shadow .2s,background .2s;
}
.ui-btn-voice:hover{
  transform:translateY(-1px);
  background:#991b1b;
  box-shadow:0 10px 32px rgba(239,68,68,.6),0 0 0 1px rgba(255,255,255,.18) inset;
  color:#fff;
}
.ui-btn-voice-dot{
  width:7px;height:7px;border-radius:50%;
  background:#dc2626;
  box-shadow:0 0 0 2px rgba(255,255,255,.7),0 0 8px rgba(220,38,38,.9);
  /* 2026-05-26: pulse slowed 1.4s -> 2.8s + amplitude softened
     (scale 1.25 -> 1.12) per pulse-glow audit. The dot is the
     primary CTA's "live" signal so it stays animated — just at
     a calmer breathing pace instead of an urgent flash. */
  animation:ui-btn-voice-pulse 2.8s ease-in-out infinite;
}
@keyframes ui-btn-voice-pulse{
  0%,100%{transform:scale(1);opacity:1}
  50%{transform:scale(1.12);opacity:.78}
}
[data-theme="light"] .ui-btn-voice,
body.light-theme .ui-btn-voice{
  border-color:rgba(217,119,6,.65);
  box-shadow:0 6px 22px rgba(217,119,6,.32),0 0 0 1px rgba(0,0,0,.04) inset;
}

/* ── Badges / chips ──────────────────────────────────────── */
.ui-badge{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 12px;border-radius:var(--radius-pill);
  font-size:.7rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  border:1px solid var(--border);color:var(--text-dim);background:var(--bg-card);
}
.ui-badge.accent{border-color:var(--accent-border);color:var(--accent-hover);background:var(--accent-soft)}
.ui-chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:8px 16px;border-radius:var(--radius-pill);
  font-size:.78rem;font-weight:500;color:var(--text-dim);
  background:var(--bg-card);border:1px solid var(--border);
  transition:border-color .2s,color .2s;
}
.ui-chip:hover{color:var(--text);border-color:var(--border-strong)}

/* ── Cards ───────────────────────────────────────────────── */
.ui-card{
  background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:22px;
  transition:border-color .2s,transform .2s;
}
.ui-card:hover{border-color:var(--border-strong)}
.ui-card-label{
  display:block;font-size:.7rem;font-weight:700;color:var(--accent);
  text-transform:uppercase;letter-spacing:.08em;margin-bottom:6px;
}
.ui-card-body{font-size:.88rem;color:var(--text-dim);line-height:1.55}
.ui-grid{display:grid;gap:14px}
.ui-grid-2{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.ui-grid-3{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}

/* ── Footer ──────────────────────────────────────────────── */
.ui-footer{
  padding:48px 24px 32px;border-top:1px solid var(--border);
  text-align:center;font-size:.78rem;color:var(--text-dim);line-height:1.6;
}
.ui-footer a{color:var(--text-dim);text-decoration:none;transition:color .2s}
.ui-footer a:hover{color:var(--text)}
.ui-footer-row{
  display:flex;gap:20px;justify-content:center;flex-wrap:wrap;
  margin-bottom:12px;
}

/* ── Mobile hamburger + slide-down sheet (≤560px only) ────
   The topbar links go display:none below 560px (existing media query
   above). Without this hamburger, mobile users had no way to
   navigate from the bar at all. Hamburger lives in .ui-topbar-right
   but shows ONLY on mobile; desktop uses the inline link rail. */
.ui-topbar-burger{
  display:none;
  width:34px;height:34px;padding:0;
  background:transparent;border:1px solid var(--border-strong, rgba(255,255,255,.18));
  border-radius:999px;color:var(--text, #fff);
  cursor:pointer;align-items:center;justify-content:center;
  font-family:inherit;transition:background .15s, border-color .15s, color .15s;
}
.ui-topbar-burger:hover{background:rgba(255,255,255,.06);border-color:var(--text)}
.ui-topbar-burger.is-open{background:var(--accent-solid,#b91c1c);border-color:var(--accent);color:#fff}
[data-theme="light"] .ui-topbar-burger{border-color:rgba(0,0,0,.18);color:rgba(0,0,0,.78)}
[data-theme="light"] .ui-topbar-burger:hover{background:rgba(0,0,0,.04);color:#1a1a1f}
@media(max-width:1280px){
  .ui-topbar-burger{display:inline-flex}
}

/* Backdrop dims the page while the sheet is open. Pointer-events:auto
   only when .is-open so the dim layer never blocks clicks while invisible. */
.ui-topbar-sheet-backdrop{
  position:fixed;inset:0;z-index:998;
  background:rgba(0,0,0,.45);
  opacity:0;pointer-events:none;
  transition:opacity .18s ease;
}
.ui-topbar-sheet-backdrop.is-open{opacity:1;pointer-events:auto}

/* Sheet itself: full width, anchored just below the topbar, slides
   down from the bar. Stacks LINKS as full-width tap targets +
   primary CTA at the bottom. */
.ui-topbar-sheet{
  position:fixed;left:0;right:0;top:60px;z-index:999;
  display:flex;flex-direction:column;gap:4px;
  padding:14px 16px 22px;
  background:var(--bg-elev-solid, #17171b);
  border-bottom:1px solid var(--border, rgba(255,255,255,.08));
  box-shadow:0 18px 40px rgba(0,0,0,.4);
  transform:translateY(-12px);opacity:0;
  /* CRITICAL: the closed sheet must NOT catch taps. The class rule
     `display:flex` above outranks the UA `[hidden]{display:none}` rule
     (author beats user-agent origin), so the `hidden` attribute the JS
     sets does nothing on its own — leaving an invisible, full-screen,
     z-index:999 overlay that swallowed every tap on mobile and routed it
     to whichever stacked nav link sat under the finger ("tap Live Debates,
     land on Learn"). Two guards make the closed state truly inert:
       1) pointer-events:none whenever .is-open is absent;
       2) [hidden] hard-hides via display:none (restores intended behavior).
     Only .is-open re-enables interaction. */
  pointer-events:none;
  transition:transform .2s ease, opacity .2s ease;
}
.ui-topbar-sheet[hidden]{display:none}
.ui-topbar-sheet.is-open{transform:translateY(0);opacity:1;pointer-events:auto}
body.has-beta-strip .ui-topbar-sheet{top:88px}
.ui-topbar-sheet-link{
  display:flex;align-items:center;gap:10px;
  padding:14px 14px;border-radius:10px;
  font-size:1rem;font-weight:600;letter-spacing:-.005em;
  color:var(--text, #fff);text-decoration:none;
}
.ui-topbar-sheet-link:hover,
.ui-topbar-sheet-link:focus-visible{background:rgba(255,255,255,.04);outline:none}
.ui-topbar-sheet-link.is-active{color:var(--accent)}
.ui-topbar-sheet-dot{
  width:8px;height:8px;border-radius:50%;
  background:#ef4444;box-shadow:0 0 10px #ef4444;flex-shrink:0;
}
.ui-topbar-sheet-cta{
  display:inline-flex;align-items:center;justify-content:center;
  margin:10px 0 0;padding:14px 18px;border-radius:999px;
  background:var(--accent-solid,#b91c1c);color:#fff;text-decoration:none;
  font-size:1rem;font-weight:800;letter-spacing:.01em;
}
.ui-topbar-sheet-cta:hover{background:#dc2626}
/* 2026-08-26: was rgba(255,255,255,.97). Three percent sounds like
   nothing and is not: the sheet covers the hero, and a 64px black
   headline bleeding through at 3% is still plainly readable behind
   the menu labels, which is what made the phone nav look like it was
   printed on tracing paper. A navigation surface is opaque. The dark
   family already was (--bg-elev-solid is solid); only this override
   was see-through. */
[data-theme="light"] .ui-topbar-sheet{background:var(--bg-elev-solid,#fff);border-bottom-color:rgba(0,0,0,.08)}
[data-theme="light"] .ui-topbar-sheet-link{color:#1a1a1f}
[data-theme="light"] .ui-topbar-sheet-link:hover{background:rgba(0,0,0,.04)}
[data-theme="light"] .ui-topbar-sheet-link.is-active{color:#dc2626}
/* Hide the sheet + backdrop entirely above the mobile breakpoint so a
   misfired class toggle on desktop can never leave hidden-but-tappable
   nodes intercepting clicks. */
@media(min-width:1281px){
  .ui-topbar-sheet,
  .ui-topbar-sheet-backdrop{display:none !important}
}

/* The bottom-left floating widgets all sit ABOVE the sheet's z-index
   (Feedback 9999, read-aloud 9500, signup nudge 9999) and the sheet is
   full-height on a phone, so they landed on top of its last entries:
   measured on /practice at 375px, the Feedback pill covered 28px of the
   "Leaderboard" link and clipped "Judging", and being higher in the stack
   it took the tap too. The sheet owns the screen while it is open, so they
   all yield and come back on close. Same rule the sheet already applies to
   the page behind it via body overflow:hidden. */
body.ui-sheet-open .fb-floating,
body.ui-sheet-open .ra-host,
body.ui-sheet-open .signup-nudge,
body.ui-sheet-open .upgrade-cta{display:none !important}

/* ── Topbar utility-toggle hide (sitewide) ─────────────────
   2026-05-26: per the founder, the SFX mute toggle (.sfx-toggle) and the
   sun/moon theme toggle (.theme-toggle) are gone from the topbar
   everywhere — not just mobile. They were tertiary controls that
   added visual noise next to the bell, lang flag, and primary CTA
   without anyone using them. Promoted from the prior @media
   (max-width:560px)-only hide to an unconditional hide that wins
   over every other display:inline-flex declaration earlier in this
   file (including the base .ui-topbar .sfx-toggle{display:inline-flex}
   and .ui-topbar .theme-toggle{display:inline-flex} rules). If we
   ever want either control back, drop this block and the cascade
   restores the originals. The mobile-only hide rule inside the
   @media block is now redundant but harmless.
   2026-05-27 plane session: theme-toggle revived (per user request,
   "have the option to change lighting here"). SFX toggle stays
   killed — that was a separate decision and didn't survive the
   2026-05-19 amber-strip sweep. */
.ui-topbar .sfx-toggle{display:none !important}

/* 2026-05-26: on mobile, the auth chip's inline "Sign out" button
   was getting truncated to "Sig..." at the right edge of the topbar
   because the chip + bell + lang caret + Voice AI pill together
   exceeded the 375px viewport. Hide the Sign-out button on ≤560px;
   the avatar+name pill is still tappable and links to /profile
   where the user can sign out from the profile actions. */
@media(max-width:560px){
  #barUser > button{display:none !important}
}

/* ── Site-wide motion polish (2026-07-01) ─────────────────────
   Loaded via ui.css on ~48 pages, so it's the one place to make the
   whole site feel smoother without touching each page.

   1) Cross-page fade. The View Transitions API crossfades one page into
      the next on same-origin navigation. Pure progressive enhancement:
      browsers without it (or reduced-motion users, via the block below)
      just hard-cut. Matches the existing @view-transition convention on
      index.html / practice.html, spread site-wide.
   2) Smooth interactive states for buttons/links. Deliberately LOW
      specificity and paint-only properties (color/background/border/
      shadow, never transform/layout), so any component's own transition
      wins and nothing janks. Buttons that had instant hovers now ease. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference){
  ::view-transition-old(root),
  ::view-transition-new(root){ animation-duration:260ms; animation-timing-function:cubic-bezier(.22,.9,.32,1); }
  ::view-transition-old(root){ animation-name:ui-vt-out }
  ::view-transition-new(root){ animation-name:ui-vt-in }
  @keyframes ui-vt-out{ to{ opacity:0; transform:translateY(-6px) } }
  @keyframes ui-vt-in { from{ opacity:0; transform:translateY(8px) } }
  a, button{ transition:color .18s ease, background-color .18s ease, border-color .18s ease, box-shadow .18s ease; }
}

/* ── Reduced motion ──────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .ui-nav-btn:hover,.ui-btn:hover{transform:none}
  /* Kill the cross-page crossfade too. */
  ::view-transition-group(*),::view-transition-old(root),::view-transition-new(root){animation:none!important}
}

/* ── Topbar Explore menu ─────────────────────────────────────
   The desktop header stays calm with one disclosure instead of a
   ten-link rail. The open panel reads as a product map: a spotlight
   card for the flagship live action, four annotated columns (icon +
   destination + one-line description), and the site pages as a quiet
   footer strip. The mobile sheet carries the same destinations. */
.ui-topbar-more{position:relative;display:inline-flex}
.ui-topbar-more-btn{
  display:inline-flex;align-items:center;gap:7px;
  margin:0;padding:9px 14px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--text, #fff) 30%,transparent);
  background:color-mix(in srgb,var(--text, #fff) 6%,transparent);
  font-weight:800;letter-spacing:.01em;
  box-shadow:0 1px 0 color-mix(in srgb,var(--text, #fff) 8%,transparent);
  transition:color .18s,background .18s,border-color .18s,box-shadow .18s;
}
.ui-topbar-more-btn:hover,
.ui-topbar-more-btn[aria-expanded="true"]{
  color:var(--text);
  border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 10%,transparent);
  box-shadow:0 5px 16px -10px color-mix(in srgb,var(--accent) 75%,transparent);
}
/* "How it works", beside the Explore trigger. It has to read as a
   first-class button a stranger can find without opening the menu. Hidden
   under 900px, where the topbar collapses to the burger and the mobile
   sheet already carries the same destination. */
.ui-topbar-howbtn{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 12px;border-radius:10px;
  border:1px solid color-mix(in srgb,var(--text, #fff) 22%,transparent);
  /* 2026-09-03, the founder: "how this works and friends should match
     size of explore tab". Explore is .ui-topbar-link at a fixed 15px;
     .8rem here followed each page's root size, so on the landing's 20px
     root these two ran 16px beside a 15px Explore. Same px now. */
  /* 2026-10-11, the founder: "smaller, maybe not both red, not as
     square". 14px, 10px corners, and only Watch keeps the accent tint. */
  font-size:14px;line-height:16px;font-weight:700;letter-spacing:.01em;
  color:var(--text);text-decoration:none;white-space:nowrap;
  transition:border-color .18s,background .18s,color .18s,box-shadow .18s;
}
.ui-topbar-watchbtn{
  border-color:color-mix(in srgb,var(--accent) 55%,transparent);
  background:color-mix(in srgb,var(--accent) 8%,transparent);
  font-weight:800;
  box-shadow:0 5px 16px -12px color-mix(in srgb,var(--accent) 75%,transparent);
}
.ui-topbar-howbtn:hover,
.ui-topbar-howbtn:focus-visible{
  border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 10%,transparent);
  color:var(--text);
}
.ui-topbar-howbtn.is-active{border-color:var(--accent);color:var(--accent)}
.ui-topbar-howbtn svg{flex:none;opacity:.9}
.ui-topbar-friendsbtn{justify-content:center;width:38px;height:38px;padding:0;gap:0;flex:none;box-sizing:border-box}
.ui-topbar-friendsbtn svg{width:20px;height:20px}
.ui-topbar-settings{
  display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:32px;height:32px;padding:0;box-sizing:border-box;border-radius:50%;
  line-height:0;vertical-align:middle;
  border:1px solid var(--border-strong,rgba(255,255,255,.18));
  background:transparent;color:var(--text-dim);text-decoration:none;
  transition:color .15s,border-color .15s,background .15s;
}
/* 2026-10-24: 32px circle and a 16px glyph, matching the theme toggle,
   the bell and the language pill. The inline 38px in topbar.js was the
   odd one out in the cluster. */
.ui-topbar-right .ui-topbar-settings{width:32px !important;height:32px !important}
.ui-topbar-settings svg{display:block;flex:none;width:16px;height:16px}
.ui-topbar-settings:hover,.ui-topbar-settings:focus-visible{
  color:var(--text);border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 8%,transparent);
}
.ui-topbar-settings:focus-visible,.ui-topbar-friendsbtn:focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;
}
/* Keep Watch and account controls in view on narrow signed-in headers;
   How it works remains available in Explore and the mobile menu. */
@media (max-width:1100px){ .ui-topbar-howbtn[href="/how-it-works"]{display:none} }
@media (max-width:900px){ .ui-topbar-howbtn{display:none} }

.ui-topbar-more-btn svg{transition:transform .18s ease}
.ui-topbar-more-btn[aria-expanded="true"] svg{transform:rotate(180deg)}
.ui-topbar-more-panel{
  position:fixed;top:calc(100% + 14px);left:50%;right:auto;z-index:1001;
  width:min(1780px,calc(100vw - 48px));
  display:none;
  /* FOUR product columns, matching the four the panel actually builds
     in topbar.js. This is the SECOND time it has been set to four: the
     2026-08-26 four-column rebuild landed here and a parallel session's
     rebase resolution put the five-column rule back the same day, while
     keeping the four-column JS. The result was a phantom fifth track,
     so the columns sat left and roughly 270px of panel stood empty on
     the right — which is exactly the "spread out" the founder then
     asked for. If you are reconciling this file again: the column
     COUNT lives in topbar.js, and this number follows it.

     2026-08-26 (later): ceiling 1660 -> 1780 and the gutter 10 -> 20,
     per the founder ("take up space across horizontally, spread out").
     Four columns in a 1660 box left each one 339px; at 1780 with real
     gutters they run ~350px and the rows stop crowding their own
     descriptions. */
  grid-template-columns:240px repeat(4,minmax(0,1fr));
  column-gap:20px;row-gap:0;
  padding:20px 22px 14px;border-radius:20px;
  /* Solid, not --bg-elev: inside the blurred topbar, backdrop-filter
     can't reach the page behind, so a translucent bg lets the hero
     text bleed through the open menu. */
  background:
    radial-gradient(circle at 7% 0%,color-mix(in srgb,var(--accent) 9%,transparent),transparent 30%),
    var(--bg-elev-solid, #17171b);
  border:1px solid var(--border, rgba(255,255,255,.1));
  box-shadow:0 34px 90px -30px rgba(0,0,0,.58),0 8px 30px -18px rgba(0,0,0,.3);
}
.ui-topbar-more-panel::before{
  content:"";position:absolute;left:0;right:0;bottom:100%;height:18px;
}
/* The panel never folds, and that is measured rather than assumed: the
   Explore button is display:none under 1280px (the mobile sheet takes
   over), so the narrowest this thing ever renders is a ~1230px box. The
   wide gutters above are what has to give there, not the column count —
   a folded row costs more height than a tight gutter costs legibility. */
@media (max-width:1460px){
  .ui-topbar-more-panel{grid-template-columns:220px repeat(4,minmax(0,1fr));column-gap:12px}
}
.ui-topbar-more-panel.is-open{
  display:grid;
  animation:ui-topbar-explore-in .16s cubic-bezier(.22,.9,.32,1) both;
}
@keyframes ui-topbar-explore-in{
  from{opacity:0;transform:translate(-50%,-8px) scale(.992)}
  to{opacity:1;transform:translate(-50%,0) scale(1)}
}
.ui-topbar-more-intro{
  grid-column:1/-1;display:flex;align-items:baseline;gap:12px;
  min-width:0;padding:2px 8px 12px;margin-bottom:16px;
  border-bottom:1px solid color-mix(in srgb,var(--text,#fff) 8%,transparent);
}
.ui-topbar-more-intro-title{
  font-size:15.5px;font-weight:800;line-height:1.1;letter-spacing:-.01em;
  color:var(--text,#fff);white-space:nowrap;
}
.ui-topbar-more-intro-sub{
  min-width:0;font-size:13.3px;font-weight:500;line-height:1.3;
  color:color-mix(in srgb,var(--text,#fff) 52%,transparent);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.ui-topbar-more-profile{
  margin-left:auto;flex:none;padding:6px 10px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--accent) 28%,transparent);
  background:color-mix(in srgb,var(--accent) 7%,transparent);
  color:var(--text,#fff);font-size:12.5px;font-weight:750;line-height:1.2;
  text-decoration:none;transition:border-color .15s,background .15s;
}
.ui-topbar-more-profile:hover,.ui-topbar-more-profile:focus-visible{
  border-color:color-mix(in srgb,var(--accent) 55%,transparent);
  background:color-mix(in srgb,var(--accent) 13%,transparent);outline:none;
}
.ui-topbar-more-profile[hidden]{display:none}
/* Spotlight: the flagship live action anchors the left edge. */
/* The 20px grid gutter replaces the hand-rolled margin this used to
   carry, so the spotlight sits on the same rhythm as the columns. */
.ui-topbar-more-spotwrap{display:flex;flex-direction:column;gap:6px;min-width:0}
.ui-topbar-more-spot{
  flex:1;display:flex;flex-direction:column;align-items:flex-start;gap:10px;
  min-height:214px;padding:18px 18px 16px;border-radius:16px;text-decoration:none;
  background:
    radial-gradient(circle at 100% 0%,color-mix(in srgb,var(--accent) 15%,transparent),transparent 55%),
    color-mix(in srgb,var(--accent) 6%,var(--bg-elev-solid,#17171b));
  border:1px solid color-mix(in srgb,var(--accent) 24%,transparent);
  transition:border-color .15s,transform .15s,box-shadow .15s;
}
.ui-topbar-more-spot:hover,
.ui-topbar-more-spot:focus-visible{
  border-color:color-mix(in srgb,var(--accent) 45%,transparent);
  transform:translateY(-1px);outline:none;
  box-shadow:0 14px 34px -18px color-mix(in srgb,var(--accent) 45%,transparent);
}
.ui-topbar-more-spot-eyebrow{
  display:inline-flex;align-items:center;gap:7px;
  font-size:10.5px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent);
}
.ui-topbar-more-spot-title{
  font-size:21px;font-weight:800;line-height:1.12;letter-spacing:-.015em;
  color:var(--text,#fff);
}
.ui-topbar-more-spot-sub{
  font-size:13.3px;font-weight:500;line-height:1.45;
  color:color-mix(in srgb,var(--text,#fff) 62%,transparent);
}
/* Faces on one line, caption on the next. Side by side, the caption was
   sharing a ~180px card with the avatar stack and rendering "Real people
   first. AI if the queue is quiet." over FIVE lines in a 57px gutter —
   the exact crop the founder zoomed in on. Wrapping the span to its own
   full-width row gives it the card instead of the leftovers, and is what
   makes room for the bigger faces below. column-gap is 0 on purpose: the
   avatars overlap through their own negative margin, and a gap here
   fights it. */
.ui-topbar-more-spot-proof{
  margin-top:auto;display:flex;flex-wrap:wrap;align-items:center;
  column-gap:0;row-gap:9px;min-width:0;
}
.ui-topbar-more-spot-proof img{
  /* 2026-08-26, the founder on a zoom of this row: "on the images
     increase their size a bit". 24 -> 32, which is the smallest size a
     face reads as a face rather than as a coloured dot; the negative
     margin grows with it so the stack keeps the same overlap ratio and
     the row's width barely moves. */
  flex:none;width:32px;height:32px;border-radius:999px;object-fit:cover;
  border:2px solid color-mix(in srgb,var(--accent) 6%,var(--bg-elev-solid,#17171b));
}
.ui-topbar-more-spot-proof img + img{margin-left:-13px}
.ui-topbar-more-spot-proof>span{
  flex:0 0 100%;
  min-width:0;font-size:12.2px;font-weight:600;line-height:1.3;
  color:color-mix(in srgb,var(--text,#fff) 56%,transparent);
}
.ui-topbar-more-spot-cta{
  display:inline-flex;align-items:center;gap:7px;
  padding:8px 15px;border-radius:999px;
  background:var(--accent-solid,#b91c1c);color:#fff;
  font-size:13.2px;font-weight:800;letter-spacing:.02em;line-height:1;
  transition:box-shadow .15s;
}
.ui-topbar-more-spot:hover .ui-topbar-more-spot-cta{
  box-shadow:0 6px 16px -6px color-mix(in srgb,var(--accent) 70%,transparent);
}
.ui-topbar-more-spot-cta svg{transition:transform .15s}
.ui-topbar-more-spot:hover .ui-topbar-more-spot-cta svg{transform:translateX(2px)}
.ui-topbar-more-spot-alt{
  display:flex;align-items:center;gap:9px;
  padding:7px 10px;border-radius:11px;text-decoration:none;
  font-size:13.2px;font-weight:600;line-height:1.2;
  color:color-mix(in srgb,var(--text,#fff) 62%,transparent);
  transition:color .15s,background .15s;
}
.ui-topbar-more-spot-alt:hover,
.ui-topbar-more-spot-alt:focus-visible{
  color:var(--text,#fff);
  background:color-mix(in srgb,var(--text,#fff) 4.5%,transparent);
  outline:none;
}
.ui-topbar-more-spot-alt .ui-topbar-more-ico{width:26px;height:26px}
/* Columns: open stacks with hairline dividers, no card boxes. */
.ui-topbar-more-col{
  min-width:0;padding:2px 6px 4px 16px;
  border-left:1px solid color-mix(in srgb,var(--text,#fff) 7%,transparent);
  /* Per-column accent. Every coloured part of a row reads var(--col), so
     recolouring a column is one line here rather than six rules below.
     Brand red is the fallback; each current position is mapped below. */
  --col:var(--accent,#ef4444);
}
/* Column palette (set on .ui-topbar-more-col by topbar.js as ui-col-N).
   Four distinct hues so Practice / Learn / Watch / Debate are separable
   at a glance instead of reading as one long red list. (ui-col-5 was
   deleted with the fifth column; Practice inherited its teal. See the
   note on the panel grid before re-adding it.)

   NOT amber or orange, on purpose: the 2026-05-19 sweep reserved those for
   state semantics (warn, achievement, tier). Debate keeps the brand red in
   its new fourth position; the first three categories keep their prior hues.

   These are the DARK-panel values (panel bg #17171b), so they run bright.
   The light-theme block further down darkens all four for white. */
.ui-topbar-more-col.ui-col-1{--col:#3ecfbb}                /* Practice · teal   */
.ui-topbar-more-col.ui-col-2{--col:#a78bfa}                /* Learn + prep · violet */
.ui-topbar-more-col.ui-col-3{--col:#f472b6}                /* Watch    · pink   */
.ui-topbar-more-col.ui-col-4{--col:var(--accent,#ef4444)}  /* Debate  · red    */
/* Light theme: the panel goes solid white (--bg-elev-solid), where the
   bright values above sit around 2:1 on body text and read washed out.
   Verified against #ffffff, not assumed from the dark pair — a light and
   dark token pair is not proof that both render (see the standing note in
   memory). Column 4 needs no entry: --accent is already #b91c1c on light. */
[data-theme="light"] .ui-topbar-more-col.ui-col-1,
body.light-theme .ui-topbar-more-col.ui-col-1{--col:#0f766e}
[data-theme="light"] .ui-topbar-more-col.ui-col-2,
body.light-theme .ui-topbar-more-col.ui-col-2{--col:#6d28d9}
[data-theme="light"] .ui-topbar-more-col.ui-col-3,
body.light-theme .ui-topbar-more-col.ui-col-3{--col:#be185d}
/* --col-text: the same accent, but at a strength that clears 4.5:1 as
   TYPE on this theme's panel. The red Debate column is the one that needed
   splitting: brand red is 4.26:1 on the dark panel, so an active label
   in the Debate column failed while the other three passed. */
.ui-topbar-more-col.ui-col-1{--col-text:#3ecfbb}
.ui-topbar-more-col.ui-col-2{--col-text:#a78bfa}
.ui-topbar-more-col.ui-col-3{--col-text:#f472b6}
.ui-topbar-more-col.ui-col-4{--col-text:#f87171}
[data-theme="light"] .ui-topbar-more-col.ui-col-1,
body.light-theme .ui-topbar-more-col.ui-col-1{--col-text:#0f766e}
[data-theme="light"] .ui-topbar-more-col.ui-col-2,
body.light-theme .ui-topbar-more-col.ui-col-2{--col-text:#6d28d9}
[data-theme="light"] .ui-topbar-more-col.ui-col-3,
body.light-theme .ui-topbar-more-col.ui-col-3{--col-text:#be185d}
[data-theme="light"] .ui-topbar-more-col.ui-col-4,
body.light-theme .ui-topbar-more-col.ui-col-4{--col-text:#b91c1c}
/* Secondary text in the panel, light theme only.
   The alphas below were tuned against the DARK panel, where white at 46
   to 52% still clears 4.5:1. The same alphas of near-black on white land
   at 2.96, 3.33 and 3.54, which is what made the open menu read as a
   page of ghost text on light. Dark measures fine and is left alone. */
[data-theme="light"] .ui-topbar-more-head,
body.light-theme .ui-topbar-more-head{
  color:color-mix(in srgb,var(--text,#fff) 64%,transparent);
}
[data-theme="light"] .ui-topbar-more-item-desc,
body.light-theme .ui-topbar-more-item-desc{
  color:color-mix(in srgb,var(--text,#fff) 66%,transparent);
}
[data-theme="light"] .ui-topbar-more-intro-sub,
body.light-theme .ui-topbar-more-intro-sub{
  color:color-mix(in srgb,var(--text,#fff) 66%,transparent);
}
/* Sits on the tinted spotlight card rather than the white panel, so it
   needs a little more than the rest to clear the same floor. */
[data-theme="light"] .ui-topbar-more-spot-proof>span,
body.light-theme .ui-topbar-more-spot-proof>span{
  color:color-mix(in srgb,var(--text,#fff) 68%,transparent);
}
.ui-topbar-more-head{
  display:flex;align-items:center;gap:7px;
  padding:2px 8px 9px;
  font-size:11.2px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:color-mix(in srgb, var(--text, #fff) 46%, transparent);
  white-space:nowrap;
}
/* The numeral and the active label are the two places a column's accent
   is used as TEXT rather than as a tile or a border, so they read
   `--col-text` instead of `--col`. Measured 2026-08-14: at 82% of --col
   the numeral was 3.86:1 in light and 3.55:1 in dark, and an active
   label in the red column was 4.26:1 in dark, all under the 4.5 floor
   for text this size. --col is tuned to look right as a 12% fill behind
   an icon; the same hue at full strength is not automatically legible as
   9.5px type, which is why these are separate tokens rather than one. */
.ui-topbar-more-head-num{
  font-family:'Geist Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:10.2px;font-weight:800;letter-spacing:.06em;
  color:var(--col-text,var(--col));
}
/* THREE size tiers, and the gap between them is the point. Before this
   there were effectively two (a default row and a `big` card) with
   `is-strong` doing nothing but bolding a label, so a 9-row column read
   as a flat list with one card floating in it. The icon ramp is now
   25 -> 32 -> 42px, which is a difference you can see without comparing.

   Tier 3 (default) - utility rows. Deliberately SMALLER than before so
   the two tiers above it have somewhere to be. */
.ui-topbar-more-item{
  display:flex;align-items:center;gap:10px;
  min-width:0;padding:5px 8px;border-radius:11px;
  text-decoration:none;transition:background .15s;
}
.ui-topbar-more-ico{
  flex:none;display:grid;place-items:center;width:25px;height:25px;border-radius:8px;
  background:color-mix(in srgb,var(--text,#fff) 4%,transparent);
  border:1px solid color-mix(in srgb,var(--text,#fff) 7%,transparent);
  color:color-mix(in srgb,var(--text,#fff) 58%,transparent);
  transition:color .15s,background .15s,border-color .15s;
}
.ui-topbar-more-ico svg{transform:scale(.92)}
.ui-topbar-more-item-text{min-width:0;display:flex;flex-direction:column;gap:1px}
/* 2026-08-24: sizes up from 12.9/11.3 per the founder. The old numbers
   were set when the five columns carried 33 entries and height was the
   binding constraint; the declutter pass took 14 rows out, so the menu
   has vertical room it is not using and the type was reading small for
   it. Width did not change, which is why the wrap rule below matters. */
.ui-topbar-more-item-label{
  display:flex;align-items:center;gap:6px;min-width:0;
  font-size:15px;font-weight:620;line-height:1.25;letter-spacing:.005em;
  color:color-mix(in srgb,var(--text,#fff) 86%,transparent);
  transition:color .15s;
}
/* Was nowrap+ellipsis. The is-big carve-out below already argued the
   right rule ("ellipsising the name of a destination is worse than a
   second line") and there is no reason that stops being true for a
   small tile, so every label wraps now. At the larger size the ones
   that would have clipped are "Spectate live rounds" and "Find a 2v2
   partner"; both take a second line instead of losing their last word. */
.ui-topbar-more-item-label>span:first-child{
  min-width:0;white-space:normal;overflow:visible;text-overflow:clip;
}
/* Flagship tiles set their label a size or two larger, so at the
   narrower five-column width the longest flagship label hit the ellipsis
   (the measurement was taken on "Competitive Voice AI", renamed to
   "Debate the AI" on 2026-08-26: it needed 167px and had 120).
   Ellipsising the name of a destination is worse than a second line, and
   only the big tiles are long enough to need it. The rule stays because
   the next long label will not announce itself. */
.ui-topbar-more-item.is-big .ui-topbar-more-item-label>span:first-child{
  white-space:normal;overflow:visible;text-overflow:clip;
}
.ui-topbar-more-item-desc{
  font-size:13px;font-weight:500;line-height:1.3;
  color:color-mix(in srgb,var(--text,#fff) 50%,transparent);
  /* Wraps to a second line rather than truncating. Five columns are
     narrower than the old four, and measured at 1440 the nowrap version
     clipped 20 of 33 descriptions where the four-column layout clipped
     2. A cut-off description is a worse defect than a tall menu, which
     is the whole thing this split was trying to fix, so the ellipsis
     comes off and the few long ones take a second line. Capped at two so
     one wordy entry cannot stretch its column. */
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  overflow:hidden;
}
.ui-topbar-more-item:hover,
.ui-topbar-more-item:focus-visible{
  background:color-mix(in srgb,var(--text,#fff) 4.5%,transparent);
  outline:none;
}
.ui-topbar-more-item:hover .ui-topbar-more-item-label,
.ui-topbar-more-item:focus-visible .ui-topbar-more-item-label{color:var(--text,#fff)}
.ui-topbar-more-item:hover .ui-topbar-more-ico,
.ui-topbar-more-item:focus-visible .ui-topbar-more-ico,
.ui-topbar-more-item.is-active .ui-topbar-more-ico{
  color:var(--col);
  background:color-mix(in srgb,var(--col) 12%,transparent);
  border-color:color-mix(in srgb,var(--col) 26%,transparent);
}
.ui-topbar-more-item.is-active .ui-topbar-more-item-label{color:var(--col-text,var(--col))}
/* Tier 2: `strong` in topbar.js. The genuine second rank in each column,
   for a destination that is a real product surface but not the column's
   flagship. It gets a bigger icon carrying the column colour at rest (not
   hover-only) and a heavier label, but NO card border, so it sits visibly
   between a plain row and a `big` tile rather than competing with it.

   This used to bold a label and nothing else, which is why the menu read
   as two tiers instead of three. */
.ui-topbar-more-item.is-strong{
  padding:7px 8px;
}
.ui-topbar-more-item.is-strong .ui-topbar-more-ico{
  width:32px;height:32px;border-radius:10px;
  color:color-mix(in srgb,var(--col) 88%,var(--text,#fff));
  background:color-mix(in srgb,var(--col) 8%,transparent);
  border-color:color-mix(in srgb,var(--col) 20%,transparent);
}
.ui-topbar-more-item.is-strong .ui-topbar-more-ico svg{transform:scale(1.06)}
.ui-topbar-more-item.is-strong .ui-topbar-more-item-label{
  font-size:15px;font-weight:800;color:var(--text,#fff);
}
.ui-topbar-more-item.is-strong .ui-topbar-more-item-desc{font-size:12.6px}
.ui-topbar-more-item.is-strong:hover .ui-topbar-more-ico,
.ui-topbar-more-item.is-strong:focus-visible .ui-topbar-more-ico{
  color:var(--col);
  background:color-mix(in srgb,var(--col) 15%,transparent);
  border-color:color-mix(in srgb,var(--col) 32%,transparent);
}
/* Tier 1: `big` in topbar.js. Flagship tiles, sized by venture weight
   (Watch, Claims & challenges, Tournaments, Leaderboard, Competitive
   Voice AI). Leaderboard was named here from the 2026-08-12 hierarchy
   pass onward but was never actually given `big` in topbar.js, so for
   twelve days this comment described a tile that did not exist and the
   board rendered as a 25px utility row. Granted 2026-08-24. A
   bordered card with a large column-coloured icon and the heaviest label
   in the panel. The coloured tile is permanent here, not hover-only:
   these rows are the point of the column.

   Sizes widened in the 2026-08-12 hierarchy pass (icon 38 -> 42, label
   15 -> 15.8, and the card now carries a faint tint of its own column)
   so a tile still outranks the new tier-2 rows underneath it. */
.ui-topbar-more-item.is-big{
  padding:11px 10px;margin:4px 0;border-radius:13px;
  background:
    linear-gradient(180deg,color-mix(in srgb,var(--col) 7%,transparent),transparent 78%),
    color-mix(in srgb,var(--text,#fff) 3%,transparent);
  border:1px solid color-mix(in srgb,var(--col) 20%,transparent);
  transition:background .15s,border-color .15s;
}
.ui-topbar-more-item.is-big .ui-topbar-more-ico{
  width:42px;height:42px;border-radius:12px;
  color:var(--col);
  background:color-mix(in srgb,var(--col) 12%,transparent);
  border-color:color-mix(in srgb,var(--col) 28%,transparent);
}
.ui-topbar-more-item.is-big .ui-topbar-more-ico svg{transform:scale(1.34)}
.ui-topbar-more-item.is-big .ui-topbar-more-item-label{
  font-size:17px;font-weight:850;letter-spacing:-.01em;color:var(--text,#fff);
}
.ui-topbar-more-item.is-big .ui-topbar-more-item-desc{font-size:13.2px}
.ui-topbar-more-item.is-big:hover,
.ui-topbar-more-item.is-big:focus-visible{
  background:
    linear-gradient(180deg,color-mix(in srgb,var(--col) 13%,transparent),transparent 78%),
    color-mix(in srgb,var(--text,#fff) 4%,transparent);
  border-color:color-mix(in srgb,var(--col) 38%,transparent);
}
/* Flagship tile depth. A 42px tile is big enough to read as a SURFACE
   rather than a swatch, so it gets a raked gradient, a hairline top
   highlight and a coloured drop, which is what separates a tile you can
   press from a coloured square. Deliberately not applied to tier 2 or 3:
   at 32px and 25px the same treatment reads as noise, and the point of
   the ramp is that the tiers look different. */
.ui-topbar-more-item.is-big .ui-topbar-more-ico{
  background:
    linear-gradient(155deg,
      color-mix(in srgb,var(--col) 24%,transparent),
      color-mix(in srgb,var(--col) 9%,transparent) 70%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,#fff 16%,transparent),
    0 5px 14px -8px color-mix(in srgb,var(--col) 65%,transparent);
}
.ui-topbar-more-item.is-big:hover .ui-topbar-more-ico,
.ui-topbar-more-item.is-big:focus-visible .ui-topbar-more-ico{
  background:
    linear-gradient(155deg,
      color-mix(in srgb,var(--col) 34%,transparent),
      color-mix(in srgb,var(--col) 13%,transparent) 70%);
  border-color:color-mix(in srgb,var(--col) 42%,transparent);
}

/* ── Explore motion ───────────────────────────────────────────────────
   2026-08-24. The panel itself has faded in since it shipped, but the
   columns arrived with it as one flat block, and a row answered a hover
   with a background change and nothing else. Two additions, both behind
   prefers-reduced-motion so the whole thing is inert for anyone who has
   asked for that.

   The stagger is 45ms per COLUMN, not per row. Per-row would take a
   33-row panel most of a second to finish assembling, which is a menu
   you wait for; per-column the eye reads it as the panel dealing itself
   left to right and it is over in ~230ms. --ci is set by topbar.js
   because CSS cannot count elements by class. */
@media (prefers-reduced-motion:no-preference){
  .ui-topbar-more-panel.is-open .ui-topbar-more-col{
    animation:ui-topbar-col-in .3s cubic-bezier(.22,.9,.32,1) both;
    animation-delay:calc(var(--ci,0) * 45ms + 40ms);
  }
  @keyframes ui-topbar-col-in{
    from{opacity:0;transform:translateY(7px)}
    to{opacity:1;transform:none}
  }
  /* The icon is the part that moves, not the row: shifting a whole row
     on hover drags its description with it and the text stops being
     readable mid-transition. */
  .ui-topbar-more-ico{
    transition:color .15s,background .15s,border-color .15s,box-shadow .15s,
               transform .2s cubic-bezier(.22,.9,.32,1);
  }
  .ui-topbar-more-item:hover .ui-topbar-more-ico,
  .ui-topbar-more-item:focus-visible .ui-topbar-more-ico{
    transform:translateY(-1px) scale(1.05);
  }
  .ui-topbar-more-item.is-big:hover .ui-topbar-more-ico,
  .ui-topbar-more-item.is-big:focus-visible .ui-topbar-more-ico{
    transform:translateY(-2px) scale(1.04);
  }
  /* Press feedback. A flagship tile is a button-sized target, so it
     should answer a mousedown before the navigation starts. */
  .ui-topbar-more-item:active .ui-topbar-more-ico{
    transform:scale(.95);transition-duration:.06s;
  }
  .ui-topbar-more-item.is-big{transition:background .15s,border-color .15s,transform .12s}
  .ui-topbar-more-item.is-big:active{transform:scale(.988)}
}
/* ── "In progress" rows in Explore ─────────────────────────────────────
   2026-08-23, `wip: true` in topbar.js. 2026-08-24, the founder: these
   rows should be "blocked by a blur thing". So the row is out of focus
   and out of service. The name, icon and sentence blur; the mark stays
   sharp on top of them; topbar.js takes the href off, which is what
   actually blocks it (pointer target, keyboard focus and the copy-link
   menu all go with the href, where pointer-events:none would leave
   Enter-on-focus working).

   The blur is deliberately readable-ish rather than opaque: a visitor
   should still see that a surface EXISTS and roughly what it is, and
   come back for it. What they cannot do is walk into it half-built.

   The mark is a direct child of the row and out of flow, because a
   filter on an ancestor blurs every descendant with it. */
.ui-topbar-more-wip{
  flex:none;
  font-size:9.2px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:color-mix(in srgb,var(--text,#fff) 38%,transparent);
  white-space:nowrap;
}
.ui-topbar-more-item.is-wip{
  position:relative;
  cursor:default;
}
/* 2026-08-24, the founder: "it should title what's in progress." The
   name of the surface now stays SHARP; only the icon and the sentence
   under it go out of focus. A blurred name plus a generic IN PROGRESS
   mark told a visitor that SOMETHING is being built without telling
   them what, which is the one thing the row is still good for. What
   stays gated is the click, not the reading. */
.ui-topbar-more-item.is-wip .ui-topbar-more-ico,
.ui-topbar-more-item.is-wip .ui-topbar-more-item-desc{
  filter:blur(3px);
  opacity:.5;
  user-select:none;
  transition:filter .18s ease,opacity .18s ease;
}
.ui-topbar-more-item.is-wip .ui-topbar-more-item-label{
  opacity:.72;
  transition:opacity .18s ease;
}
/* A blur is a paint effect, so the text under it is still selectable and
   still copyable without this. */
.ui-topbar-more-item.is-wip .ui-topbar-more-item-text{pointer-events:none}
/* Right-aligned, not centred: centred it landed on the name line, which
   is the line that now has to stay readable. */
.ui-topbar-more-wip-over{
  position:absolute;right:10px;top:50%;
  transform:translateY(-50%);
  z-index:2;
  padding:3px 8px;border-radius:999px;
  font-size:9px;
  color:color-mix(in srgb,var(--text,#fff) 74%,transparent);
  background:color-mix(in srgb,var(--bg,#000) 62%,transparent);
  border:1px solid color-mix(in srgb,var(--text,#fff) 14%,transparent);
  backdrop-filter:blur(2px);
  -webkit-backdrop-filter:blur(2px);
  pointer-events:none;
}
/* A flagship tile is tall enough that a centred mark floats in the
   middle of nothing; it sits under the label instead. */
.ui-topbar-more-item.is-big .ui-topbar-more-wip-over{
  top:auto;bottom:12px;right:12px;
}
/* Hover does NOT restore the row. The old treatment un-dimmed on hover
   because the row was a real destination and a permanently dim link
   reads as broken; this one is not a destination, so lifting the gate
   under the cursor would promise a click that does nothing. It softens
   just enough to answer the pointer. */
.ui-topbar-more-item.is-wip:hover .ui-topbar-more-ico,
.ui-topbar-more-item.is-wip:hover .ui-topbar-more-item-desc{
  filter:blur(2.2px);
  opacity:.62;
}
.ui-topbar-more-item.is-wip:hover .ui-topbar-more-item-label{opacity:.85}
/* Mobile sheet: same gate, one line, no icon to blur. */
.ui-topbar-sheet-more a.is-wip,
.ui-topbar-sheet-link.is-wip{
  display:flex;align-items:baseline;gap:6px;
  cursor:default;
}
/* The sheet row is one line and that line is the name, so blurring it
   left nothing to read at all. It dims; the mark beside it says why. */
.ui-topbar-sheet-more a.is-wip .ui-topbar-sheet-more-label,
.ui-topbar-sheet-link.is-wip .ui-topbar-sheet-link-label{
  opacity:.62;
  user-select:none;
  pointer-events:none;
}
.ui-topbar-sheet-more a.is-wip .ui-topbar-more-wip{font-size:8.6px}
/* Someone who has asked the OS not to animate has usually also asked for
   fewer visual effects; the mark alone still says the row is not open. */
@media (prefers-reduced-transparency: reduce){
  .ui-topbar-more-wip-over{backdrop-filter:none;-webkit-backdrop-filter:none}
}
/* Live pulse dot, shared by the spotlight eyebrow and the LIVE row. */
.ui-topbar-more-live-dot{
  flex:none;width:7px;height:7px;border-radius:999px;background:var(--accent);
  animation:ui-topbar-more-dot 2.8s ease-in-out infinite;
}
@keyframes ui-topbar-more-dot{
  0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 45%,transparent)}
  60%{box-shadow:0 0 0 5px color-mix(in srgb,var(--accent) 0%,transparent)}
}
/* Site pages: quiet footer strip under a hairline. */
.ui-topbar-more-site{
  grid-column:1/-1;display:flex;align-items:center;flex-wrap:wrap;gap:2px 4px;
  margin-top:14px;padding:10px 8px 0;
  border-top:1px solid color-mix(in srgb,var(--text,#fff) 8%,transparent);
}
/* 42% failed in BOTH themes (4.08:1 dark, 2.65:1 light), so this one is
   raised at the base rule rather than in the light block. */
.ui-topbar-more-site-head{
  margin-right:12px;
  font-size:11px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:color-mix(in srgb,var(--text,#fff) 62%,transparent);
}
.ui-topbar-more-site a{
  padding:5px 10px;border-radius:999px;text-decoration:none;
  font-size:13.2px;font-weight:600;line-height:1.2;
  color:color-mix(in srgb,var(--text,#fff) 62%,transparent);
  transition:color .15s,background .15s;
}
.ui-topbar-more-site a:hover,
.ui-topbar-more-site a:focus-visible{
  color:var(--text,#fff);
  background:color-mix(in srgb,var(--text,#fff) 4.5%,transparent);
  outline:none;
}
.ui-topbar-more-site a.is-active{color:var(--accent)}
@media(max-width:1280px){
  .ui-topbar-more{display:none}
}

/* Mobile-sheet More group: quiet two-column grid under the main
   stack so ten extra links don't triple the sheet's height. The
   sheet itself gains a scroll guard for short viewports. */
.ui-topbar-sheet{max-height:calc(100dvh - 60px);overflow-y:auto;padding-bottom:calc(22px + env(safe-area-inset-bottom,0px))}
/* 2026-09-01 mobile pass: anchor targets scroll clear of the fixed topbar
   instead of landing underneath it. scroll-margin only affects anchor and
   scrollIntoView landings, so it cannot move anything at rest. */
[id]{scroll-margin-top:64px}
body.has-beta-strip [id]{scroll-margin-top:96px}
.ui-topbar-sheet-more-head{
  margin:10px 14px 2px;padding-top:12px;
  border-top:1px solid var(--border, rgba(255,255,255,.08));
  /* max(): the 2026-08-26 mobile root drop (13.5px) would put a bare
     .6rem at 8.1px, which is past reading and into decoration. The rem
     still governs desktop; the floor only engages once the root shrinks. */
  font-size:max(10px,.6rem);font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:color-mix(in srgb, var(--text, #fff) 52%, transparent);
}
.ui-topbar-sheet-more{display:grid;grid-template-columns:1fr 1fr;gap:0 10px;padding:0 4px}
.ui-topbar-sheet-more a{
  display:block;padding:10px 10px;border-radius:8px;
  font-size:.85rem;font-weight:500;
  color:color-mix(in srgb, var(--text, #fff) 78%, transparent);
  text-decoration:none;
}
.ui-topbar-sheet-more a:hover,
.ui-topbar-sheet-more a:focus-visible{background:rgba(255,255,255,.04);outline:none}
.ui-topbar-sheet-more a.is-active{color:var(--accent)}

/* ── Dark-mode reminder card ────────────────────────────────────────
   Bottom-centre so it clears the feedback and community controls, which
   both sit bottom-left, and clears the topbar entirely — the corner the
   2026-08-26 pass was decluttering. Sits under modals (z 9000) and over
   page content. See the module in topbar.js for why it appears at most
   once per browser. */
.da-dark-nudge{
  /* Anchored on both edges rather than left:50% alone. A fixed element
     positioned only from the left shrink-to-fits into the space that is
     LEFT of it, so at left:50% on a 375px phone the card was capped at
     187px and wrapped into a four-line block. Insetting both sides and
     letting margin centre it gives the pill the full width it is
     allowed. */
  /* 76px, not 16px. The floating feedback button is 42px square at
     left:12px bottom:12px on every topbar page, and at bottom:16px this
     card landed straight on top of it: measured on the landing at 375px,
     the FAB covered the card's first words ("Reading at night?" rendered
     as "ding at night?"). experience-ask.js clears the same button the
     same way and for the same reason. */
  position:fixed;left:12px;right:12px;bottom:calc(76px + env(safe-area-inset-bottom,0px));
  margin:0 auto;width:max-content;
  transform:translateY(14px);
  z-index:9000;
  display:flex;align-items:center;gap:10px;
  max-width:min(94vw,420px);
  padding:10px 10px 10px 14px;border-radius:999px;
  background:#17171b;color:#fff;
  border:1px solid rgba(255,255,255,.16);
  box-shadow:0 12px 34px rgba(0,0,0,.34);
  font-family:var(--font-body);
  opacity:0;pointer-events:none;
  transition:opacity .22s ease, transform .22s ease;
}
.da-dark-nudge.is-in{opacity:1;transform:translateY(0);pointer-events:auto}
.da-dark-nudge-txt{
  font-size:12.5px;font-weight:500;line-height:1.25;
  color:rgba(255,255,255,.86);
}
.da-dark-nudge-go{
  flex:none;
  padding:7px 12px;border-radius:999px;border:0;
  background:#b91c1c;color:#fff;
  font-family:inherit;font-size:12px;font-weight:800;letter-spacing:.01em;
  cursor:pointer;
}
.da-dark-nudge-go:hover{background:#dc2626}
.da-dark-nudge-x{
  flex:none;
  background:transparent;border:0;color:rgba(255,255,255,.6);
  font-family:inherit;font-size:12px;font-weight:700;line-height:1;cursor:pointer;padding:7px 6px;
}
.da-dark-nudge-x:hover{color:#fff}
@media(min-width:561px){
  .da-dark-nudge{bottom:24px}
}
@media(prefers-reduced-motion:reduce){
  .da-dark-nudge{transition:opacity .22s ease}
  .da-dark-nudge,.da-dark-nudge.is-in{transform:none}
}

/* ── Mobile type scale ──────────────────────────────────────────────
   2026-08-26, the founder: "decrease font size in text in a lot of
   mobile so it simplifies."

   This is the ROOT size and nothing else, deliberately. The obvious
   alternative was to set h1/h2/p directly on phones, and it was tried
   and rejected against the live pages: a blanket `h2{font-size:1.4rem}`
   shrinks the big ones and INFLATES the small ones, measured on
   /how-it-works where the first h2 is an 11.1px eyebrow and the rule
   blew it up to 18.9px. Half this site uses low-level headings as
   labels, so any absolute heading rule is as likely to make a page
   louder as quieter. Capping h1 was rejected for a different reason:
   the landing hero is a composition that was deliberately rebuilt
   around a large visible h1 on 2026-08-19, and a global cap would
   quietly undo it.

   Scaling the root scales every rem-based size on the page by the same
   factor, so it can only ever shrink, it preserves the hierarchy each
   page authored, and the hero stays a hero at a smaller size.

   !important is load-bearing here and it is not laziness. There are six
   competing `html{font-size}` declarations in play on a typical page
   (three in this file, three inline per-page), and the inline ones win
   on source order because this stylesheet is linked before them. Pages
   land around 16px on phones today; 13.5px is roughly a 16% reduction,
   with body copy still resolving to ~14px because most body rules sit
   above 1rem. Do not push this lower without measuring real body text
   on a real page: the floor is legibility, not a number in this file.

   Scoped to 560px, the width the rest of this file already treats as a
   phone. The pre-existing 640px rules above are left alone rather than
   reconciled; they are overridden per-page anyway and untangling six
   declarations is its own pass. */
@media(max-width:560px){
  html{font-size:13.5px !important}
}

/* ── Mobile sheet: group headings + the settings row ────────────────
   2026-08-26. The sheet used to print ONE "More" heading and then
   nineteen rows in a single grid. It now prints a heading per group
   (Compete / Watch & community / Train / Site), which is the structure
   the desktop panel always had and the phone never got.

   With several headings instead of one, the old heading rule's 12px
   top padding plus a full-width rule line repeated four times read as
   four horizontal bars marching down the sheet. The first heading keeps
   its divider because it genuinely separates the primary stack above
   from the secondary grids below; the rest are spacing only, so the
   groups read as one list with signposts rather than four boxed
   sections. :not(:first-of-type) is doing that, and it is why the
   divider does not simply move onto .ui-topbar-sheet-more-head. */
.ui-topbar-sheet-more-head:not(:first-of-type){
  border-top:0;
  padding-top:2px;
  margin-top:14px;
}

/* Appearance control, re-parented here from the bar under 560px by
   placeUtilities() in topbar.js. Every .theme-toggle rule in this file
   is scoped to `.ui-topbar`, so the moved node arrives with no styling
   at all — including the absolutely-positioned sun/moon pair, which
   without the opacity swap renders BOTH glyphs stacked on top of each
   other. These rules are that styling, restated for its second home
   rather than un-scoping the originals, which would change how the
   control looks on desktop. */
.ui-topbar-sheet-utils{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  position:relative;
  margin:12px 4px 2px;padding:12px 10px 10px 14px;
  border-radius:10px;cursor:pointer;
}
/* Divider as a pseudo-element, not border-top. A top border on a box
   with border-radius curls up at both ends, which drew the row as a
   rounded outline instead of a rule under the list. The radius has to
   stay for the hover fill, so the line moves off the border. */
.ui-topbar-sheet-utils::before{
  content:'';position:absolute;left:10px;right:10px;top:0;
  border-top:1px solid var(--border, rgba(255,255,255,.08));
}
.ui-topbar-sheet-utils[hidden]{display:none}
.ui-topbar-sheet-utils:hover{background:rgba(255,255,255,.04)}
[data-theme="light"] .ui-topbar-sheet-utils:hover{background:rgba(0,0,0,.04)}
/* Named at row weight, not at heading weight. This is a control the
   founder wants people to NOTICE (2026-08-26), so it is set like the
   other things you can tap in here rather than like the .16em uppercase
   section labels above it, which are signposts and read as inert. */
.ui-topbar-sheet-utils-label{
  font-size:.9rem;font-weight:600;letter-spacing:-.005em;
  color:var(--text, #fff);
}
[data-theme="light"] .ui-topbar-sheet-utils-label{color:#1a1a1f}
.ui-topbar-sheet-utils .theme-toggle{
  position:relative;
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;padding:0;border-radius:999px;
  background:transparent;border:1px solid var(--border-strong, rgba(255,255,255,.18));
  color:var(--text-dim, rgba(255,255,255,.62));
  cursor:pointer;font-family:inherit;
  /* Full opacity, unlike the bar copy: the bar dims its secondary
     controls until the bar is hovered, and there is no hover on a
     phone. A 55%-opacity control inside an opened menu just reads as
     disabled. 34px so it clears the 34px tap-target floor the burger
     and bell already meet. */
  opacity:1;
  transition:color .15s, background .15s, border-color .15s;
}
.ui-topbar-sheet-utils .theme-toggle svg{
  width:15px;height:15px;display:block;
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  transition:opacity .15s;
}
.ui-topbar-sheet-utils .theme-toggle .ti-sun{opacity:1}
.ui-topbar-sheet-utils .theme-toggle .ti-moon{opacity:0}
[data-theme="light"] .ui-topbar-sheet-utils .theme-toggle{
  border-color:rgba(0,0,0,.18);color:rgba(0,0,0,.64);
}
[data-theme="light"] .ui-topbar-sheet-utils .theme-toggle .ti-sun{opacity:0}
[data-theme="light"] .ui-topbar-sheet-utils .theme-toggle .ti-moon{opacity:1}

/* ── Social accounts ───────────────────────────────────────────────────
   Rendered from the SOCIALS array in topbar.js. Monochrome at rest so a
   row of platform logos doesn't read as a sponsor strip in the middle of
   the product nav; each link carries its platform colour as --brand and
   only spends it on hover and focus.

   Desktop rail: icon-only. This bar has overflowed at laptop widths more
   than once, so the accounts pay for themselves in glyph width or not at
   all. Hidden under 900px, where the sheet row below takes over. */
.ui-topbar-socials{display:inline-flex;align-items:center;gap:2px;margin:0 2px}
.ui-topbar-social{
  display:grid;place-items:center;width:32px;height:32px;border-radius:9px;
  color:color-mix(in srgb,var(--text,#fff) 58%,transparent);
  border:1px solid transparent;
  text-decoration:none;
  transition:color .15s,background .15s,border-color .15s;
}
.ui-topbar-social:hover,
.ui-topbar-social:focus-visible{
  color:var(--brand,var(--accent));
  background:color-mix(in srgb,var(--brand,var(--accent)) 12%,transparent);
  border-color:color-mix(in srgb,var(--brand,var(--accent)) 30%,transparent);
  outline:none;
}
[data-lighting="light"] .ui-topbar .ui-topbar-social{color:rgba(0,0,0,.6)}
[data-lighting="dark"] .ui-topbar .ui-topbar-social{color:rgba(255,255,255,.68)}
@media(max-width:900px){ .ui-topbar-socials{display:none} }

/* Points chip. A wallet readout, not a nav tab: quiet by default, the
   numeral doing the work, and it only exists for a signed-in visitor
   who actually holds a balance. Tabular numerals so the width does not
   jump between 1,000 and 950 as the number moves.
   `[hidden]` needs the !important because the UA rule loses to any
   author rule that sets `display` — the same trap that rendered an
   empty stats strip on /ladder. */
.ui-topbar-points[hidden]{display:none!important}
.ui-topbar-points{
  display:inline-flex;align-items:baseline;gap:4px;
  padding:4px 10px;border-radius:999px;
  border:1px solid var(--border);
  background:var(--bg-card,transparent);
  text-decoration:none;line-height:1;
  transition:background .15s,border-color .15s;
}
.ui-topbar-points:hover,
.ui-topbar-points:focus-visible{
  background:var(--bg-elev);border-color:var(--accent);outline:none;
}
.ui-topbar-points-v{
  font-weight:800;font-size:.78rem;color:var(--text);
  font-variant-numeric:tabular-nums;
}
.ui-topbar-points-k{
  font-size:.62rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-dim);
}
[data-lighting="light"] .ui-topbar .ui-topbar-points-k{color:rgba(0,0,0,.55)}
[data-lighting="dark"] .ui-topbar .ui-topbar-points-k{color:rgba(255,255,255,.6)}
/* Under 560px the name and Sign out already drop off this bar. The chip
   is narrower than either and is the whole point of the change, so it
   stays; the socials above it are what yields the width. */

/* Mobile sheet: labelled rows, because a bare glyph inside a list of
   words is a guessing game. Handle sits right-aligned so the row still
   reads as one line rather than two. */
.ui-topbar-sheet-socials{
  display:flex;flex-direction:column;
  margin:10px 14px 4px;padding-top:12px;
  border-top:1px solid var(--border, rgba(255,255,255,.08));
}
.ui-topbar-sheet-social{
  display:flex;align-items:center;gap:10px;
  padding:11px 0;border-radius:8px;text-decoration:none;
  font-size:.9rem;font-weight:600;
  color:color-mix(in srgb,var(--text,#fff) 84%,transparent);
}
.ui-topbar-sheet-social:hover,
.ui-topbar-sheet-social:focus-visible{color:var(--brand,var(--accent));outline:none}
.ui-topbar-sheet-social-h{
  margin-left:auto;font-weight:500;
  color:color-mix(in srgb,var(--text,#fff) 48%,transparent);
}
[data-theme="light"] .ui-topbar-sheet-social{color:#1a1a1f}

/* ── Contrast safeguards ───────────────────────────────────
   A number of React-heavy pages carry a crawler-visible site footer with
   dark-theme slate colors inline. In light mode those links landed around
   2.3:1. Keep the footer source simple, but bind its final ink to the active
   theme so the same markup clears AA in every lighting mode. */
[data-theme="light"] aside[aria-label="Site navigation"],
[data-lighting="light"] aside[aria-label="Site navigation"],
body.light-theme aside[aria-label="Site navigation"]{
  color:rgba(0,0,0,.68) !important;
  border-top-color:rgba(0,0,0,.14) !important;
}
[data-theme="light"] aside[aria-label="Site navigation"] a,
[data-lighting="light"] aside[aria-label="Site navigation"] a,
body.light-theme aside[aria-label="Site navigation"] a{
  color:inherit !important;
}

/* ── Readability floor (2026-08-18) ─────────────────────────
   The site read small: 16px root with rem micro-labels at .6-.78rem,
   and a 14px mobile root that shrank everything a further 12.5%.
   One size up across the board. rem-based type on every page that
   loads this file scales with the root, so this is the sitewide lever.
   Keep this block LAST so it wins the earlier 16px/14px declarations. */
html{font-size:17px}
body{font-size:17px}
@media(max-width:640px){
  /* was 14px: phones are where the small type hurt most */
  html{font-size:15.5px}
}

/* ── Phone tab bar ── 2026-09-02 ─────────────────────────────────────
   Founder: mobile is overwhelming, make it an app. js/topbar.js mounts
   a five-tab bar (Friends / Watch / Debate / Board / Me) on phones, web
   only: the iOS shell draws its own in native-bridge.js and sets
   html.dbnative, which this whole block stands down for. Hidden above
   720px so tablets and desktop keep the rail. body.has-tabbar reserves
   the height and lifts every fixed-bottom floater the site already
   ships (live popup, signup pill, sign-in wall CTA, experience ask)
   so nothing lands under the bar. Round surfaces never get it; see the
   SKIP regex in topbar.js. */
.da-tabbar{display:none}
@media(max-width:720px){
  html:not(.dbnative) body.has-tabbar .da-tabbar{display:flex}
  html:not(.dbnative) body.has-tabbar{padding-bottom:calc(64px + env(safe-area-inset-bottom,0px))}
  .da-tabbar{
    position:fixed;left:0;right:0;bottom:0;z-index:1200;
    height:calc(62px + env(safe-area-inset-bottom,0px));
    padding:0 4px env(safe-area-inset-bottom,0px);
    justify-content:space-around;align-items:stretch;
    background:var(--bg-elev-solid,#17171b);
    border-top:1px solid var(--border,rgba(255,255,255,.08));
    box-shadow:0 -8px 24px rgba(0,0,0,.08);
  }
  .da-tab{
    flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    padding:6px 2px 4px;color:var(--text-dim,rgba(255,255,255,.68));text-decoration:none;
    font-family:var(--font-body,'Inter',system-ui,sans-serif);font-size:10.5px;font-weight:700;letter-spacing:.02em;line-height:1;
    -webkit-tap-highlight-color:transparent;
  }
  .da-tab svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex:none}
  .da-tab.is-active{color:var(--accent-solid,#b91c1c)}
  [data-theme="light"] .da-tab{color:rgba(26,26,31,.6)}
  [data-theme="light"] .da-tab.is-active{color:#b91c1c}
  /* Debate is the home control, so it is the raised red disc in the
     middle, the same weight the landing's Meet someone door carries. */
  .da-tab--primary .da-tab-ic{
    width:46px;height:46px;margin-top:-18px;border-radius:50%;display:grid;place-items:center;
    background:var(--accent-solid,#b91c1c);color:#fff;
    box-shadow:0 10px 22px rgba(185,28,28,.35),0 0 0 4px var(--bg-elev-solid,#17171b);
  }
  .da-tab--primary .da-tab-ic svg{width:24px;height:24px}
  .da-tab--primary{color:var(--text,#fff)}
  [data-theme="light"] .da-tab--primary{color:#1a1a1f}
  .da-tab--primary.is-active .da-tab-ic{background:#dc2626}
  .da-tab-badge{
    position:absolute;top:2px;right:calc(50% - 20px);min-width:16px;height:16px;padding:0 4px;border-radius:8px;
    background:#dc2626;color:#fff;font-size:10px;font-weight:800;line-height:16px;text-align:center;
  }
  .da-tab{position:relative}
  /* Floaters that already sit on the bottom edge ride up over the bar. */
  body.has-tabbar .da-livepop,
  body.has-tabbar .signup-pill,
  body.has-tabbar .fb-floating,
  body.has-tabbar .upgrade-cta,
  body.has-tabbar #daWallGo{bottom:calc(78px + env(safe-area-inset-bottom,0px)) !important}
  body.has-tabbar #daExpAsk{bottom:calc(136px + env(safe-area-inset-bottom,0px)) !important}
  body.has-tabbar .ui-topbar-sheet{padding-bottom:calc(84px + env(safe-area-inset-bottom,0px));max-height:calc(100svh - 60px);overflow-y:auto}
}

/* The Google "G" on every "Continue with Google" button (2026-09-03, the
   founder: "have the google logo and coloring here obviously"). Four
   brand colours, never recoloured; sits left of the label at cap height. */
.g-mark{display:inline-block;width:18px;height:18px;flex:none;vertical-align:-4px;margin-right:10px}

/* ── Site language picker (js/locale.js, 2026-09-07) ─────────────────
   Same dim-until-hover treatment as .theme-toggle: a settings control,
   not a call to action. Hidden on phones; the burger sheet carries a
   labelled row instead (.ui-topbar-sheet-lang). */
.db-locale-picker{
  display:inline-flex;align-items:center;height:32px;
  padding:0;border-radius:999px;position:relative;
  border:1px solid var(--border-strong, rgba(255,255,255,.18));
  color:var(--text-dim, rgba(255,255,255,.62));
  font-family:inherit;font-size:.76rem;font-weight:600;line-height:1;
  cursor:pointer;opacity:1;
  transition:color .15s, border-color .15s;
}
.db-locale-picker:hover,
.db-locale-picker:focus-within{color:var(--text, #fff);border-color:var(--text, #fff)}
/* The native select covers the pill, including the globe and padding.
   A label click only focuses a select; it does not open its menu. */
.db-locale-picker .db-locale-glyph{position:absolute;left:9px;width:15px;height:15px;line-height:0;display:block;pointer-events:none}
.db-locale-picker .db-locale-glyph svg{width:15px;height:15px;display:block}
.db-locale-picker .db-locale-select{
  appearance:none;-webkit-appearance:none;background:transparent;border:0;
  color:inherit;font:inherit;height:100%;padding:0 10px 0 29px;margin:0;
  cursor:pointer;outline:none;border-radius:inherit;max-width:158px;
}
.db-locale-picker .db-locale-select option{color:#111;background:#fff}
[data-theme="light"] .db-locale-picker{border-color:rgba(0,0,0,.18);color:rgba(0,0,0,.64)}
[data-theme="light"] .ui-topbar:hover .db-locale-picker,
[data-theme="light"] .db-locale-picker:hover,
[data-theme="light"] .db-locale-picker:focus-within{color:#1a1a1f;border-color:#1a1a1f}
@media(max-width:560px){.ui-topbar .ui-topbar-right > .db-locale-picker{display:none}}
.ui-topbar-sheet-lang{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0}
.ui-topbar-sheet-lang .db-locale-picker{opacity:1}

/* The loop hangs below the bar and points back to the wordmark. */
.ui-home-cue{
  --home-cue-red:#b91c1c;--home-cue-arrow:#b91c1c;
  position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  margin-inline-start:18px;min-height:44px;padding:0 13px;white-space:nowrap;
  font-family:var(--font-display);font-size:16px;font-weight:800;line-height:1;letter-spacing:.01em;
  text-decoration:none;color:#fff;background:var(--home-cue-red);border:2px solid var(--home-cue-red);border-radius:8px;
  transform:translateY(9px) rotate(-8deg);transform-origin:center;
  box-shadow:0 3px 0 rgba(0,0,0,.2);animation:ui-home-lean 4.8s ease-in-out infinite;
}
[data-lighting="dark"] .ui-home-cue{--home-cue-arrow:#f87171;border-color:#f87171}
.ui-home-cue-label{position:relative;z-index:1}
.ui-home-cue-arrow{position:absolute;right:-8px;top:25px;width:132px;pointer-events:none;color:var(--home-cue-arrow)}
.ui-home-cue-arrow svg{display:block;width:100%;height:auto;overflow:visible}
.ui-home-cue:hover,.ui-home-cue:focus-visible{animation-play-state:paused;background:#991b1b}
.ui-home-cue:focus-visible{outline:3px solid var(--text,#fff);outline-offset:4px}
@keyframes ui-home-lean{
  0%,32%,52%,100%{transform:translateY(9px) rotate(-8deg)}
  40%{transform:translate(3px,12px) rotate(-3deg)}
  46%{transform:translate(-1px,9px) rotate(-10deg)}
}
@media(max-width:760px){
  .ui-home-cue{font-size:12px;padding:0 8px;margin-inline-start:8px;letter-spacing:0;border-radius:6px}
  .ui-home-cue-arrow{width:94px;right:-6px;top:28px}
}
@media(prefers-reduced-motion:reduce){.ui-home-cue{animation:none}}

/* The mobile Explore sheet uses the same breadth as desktop. */
.ui-topbar-sheet-primary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:12px 4px}
.ui-topbar-sheet-primary .ui-topbar-sheet-link{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:6px;min-width:0;min-height:94px;padding:16px;border:1px solid var(--border,rgba(128,128,128,.3));border-radius:12px;background:color-mix(in srgb,var(--accent,#bd1830) 5%,transparent);white-space:normal}
.ui-topbar-sheet-description{font-size:12px;font-weight:400;line-height:1.4;opacity:.75}
.ui-topbar-sheet-more a{min-height:44px;align-content:center}
@media(min-width:700px){.ui-topbar-sheet-primary{grid-template-columns:repeat(4,minmax(0,1fr))}.ui-topbar-sheet-more{grid-template-columns:repeat(4,minmax(0,1fr))}}

/* 2026-10-14: shared navigation is plain clickable text and icons.
   Preserve the existing hit areas, avatar circles and unread badges. */
.ui-topbar :is(.ui-topbar-link,.ui-topbar-howbtn,.ui-topbar-pill,
  .ui-topbar-points,.ui-btn,.theme-toggle,.sfx-toggle,.ui-bell,
  .ui-topbar-lang,.ui-topbar-burger,.ui-topbar-settings,.ui-topbar-userpill,
  .db-locale-picker,.lang-picker.in-nav){
  border:0 !important;border-radius:0 !important;
  background:transparent !important;box-shadow:none !important;
}
.ui-topbar :is(a,button,select):focus-visible{
  outline:2px solid var(--accent,#ef4444);outline-offset:3px;
}
