/* ============================================================
   AI Plays Games — Central Brand Tokens
   ============================================================
   SINGLE SOURCE OF TRUTH for color, surface, accent, geometry, and shared
   typography tokens
   used by every public surface in this repo:
     - aiplaysgames.com  (aiplaysgames-site/)
     - aiju.gg           (aiju-site/)
    - donation pages    (tip-platform/tip_platform/, served by tip-platform Vercel)
    - OBS HUD widgets   (stream/hud/, served locally by the stream HUD server)

   ─────────────────────────────────────────────────────────────────────────
   UNBREAKABLE RULE FOR ALL FUTURE AGENTS — see AGENTS.md "PINNED RULE #3".
   ─────────────────────────────────────────────────────────────────────────
   1. NEVER hard-code a color hex, rgba(), or pixel radius in any other CSS
      file. Use the tokens declared here.
   2. Need a color/radius/surface that doesn't exist? ADD IT HERE first,
      with a comment naming where it's used, then reference the new token
      from your CSS. Token naming follows the patterns below.
   3. Per-brand differences (US vs CN) belong in the `body.brand-<id>`
      override blocks at the bottom of this file. Add new brands the same
      way — never branch by hard-coding values in site stylesheets.
   4. Shared typography font-family stacks live here too. Self-hosted @font-face
      declarations are defined in this file; consumers reference the --font-*
      tokens. Pages do NOT need separate Google Fonts <link> tags.
   ─────────────────────────────────────────────────────────────────────────

   How this file gets to all three sites:
    - It lives physically at tip-platform/public/static/brand.css inside the
       tip-platform Vercel deploy.
     - aiplaysgames-site/vercel.json and aiju-site/vercel.json rewrite
       /static/* to the tip-platform deploy, so <link href="/static/brand.css"> works
       transparently from aiplaysgames.com and aiju.gg too.
     - The donation page templates also load it from /static/brand.css.
     - Every page that loads brand.css MUST load it BEFORE its own
       style.css so per-page rules can override / consume the tokens.
   ============================================================ */

/* ============================================================
   Self-hosted web fonts
   ============================================================
   Files live at tip-platform/public/static/fonts/ and are served
   by the tip-platform Vercel deploy under /static/fonts/.
   Both aiplaysgames.com and the tip-platform pages reach them via
   the /static/* rewrite in aiplaysgames-site/vercel.json.

   Space Grotesk v22 — variable weight font (latin subset).
   A single .woff2 file covers weights 300–700; the font-weight
   range below matches the 400–700 range used by this project.

   Press Start 2P v16 — single-weight pixel display font (latin subset).
   ============================================================ */

/* Space Grotesk (latin, weights 400–700, variable font) */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/static/fonts/space-grotesk-v22-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Press Start 2P (latin, weight 400) */
@font-face {
  font-family: 'Press Start 2P';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/press-start-2p-v16-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: dark;

  /* ---- Surfaces ---------------------------------------------------------
     Solid panel colors used on cards, fieldsets, inputs, modals.
     Near-true-black neutral dark — committed to black rather than
    slate-blue-tinted. YouTube-TV exact palette: yt-spec-base-background
    for the page, yt-spec-raised-background for cards, additive-/menu-
    backgrounds for hover/nested. Keeps the gray hierarchy tight so the
    UI reads as one neutral system rather than stepped tiers. */
  --bg:                    #0f0f0f;     /* page background — yt-spec-base-background */
  --bg-grid:               #1a1a1a;     /* subtle gridded backdrop overlay */
  --bg-stream:             #000000;     /* video player bezel (intentional pure black) */
  /* SMPTE-style off-air color bars (tip_compact stream holder before embed loads). */
  --off-air-white:         #f0f0f0;
  --off-air-yellow:        #f0f000;
  --off-air-cyan:          #00f0f0;
  --off-air-green:         #00f000;
  --off-air-magenta:       #f000f0;
  --off-air-red:           #f00000;
  --off-air-blue:          #0000f0;
  --panel:                 #181818;     /* card / fieldset background — sits close to bg so cards feel embedded, not floating */
  --panel-2:               #202020;     /* nested surface (inputs, sub-cards) */
  --panel-hover:           #232323;     /* card hover state */
  --panel-stroke:          #232323;     /* card / input borders — barely visible, YouTube-style */
  --panel-stroke-strong:   #2f2f2f;     /* heavier dividers */

  /* ---- Translucent neutrals ---------------------------------------------
     For chrome on top of dark backgrounds (top bars, soft buttons, hover
     surfaces, hairlines). Use these instead of rgba(255,255,255,0.0X). */
  --surface-soft:          color-mix(in srgb, #ffffff 6%, transparent);
  --surface-soft-hover:    color-mix(in srgb, #ffffff 12%, transparent);
  --hairline:              color-mix(in srgb, #ffffff 6%, transparent);
  --shadow-ink:            #000000;     /* aiplaysgames.com modal/feed scrims and elevation shadows */

  /* ---- Text -------------------------------------------------------------
     YouTube-TV-exact: pure white primary text, mid-gray secondary. */
  --text:                  #ffffff;     /* primary text — yt-spec-text-primary */
  --text-muted:            #aaaaaa;     /* descriptions, captions, legend hints — yt-spec-text-secondary */

  /* ---- Typography -------------------------------------------------------
     Shared font stacks for the US public surfaces. Fonts are self-hosted
     under /static/fonts/ via the @font-face blocks below — no external
     Google Fonts requests needed. Consumers reference these tokens so
     aiplaysgames.com and the tip flow stay in lockstep. */
  --font-ui:               "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  --font-display:          "Press Start 2P", system-ui;
  --font-mono:             ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Mono stack tuned for box-drawing chars (▁▂▃▄▅▆▇█) used by the OBS HUD
     sparklines. ``--font-mono`` above is Apple-only and falls all the way
     to generic ``monospace`` on Windows, which on the streaming VMs ends
     up at Courier New — Courier New does not contain the lower-block
     glyphs, so Chromium per-glyph-substitutes to a wide proportional
     fallback and the "mono" font effectively isn't mono. Naming
     Cascadia Mono / Consolas explicitly keeps the spark advance width
     at the font's mono advance (~0.55em) so spark column widths are
     stable and identical between rows. */
  --font-mono-glyph:       "Cascadia Mono", "Cascadia Code", Consolas, "Courier New", monospace;

  /* ---- Brand accent -----------------------------------------------------
     Default = US (aiplaysgames). CN brand overrides via the
     body.brand-aiju block below. Keep these synced with
     tip-platform/tip_platform/config/streams.yaml::brands.<id>.accent_color.

     Soft / hairline tints (selected pill, focus ring, etc.) are derived
     inline at the consumer with color-mix(in srgb, var(--accent) N%, ...)
     — there is no --accent-soft token because the recipes vary per use
     site (12% vs 10% vs 8% backgrounds, etc.) and inlining keeps brand.css
     focused on raw, atomic values. */
  --accent:                #6bb94c;     /* shared gamer green action color on the YouTube-style black-gray shell */
  --accent-ink:            #0f0f0f;     /* legible dark text on solid green */

  /* ---- Tip amount tiers --------------------------------------------------
     Compact prompt-page amount pills only. Tiers map to preset slots 1–3
     ($3 / $5 / $10), then escalating energy on larger custom amounts.

     Narrative — the three preset slots read bronze / silver / gold ($3 / $5
     / $10). After gold, orbit opens at $25 with rich galaxy blue — the sole
     deep cool anchor before the hue walks hotter: legendary magenta at $50,
     plasma rose–red at $100 (no return to midnight indigo), solar ember amber
     at $250 capped with a golden flare rim, full prism ($500), white ($1000).
       1 bronze      ($3)    warm copper entry metal
       2 silver      ($5)    cool neutral mid metal
       3 gold        ($10)   warm lemon-tilt gold preset (distinct from bronze)
       4 blue        ($25)   rich galaxy blue — orbital floor / saturated entry
       5 magenta     ($50)   legendary voltage — blue→magenta→fuchsia rim
       6 plasma      ($100)  hot plasma rose (+ coral flare inner bloom)
       7 solar       ($250)  ember orange core → bright gold apex rim → prism next
       8 galaxy      ($500)  multi-hue cosmic prism
       9 white       ($1000) radiant transcendent cap (visual ceiling)

     Secondary hues: `--tip-tier-5-warmer` = third rim stop on tier-5 (fuchsia);
       `--tip-tier-6-ion` = hot coral inner bloom on tier-6 (legacy name);
       `--tip-tier-7-violet` = gold flare rim partner on tier-7 (legacy name).

     Each tier owns atomic tokens referenced from style-compact.css (tier-5 rim,
     tier-6 dual inset, tier-7 thermal bridge, galaxy prism tier 8). Pill does not escalate
     above tier 9 / $1000 (anti-dark-pattern guardrail). */
  --tip-tier-1-accent:      #c68642;     /* bronze — warm copper entry metal */
  --tip-tier-1-glow:        color-mix(in srgb, var(--tip-tier-1-accent) 24%, transparent);
  --tip-tier-1-sheen:       color-mix(in srgb, var(--tip-tier-1-accent) 48%, var(--text));
  --tip-tier-2-accent:      #b8c4d4;     /* silver — cool neutral mid metal */
  --tip-tier-2-glow:        color-mix(in srgb, var(--tip-tier-2-accent) 28%, transparent);
  --tip-tier-2-sheen:       color-mix(in srgb, var(--tip-tier-2-accent) 56%, var(--text));
  --tip-tier-3-accent:      #f2cc3f;     /* warmer coin gold — nudged toward lemon vs bronze-orange */
  --tip-tier-3-glow:        color-mix(in srgb, var(--tip-tier-3-accent) 26%, transparent);
  --tip-tier-3-sheen:       color-mix(in srgb, var(--tip-tier-3-accent) 56%, var(--text));
  --tip-tier-4-accent:      #3d7aeb;     /* rich galaxy blue ($25) — saturated orbital floor */
  --tip-tier-4-glow:        color-mix(in srgb, var(--tip-tier-4-accent) 34%, transparent);
  --tip-tier-4-sheen:       color-mix(in srgb, var(--tip-tier-4-accent) 64%, var(--text));
  --tip-tier-5-accent:      #ea45f8;     /* legendary magenta ($50) — voltage spike */
  /* Tier-5 rim third stop — hyper fuchsia apex (threads into prism wedge later) */
  --tip-tier-5-warmer:      #ec4899;
  --tip-tier-5-glow:        color-mix(in srgb, var(--tip-tier-5-accent) 32%, transparent);
  --tip-tier-5-sheen:       color-mix(in srgb, var(--tip-tier-5-accent) 62%, var(--text));
  --tip-tier-6-accent:      #f43f5e;     /* plasma rose ($100) — hot pink/red without cool purple rewind */
  /* Hot coral inner bloom on tier-6 pill (same CSS var name since launch; reads warm vs old indigo ion) */
  --tip-tier-6-ion:         #ff7358;
  --tip-tier-6-glow:        color-mix(in srgb, var(--tip-tier-6-accent) 34%, transparent);
  --tip-tier-6-sheen:       color-mix(in srgb, var(--tip-tier-6-accent) 64%, var(--text));
  --tip-tier-7-accent:      #f97316;     /* solar ember ($250) — orange thermal peak before prism */
  /* Bright gold apex on tier-7 gradient rim (--tip-tier-7-violet kept for stylesheet compat) */
  --tip-tier-7-violet:      #fbbf24;
  --tip-tier-7-glow:        color-mix(in srgb, var(--tip-tier-7-accent) 28%, transparent);
  --tip-tier-7-sheen:       color-mix(in srgb, var(--tip-tier-7-accent) 60%, var(--tip-tier-7-violet));
  --tip-tier-8-accent:      #a78bfa;     /* galaxy anchor — multi-hue conic rim lives here */
  --tip-tier-8-violet:      #818cf8;     /* indigo wedge */
  --tip-tier-8-cyan:        #22d3ee;     /* cyan caustic wedge */
  --tip-tier-8-magenta:     #ec4899;     /* magenta wedge that closes the loop back to violet */
  --tip-tier-8-glow:        color-mix(in srgb, var(--tip-tier-8-accent) 30%, transparent);
  --tip-tier-8-sheen:       color-mix(in srgb, var(--tip-tier-8-cyan) 50%, var(--tip-tier-8-accent));
  --tip-tier-9-accent:      #ffffff;     /* white holiness — radiant ceiling */
  --tip-tier-9-warm:        #fff6d6;     /* faint warm-white undertone */
  --tip-tier-9-violet:      #c4b5fd;     /* faint violet undertone, keeps it from feeling cold */
  --tip-tier-9-glow:        color-mix(in srgb, var(--tip-tier-9-warm) 34%, transparent);
  --tip-tier-9-sheen:       color-mix(in srgb, var(--tip-tier-9-warm) 62%, var(--text));

  /* ---- Stream overlay username + donor rank palette ----------------------
     Chat usernames, donor popup names, and donor rank accents share the
     full tip-tier escalation ramp (metals → galaxy → transcendent white).
     Slot 0 stays brand green — chat-overlay.js calibrates "anonymous" to
     this index. Slots 1–11 sample the tier ladder; no new hex here. */
  --stream-username-color-0:  var(--accent);
  --stream-username-color-1:  var(--tip-tier-1-accent);
  --stream-username-color-2:  var(--tip-tier-2-accent);
  --stream-username-color-3:  var(--tip-tier-3-accent);
  --stream-username-color-4:  var(--tip-tier-4-accent);
  --stream-username-color-5:  var(--tip-tier-5-accent);
  --stream-username-color-6:  var(--tip-tier-6-accent);
  --stream-username-color-7:  var(--tip-tier-7-accent);
  --stream-username-color-8:  var(--tip-tier-8-accent);
  --stream-username-color-9:  var(--tip-tier-8-cyan);
  --stream-username-color-10: var(--tip-tier-8-magenta);
  --stream-username-color-11: var(--tip-tier-9-warm);
  --chat-name-color-0:  var(--stream-username-color-0);
  --chat-name-color-1:  var(--stream-username-color-1);
  --chat-name-color-2:  var(--stream-username-color-2);
  --chat-name-color-3:  var(--stream-username-color-3);
  --chat-name-color-4:  var(--stream-username-color-4);
  --chat-name-color-5:  var(--stream-username-color-5);
  --chat-name-color-6:  var(--stream-username-color-6);
  --chat-name-color-7:  var(--stream-username-color-7);
  --chat-name-color-8:  var(--stream-username-color-8);
  --chat-name-color-9:  var(--stream-username-color-9);
  --chat-name-color-10: var(--stream-username-color-10);
  --chat-name-color-11: var(--stream-username-color-11);
  /* Topper donor carousel (#1–#5) — epic ladder top (tier 9 → tier 5). */
  --topper-donor-rank-1-color: var(--tip-tier-9-warm);
  --topper-donor-rank-2-color: var(--tip-tier-8-accent);
  --topper-donor-rank-3-color: var(--tip-tier-7-accent);
  --topper-donor-rank-4-color: var(--tip-tier-6-accent);
  --topper-donor-rank-5-color: var(--tip-tier-5-accent);
  /* BEST DONORS bento rail (top 3 lifetime) — spread across epic + gold. */
  --hud-donor-rank-1-color: var(--tip-tier-7-accent);
  --hud-donor-rank-2-color: var(--tip-tier-5-accent);
  --hud-donor-rank-3-color: var(--tip-tier-3-accent);

  /* ---- Status ----------------------------------------------------------- */
  --danger:                #f27272;     /* error toasts, validation */
  --warn:                  #3b2e12;     /* warning banner background (e.g. Stripe test-mode banner) */
  --warn-fg:               #ffd27a;     /* warning banner text — derive --warn-stroke and --warn-soft via color-mix() at the consumer */

  /* ---- Third-party brand marks -----------------------------------------
     Brand colors of third-party services that appear as text or marks on
     our pages (Stripe wordmark, etc.). Treated as canonical tokens for
     those brands — same exception precedent as the Anthropic-orange
     Claude icon in the brand-icon block below. Add new ones here, never
     hard-code a third-party brand color in a site stylesheet. */
  --stripe-brand:          var(--text-muted); /* tip checkout Stripe wordmark — matches Powered by */
  --model-claude:          #d97757;     /* Anthropic / Claude chip accent */
  --model-chatgpt:         #10a37f;     /* OpenAI / ChatGPT chip accent */
  /* Chess lane trophies + donation amounts — 3-stop ramps tuned for --bg (#0f0f0f).
     Stops stay above ~L*55 so gradient text/icons never read as black/transparent. */
  --model-claude-trophy-from: #ffd9cc;  /* Anthropic peach highlight */
  --model-claude-trophy-mid:  #f0a88a;  /* soft coral */
  --model-claude-trophy-to:   #e8956f;  /* warm accent (lighter than --model-claude) */
  --model-chatgpt-trophy-from: #b8f5e4; /* OpenAI mint highlight */
  --model-chatgpt-trophy-mid:  #5ee0b8; /* bright teal */
  --model-chatgpt-trophy-to:   #2ec49a; /* brand green, dark-bg safe */
  --model-kimi:            #6f7cff;     /* Moonshot Kimi chip accent */
  --model-kimi-trophy-from: #b8c2ff;
  --model-kimi-trophy-mid:  #6f7cff;
  --model-kimi-trophy-to:   #4a52b8;
  --model-gemini:          #4da3ff;     /* Google Gemini chip accent — blue/teal, distinct from ChatGPT green */
  --model-gemini-trophy-from: #9fd4ff;
  --model-gemini-trophy-mid:  #4da3ff;
  --model-gemini-trophy-to:   #1e6bb8;
  --model-deepseek:        #2563eb;     /* DeepSeek chip accent — deep blue */
  --model-deepseek-trophy-from: #93b4f9;
  --model-deepseek-trophy-mid:  #2563eb;
  --model-deepseek-trophy-to:   #1e3a8a;
  --model-grok:            #d4d4d8;     /* xAI Grok chip accent — silver on dark stream bg */
  --model-grok-trophy-from: #f4f4f5;
  --model-grok-trophy-mid:  #d4d4d8;
  --model-grok-trophy-to:   #71717a;
  --model-mistral:         #f97316;     /* Mistral chip accent — orange/coral brand */
  --model-mistral-trophy-from: #fdba74;
  --model-mistral-trophy-mid:  #f97316;
  --model-mistral-trophy-to:   #c2410c;
  --model-qwen:            #a855f7;     /* Alibaba Qwen chip accent — violet (optional tier C) */
  --model-qwen-trophy-from: #d8b4fe;
  --model-qwen-trophy-mid:  #a855f7;
  --model-qwen-trophy-to:   #6b21a8;

  /* ---- Chess board (stream mock + chess scene) ------------------------- */
  --chess-board-light:     #e8d8a8;     /* chess mock / agent chess scene light squares */
  --chess-board-dark:      #6f8e5a;     /* chess mock / agent chess scene dark squares */
  --chess-board-light-hl:  #e5c038;     /* last-move highlight on light squares — goldenrod highlighter */
  --chess-board-dark-hl:   #b8c928;     /* last-move highlight on dark squares — chartreuse on olive */
  --chess-piece-shadow-w:  #1a1a1a;     /* white-piece outline shadow */
  --chess-piece-shadow-b:  #ffffff;     /* black-piece outline shadow */

  /* ---- Geometry --------------------------------------------------------- */
  --radius-xs:             4px;         /* tiny controls, code pills, scrollbar thumbs */
  --radius-sm:             6px;         /* inputs, pills, small buttons */
  --radius:                10px;        /* cards, fieldsets */
  --radius-lg:             12px;        /* large feature cards */
  --radius-pill:           999px;       /* fully rounded floating pills */
  --brand-header-height:   48px;        /* shared fixed top-bar height across homepage + tip pages */
  --brand-header-padding-x: 12px;       /* shared horizontal gutter for header lockup */
  --brand-header-padding-x-desktop: 16px; /* desktop gutter keeps logo rhythm consistent */
  --brand-header-gap:      12px;        /* preserved for any per-brand lockup that pairs a logo mark with a wordmark span */
  --brand-header-logo-height: 28px;     /* AIPG type-stack in 48px top-bar */
  --brand-header-logo-offset-y: 0px;    /* no vertical offset */

  /* ---- OBS HUD / widget tokens ------------------------------------------
     Shared by stream/hud/*.html via /static/brand.css + /hud-theme.css.
     These preserve the existing GitHub-terminal palette used on stream while
     keeping raw colors/radii centralized in this file. */
  --hud-bg:                 #000000;
  --hud-text:               #e6edf3;
  --hud-muted:              #7d8590;
  --hud-dim:                #3d444d;
  --hud-line:               #21262d;
  --hud-surface-soft:       #0d1117;
  --hud-ice:                #79c0ff;
  --hud-cyan:               #56d4dd;
  --hud-amber:              #f0b429;
  --hud-good:               var(--accent); /* live/good states use the shared gamer green */
  --hud-danger:             #f85149;
  --hud-violet:             #bc8cff;
  /* Medal podium tokens. ``--hud-rank-2`` (silver) + ``--hud-rank-3``
     (bronze) anchor the BEST DONORS bento rail — slightly muted because
     they're rendered behind a flex bar chart on a black panel. The
     ``--hud-gold`` / ``--hud-silver-bright`` / ``--hud-bronze-bright``
     trio added 2026-05-22 carry the **topper donor carousel** podium
     (small 11px text on the brand chip, where the bento-rail muted
     variants blended into ``--text``). The yellow gold is the canonical
     CSS ``gold`` ramped slightly warmer; bright silver pushes silver-
     blue closer to white-shimmer; bright bronze brings copper saturation
     up so the metal reads as warm-orange rather than mud-brown. */
  --hud-gold:               #ffcf3a;
  --hud-silver-bright:      #e0e6ed;
  --hud-bronze-bright:      #e09b5b;
  --hud-rank-2:             #b1bac4;
  --hud-rank-3:             #a87543;
  --hud-radius-chip:        2px;
  --hud-radius-box:         3px;
  --hud-font-mono:          var(--font-ui); /* OBS widgets use the same body face as the public site */
  --hud-font-spark:         var(--font-mono-glyph); /* true mono for the box-drawing sparkline glyphs only */

  /* JC OBS HUD site lockup (index.html?hud_header=brand) — scaled for 340px rail.
     The lockup is wordmark-only as of 2026-05-21 (the retired green
     controller mark is gone). The wordmark-offset-y is preserved for any
     future surface that pairs the wordmark with a logo mark and needs to
     pull the Press Start 2P glyph down to optical center; the logo-height
     and gap tokens are inert in the JC HUD today but remain available so
     a per-brand override can re-enable an icon next to the wordmark
     without re-deriving these numbers. */
  --hud-brand-lockup-logo-height:        32.34px;  /* +10% then +5% on 2026-05-12 (28px → 30.8px → 32.34px); inert in JC HUD lockup */
  --hud-brand-lockup-wordmark-px:        16.17px;  /* +10% then +5% on 2026-05-12 (14px → 15.4px → 16.17px) */
  --hud-brand-lockup-gap:                10px;
  --hud-brand-lockup-wordmark-offset-y:  3px;
}

/* ============================================================
   Light mode (public site + tip pages)
   ============================================================
   Production ships dark only (``color-scheme-init.js`` sets
   ``data-color-scheme="dark"``). To preview light again, set on ``<html>``:
     data-color-scheme="light"   — light surfaces/text (dormant tokens below)
     data-color-scheme="auto"    — follow prefers-color-scheme when set

   Only remap the neutral shell (surfaces, text, chrome, status banners).
   --accent, tip-tier ramps, model chip hues, and OBS --hud-* tokens stay
   as declared in :root so pills, stream bezels, and HUD overlays stay
   on-brand. Light header uses ``/static/aiplaysgames-logo-light.svg`` (white
   tile, #0f0f0f type, hairline stroke); dark uses ``/static/aiplaysgames-logo.svg``.
   Regenerate both via ``operator/scripts/generate-brand-icons.py``.

   When re-enabling light, bump <meta name="theme-color"> to match --bg
   (light: #f4f4f4). HUD pages should not set data-color-scheme="light".

   Light hierarchy (Material / Apple / YouTube-light pattern — NOT a mirror
   of dark): --bg is an off-white canvas; --panel is #fff elevated content;
   --surface-soft is a subtle control tint on the canvas. Pair white panels
   with --panel-stroke borders on schedule/social chips (see style.css).
   ============================================================ */

@media (prefers-color-scheme: light) {
  :root[data-color-scheme="auto"] {
    color-scheme: light;
    --bg:                    #f4f4f4;     /* canvas — off-white, not mid-gray */
    --bg-grid:               #ececec;     /* schedule grid wash */
    --panel:                 #ffffff;     /* elevated cards / chips */
    --panel-2:               #f5f5f5;     /* nested inputs */
    --panel-hover:           #fafafa;
    --panel-stroke:          #e3e3e3;     /* hairline borders on white panels */
    --panel-stroke-strong:   #d4d4d4;
    --surface-soft:          #ededed;     /* tertiary chrome on canvas */
    --surface-soft-hover:    #e5e5e5;
    --hairline:              #e3e3e3;
    --text:                  #0f0f0f;     /* primary — same ink as dark --accent-ink */
    --text-muted:            #606060;     /* secondary */
    --stripe-brand:          var(--text-muted);
    --warn:                  #fff4d6;     /* test-mode / caution banner fill */
    --warn-fg:               #7a5a12;     /* banner text */
  }
}

:root[data-color-scheme="light"] {
  color-scheme: light;

  --bg:                    #f4f4f4;
  --bg-grid:               #ececec;
  --panel:                 #ffffff;
  --panel-2:               #f5f5f5;
  --panel-hover:           #fafafa;
  --panel-stroke:          #e3e3e3;
  --panel-stroke-strong:   #d4d4d4;
  --surface-soft:          #ededed;
  --surface-soft-hover:    #e5e5e5;
  --hairline:              #e3e3e3;
  --text:                  #0f0f0f;
  --text-muted:            #606060;
  --stripe-brand:          var(--text-muted);
  --warn:                  #fff4d6;
  --warn-fg:               #7a5a12;
}

/* Highlighted text: accent wash + --accent-ink (dark on green; WebKit needs
   -webkit-text-fill-color or selection text can ignore `color`). */
::selection {
  background-color: var(--accent);
  color: var(--accent-ink);
  -webkit-text-fill-color: var(--accent-ink);
}

::-moz-selection {
  background-color: var(--accent);
  color: var(--accent-ink);
}

/* ============================================================
   Shared Header Brand Lockup
   ============================================================
   The homepage, site subpages, and tip pages share these exact selectors
   (.top-bar, .brand, .brand-logo, .brand-wordmark). Keeping them here
   prevents the separate site stylesheets from drifting.

   HTML contract (copy from HEADER-LOCKUP.snippet.html in this directory):
     - Logo-only top bar: <a class="brand brand--mark-only"> + .brand-logo
       (no .brand-wordmark sibling).
     - Do NOT add per-page .top-bar / .brand-logo rules in style.css,
       subpage.css, or tip templates — only tokens in :root above.
     - Bump ?v= on brand.css + logo SVG together when lockup CSS changes.
   ============================================================ */

.top-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--top-bar-h, var(--brand-header-height));
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--brand-header-padding-x);
  background: var(--bg);
  border-bottom: 1px solid var(--hairline);
}

/* Prompt pages (tip.html / tip_compact.html) — the header sits directly
   above the stream embed and the hairline reads as visual noise between
   the two surfaces. Homepage / terms / thanks keep the hairline. */
body.prompt-body .top-bar {
  border-bottom: none;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--brand-header-gap);
  color: var(--text);
  text-decoration: none;
  flex-shrink: 0;
}

/* Press Start 2P wordmark typography — only when a wordmark span is present.
   Logo-only headers must use .brand--mark-only (or omit .brand-wordmark) so
   they never inherit this line-height box (was shifting the AIPG mark). */
.brand:has(.brand-wordmark) {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 2.2;
  word-spacing: -0.45em;
  white-space: nowrap;
}

.brand.brand--mark-only,
.brand:not(:has(.brand-wordmark)) {
  gap: 0;
  line-height: 1;
  font-size: 0;
}

.brand-logo {
  height: var(--brand-header-logo-height);
  width: auto;
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  object-fit: contain;
  transform: translateY(var(--brand-header-logo-offset-y));
}

.brand-wordmark {
  display: inline-block;
}

/* stream/hud/index.html — optional site header lockup (JC JCHUDBrowser only) */
#ksp-hud[data-hud-header="brand"] .hud-brand-lockup.brand {
  gap: var(--hud-brand-lockup-gap);
  font-size: var(--hud-brand-lockup-wordmark-px);
  line-height: 1.25;
  letter-spacing: 0.02em;
  word-spacing: -0.45em;
  color: var(--hud-color-text);
  font-family: var(--font-display);
  font-weight: 400;
  text-decoration: none;
  white-space: nowrap;
}
#ksp-hud[data-hud-header="brand"] .hud-brand-lockup .brand-logo {
  height: var(--hud-brand-lockup-logo-height);
  width: auto;
  flex-shrink: 0;
  display: block;
  transform: translateY(0);
}
#ksp-hud[data-hud-header="brand"] .hud-brand-lockup .brand-wordmark {
  display: inline-block;
  transform: translateY(var(--hud-brand-lockup-wordmark-offset-y));
}

@media (min-width: 720px) {
  .top-bar {
    padding: 0 var(--brand-header-padding-x-desktop);
  }
}

@media (max-width: 520px), (max-height: 380px) {
  #ksp-hud[data-hud-header="brand"] .hud-brand-lockup.brand {
    font-size: 13.86px;  /* +10% then +5% on 2026-05-12 (12px → 13.2px → 13.86px) */
    gap: 8px;
  }
  #ksp-hud[data-hud-header="brand"] .hud-brand-lockup .brand-logo {
    height: 27.72px;  /* +10% then +5% on 2026-05-12 (24px → 26.4px → 27.72px) */
  }
  /* Press Start 2P's glyph sits high inside its EM box; the offset stays
     near 1px across the compact range (9-12px) because the bias is mostly
     a fixed pixel offset, not a proportional one. */
  #ksp-hud[data-hud-header="brand"] .hud-brand-lockup .brand-wordmark {
    transform: translateY(1px);
  }
}

/* ============================================================
   Per-brand overrides
   ============================================================
   Apply by setting <body class="brand-<id>"> in the page that loads this
   file. The donation page templates (tip.html, thanks.html) already do
   this from streams.yaml::brand.id; aiju.gg's landing page sets it
   directly; aiplaysgames.com uses the :root defaults (no class needed).

   Adding a new brand:
     1. Append a `body.brand-<id>` block below.
     2. Add the matching brand entry under `brands:` in
        tip-platform/tip_platform/config/streams.yaml.
     3. Keep the accent_color in streams.yaml in sync with --accent here.
   ============================================================ */

body.brand-aiju, .brand-aiju {
  --accent:                #6bb94c;     /* shared gamer green action color on the YouTube-style black-gray shell */
  --accent-ink:            #0f0f0f;     /* dark text reads cleanly on jade green */
}


/* ============================================================
   Brand icon system
   ============================================================
   Mask-based monochrome icons that inherit `currentColor`. The SVG
   files at /icons/<name>.svg were normalized so they paint as a
   single shape; we re-tint them via `mask-image` so a single asset
   can render in any context (white on dark cards, accent-colored
   on hover, brand-orange for Anthropic, etc.).

   Why mask-image and not <img>? `<img>` SVGs ignore the parent's
   `color`, so we can't restyle them per-context. Mask-image makes
   the icon a coloured silhouette of the SVG's union-of-paths,
   which is exactly what we want for square brand marks.

   Usage:
     <span class="brand-icon" data-icon="claude" aria-hidden="true"></span>
       <h2 class="card-title">Claude plays Kerbal Space Program</h2>

  Two render modes are supported:

  • Mono (default) — paints `--brand-icon-url` as a silhouette via
    mask-image, tinted by `color`. Use for clean single-shape logos
    (Claude, ChatGPT, KSP, Factorio, chess piece, etc.).

  • Image — paints the asset directly via `background-image`, mask
    disabled. Use when a logo needs its original colors / multi-tone
    art (Stardew sprite, Kimi rounded square, FM crest, Go board).
    See the "Full-color icons" block below for the opt-in pattern.

  Icon names map 1:1 to the file under public/icons/. Add a new
  mono icon by (a) dropping a square SVG into public/icons/<name>.svg
  (currentColor fills, see public/icons/_normalize.py), and
  (b) appending a `[data-icon="<name>"]` rule to the mono block.

  Add a brand-color override (e.g. Anthropic's rust orange) by
  declaring `color: <hex>` on that mono rule — `currentColor`
  flowing into the mask paints the icon in that hue. ALL these
  hexes are official brand colors and are the only place in this
  file allowed to bypass the token system, since they ARE the
  tokens for those brands.
   ============================================================ */

.brand-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  vertical-align: -0.18em;
  background-color: currentColor;
  -webkit-mask-image: var(--brand-icon-url, none);
          mask-image: var(--brand-icon-url, none);
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: contain;
          mask-size: contain;
}

/* ------------------------------------------------------------------
   Mono icons (mask mode)
   Single-color silhouettes that inherit `currentColor`. Optimal for
   logos that read as a clean shape and want to recolor per-context
   (Claude orange, white-on-dark for ChatGPT, etc.).
   ------------------------------------------------------------------ */
.brand-icon[data-icon="claude"]           { --brand-icon-url: url("/icons/claude.svg");           color: #d97757; }
.brand-icon[data-icon="chatgpt"]          { --brand-icon-url: url("/icons/chatgpt.svg");          color: var(--text); }
.brand-icon[data-icon="ksp"]              { --brand-icon-url: url("/icons/ksp.svg");              color: var(--text); }
.brand-icon[data-icon="chess"]            { --brand-icon-url: url("/icons/chess.svg");            color: var(--text); }
.brand-icon[data-icon="just-chatting"]    { --brand-icon-url: url("/icons/just-chatting.svg");    color: var(--text); }
.brand-icon[data-icon="chinese-parents"]  { --brand-icon-url: url("/icons/chinese-parents.svg");  color: var(--text); }
.brand-icon[data-icon="hitman"]           { --brand-icon-url: url("/icons/hitman.svg");           color: var(--text); }
.brand-icon[data-icon="twitch"]           { --brand-icon-url: url("/icons/twitch.svg");           color: #9146ff; }
.brand-icon[data-icon="kick"]             { --brand-icon-url: url("/icons/kick.svg");             color: #53fc18; }
.brand-icon[data-icon="map"]              { --brand-icon-url: url("/icons/map.svg");              color: var(--text); }
.brand-icon[data-icon="send"]             { --brand-icon-url: url("/icons/send.svg");             color: var(--text); }

/* ------------------------------------------------------------------
   Full-color icons (image mode)
   Some brand marks (game crests, multi-tone product logos) lose their
   identity when flattened to a silhouette — the FM crest is two-tone,
   Stardew's sprite is illustrative, the Kimi logo is a rounded square
   with embedded type, and the Go board is a textured photo-real piece.
   For these we paint the asset directly via background-image and turn
   off the mask-image colour fill. The .brand-icon shell still gives us
   sizing + flex alignment + vertical centering.

   To opt an icon into image mode: declare its rule under this block
   instead of the mono block, and reference any vector OR raster file
   under /icons/<name>.{svg,png}.
   ------------------------------------------------------------------ */
.brand-icon[data-icon="kimi"],
.brand-icon[data-icon="stardew"],
.brand-icon[data-icon="football-manager"],
.brand-icon[data-icon="factorio"],
.brand-icon[data-icon="minecraft"],
.brand-icon[data-icon="go"] {
  background-color: transparent;
  -webkit-mask-image: none;
          mask-image: none;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}
.brand-icon[data-icon="kimi"]             { background-image: url("/icons/kimi.png"); }
.brand-icon[data-icon="stardew"]          { background-image: url("/icons/stardew.png"); }
.brand-icon[data-icon="football-manager"] { background-image: url("/icons/football-manager.svg"); }
.brand-icon[data-icon="factorio"]         { background-image: url("/icons/factorio.svg"); }
/* Minecraft grass block: green grass top + brown dirt body needs the
   raw fills painted, the mono mask flattens it to a featureless
   square. */
.brand-icon[data-icon="minecraft"]        { background-image: url("/icons/minecraft.svg"); }
.brand-icon[data-icon="go"]               { background-image: url("/icons/go.png"); }

/* Sizing modifiers --------------------------------------------------- */
.brand-icon--lg { width: 1.4em;  height: 1.4em;  vertical-align: -0.32em; }
.brand-icon--xl { width: 28px;   height: 28px;   vertical-align: middle; }  /* fits inside 44px stream-head avatar */
