/* JakeCrate platform styles — tokens, buttons, lobby, podium, reveal, TV, kit, shared overlays.
   Carved from public/index.html (Stage 1 monolith split). Load FIRST, before game sheets. */
        /* Display font is BUNDLED (public/vendor/fonts/, OFL — see vendor/ATTRIBUTION.md),
           not Google-hosted: offline hotspot parties used to silently fall back to
           monospace because the fonts.googleapis.com link never resolved. Same family
           name, so every var(--font-display) usage and the canvas literals still work. */
        @font-face {
            font-family: 'Press Start 2P';
            font-style: normal;
            font-weight: 400;
            font-display: swap;
            src: url('/vendor/fonts/press-start-2p.woff2') format('woff2');
        }
        /* Playtest overhaul (2026-07-13): Bungee = new display font (arcade signage,
           Jake's pick from tools/mock/visual-direction.html), Nunito = body font.
           Press Start 2P stays bundled — canvas draw calls still name it directly. */
        @font-face {
            font-family: 'Bungee'; font-style: normal; font-weight: 400; font-display: swap;
            src: url('/vendor/fonts/bungee.woff2') format('woff2');
        }
        /* v2 correction (Jake's second feedback round): ONE bouncy display font PER
           GAME — Bungee stays for Sleight of Hands; the others get their own face
           via --font-display under body[data-game]. Body text stays Nunito. */
        @font-face {
            font-family: 'Baloo 2'; font-style: normal; font-weight: 800; font-display: swap;
            src: url('/vendor/fonts/baloo2.woff2') format('woff2');
        }
        @font-face {
            font-family: 'Shrikhand'; font-style: normal; font-weight: 400; font-display: swap;
            src: url('/vendor/fonts/shrikhand.woff2') format('woff2');
        }
        @font-face {
            font-family: 'Luckiest Guy'; font-style: normal; font-weight: 400; font-display: swap;
            src: url('/vendor/fonts/luckiest.woff2') format('woff2');
        }
        @font-face {
            font-family: 'Titan One'; font-style: normal; font-weight: 400; font-display: swap;
            src: url('/vendor/fonts/titan-one.woff2') format('woff2');
        }
        @font-face {
            font-family: 'Nunito'; font-style: normal; font-weight: 400; font-display: swap;
            src: url('/vendor/fonts/nunito-400.woff2') format('woff2');
        }
        @font-face {
            font-family: 'Nunito'; font-style: normal; font-weight: 700; font-display: swap;
            src: url('/vendor/fonts/nunito-700.woff2') format('woff2');
        }
        *, *::before, *::after { box-sizing: border-box; }
        body, html { margin:0; padding:0; width:100%; height:100%; background:#050508; overflow:hidden; font-family:'Nunito',system-ui,sans-serif; overscroll-behavior:none; touch-action:none; }

        /* ── Design tokens + button system ─────────────────────────────────────
           Exactly three button weights. Every screen gets ONE .btn-primary (the
           single thing the player should do next); everything else is secondary
           or quiet. New/migrated UI should use these instead of inline styles. */
        :root {
            /* Theme tokens — the Workshop editor (workshop/, local dev only) can
               retint every one of these live via the 'themeVars' socket event;
               committed overrides ride in config/tunables.json (theme section). */
            --c-card:#0d1525; --c-border:#2a3450;
            /* ink3 raised from #4a6a8a — hints/placeholders now clear 4.5:1 on the dark grounds */
            --c-ink:#fff; --c-ink2:#9fb0cc; --c-ink3:#8296b8;
            --c-brand:#ffeb3b; --c-danger:#c62828;
            --c-hot:#ff6600;   /* battle orange (VS, timers, round banners) */
            --c-gold:#ffd700;  /* winner gold */
            --c-mint:#8fa;     /* progress/status mint */
            /* ── Portal palette (lobby identity) — the Spawnpoint "Rising Ember" anchors.
               Coral + teal lead; amber is a sparing spark accent; ground is the blue-black.
               Scoped to the lobby chrome + wordmark + hero; not a repo-wide reskin. */
            --portal-coral:#FF5D73; --portal-teal:#35E0C8; --portal-amber:#FFCF5C; --portal-ground:#0A0F1C;
            --font-display:'Bungee', 'Press Start 2P', monospace;
            /* Scale tokens (lobby reskin) — radius/shadow/spacing route through these */
            --radius:14px; --radius-sm:10px;
            --shadow-1:0 2px 10px rgba(0,0,0,.35); --shadow-2:0 10px 30px rgba(0,0,0,.45);
            --focus-ring:3px solid var(--c-brand);
        }
        .btn { border:none; cursor:pointer; font-weight:800; letter-spacing:.04em; border-radius:12px; -webkit-tap-highlight-color:transparent; font-family:inherit; flex-grow:0; text-transform:uppercase; }
        .btn:disabled { opacity:.4; }
        .btn-danger { color:var(--c-danger) !important; border-color:rgba(198,40,40,.5) !important; }
        .btn-primary { background:var(--c-brand); color:#090b12; padding:16px 22px; font-size:1em; }
        .btn-secondary { background:var(--c-card); color:var(--c-ink2); border:1.5px solid var(--c-border); padding:11px 18px; font-size:.8em; }
        .btn-quiet { background:transparent; color:var(--c-ink3); padding:8px 12px; font-size:.8em; }
        .btn-quiet:active, .btn-secondary:active { filter:brightness(1.35); }
        .btn-secondary.btn-active { background:rgba(94,230,197,.15); border-color:#5ee6c5; color:#5ee6c5; }
        canvas { display:block; touch-action:none; cursor:crosshair; }
        #global-leave { display:none; position:fixed; top:calc(env(safe-area-inset-top) + 6px); left:6px; z-index:250; background:rgba(198,40,40,0.82); color:#fff; border:none; border-radius:8px; padding:6px 10px; font-size:0.7em; font-weight:bold; letter-spacing:1px; cursor:pointer; -webkit-user-select:none; user-select:none; }
        #global-host-lobby { display:none; position:fixed; top:calc(env(safe-area-inset-top) + 6px); right:6px; z-index:250; background:rgba(255,235,59,0.88); color:#111; border:none; border-radius:8px; padding:6px 10px; font-size:0.7em; font-weight:bold; letter-spacing:1px; cursor:pointer; -webkit-user-select:none; user-select:none; }

        /* ── Per-game identity (playtest overhaul, 2026-07-13) ─────────────────
           While a game runs, jcApplyGameTheme() sets body[data-game] and each
           game re-tints --c-brand + gets a signature backdrop. Split Crew is
           LOCKED as-is per Jake's playtest notes — no override on purpose.
           Palettes: tools/mock/visual-direction.html, variant A everywhere
           except Squiggle Fight (ships dark "Neon Versus" B — light A needs a
           dedicated contrast pass before it's safe on this dark-baseline UI). */
        body[data-game="tacostealth"]   { --c-brand:#ffb648; --font-display:'Bungee', sans-serif; background:radial-gradient(circle at 50% 8%,#1b2b21,#0d1512 78%); }
        /* v2 correction: PikPic + Snap Chain go LIGHT (Jake: "not everything dark").
           Token-level flip — inside these scopes the ink/card/border tokens invert,
           so token-driven children restyle themselves; the handful of hardcoded
           dark-ground accents get explicit overrides just below. */
        body[data-game="pikpic"] {
            /* Reconciled 2026-07-16 (Jake: "I don't like the blue") — PikPic's ONE accent
               is the coral its lobby card always had; the cream album ground stays. */
            --c-brand:#ff6242; --font-display:'Baloo 2', sans-serif;
            --c-card:#fffdf6; --c-border:#ddd3c0;
            --c-ink:#28251f; --c-ink2:#5a5346; --c-ink3:#8a8172;
            --c-gold:#a8731f; /* gold timers/badges need a darker amber on cream */
            background:radial-gradient(circle at 50% 8%,#f1ece2,#e7e0d2 78%);
        }
        body[data-game="pikpic"] #pp-upload-screen, body[data-game="pikpic"] #pp-clue-screen,
        body[data-game="pikpic"] #pp-wait-screen, body[data-game="pikpic"] #pp-submit-screen,
        body[data-game="pikpic"] #pp-vote-screen, body[data-game="pikpic"] #pp-result-screen {
            background:radial-gradient(circle at 50% 20%,#f1ece2,#e2dac8 70%); color:#28251f;
        }
        body[data-game="pikpic"] .pp-timer-big { text-shadow:none; }
        body[data-game="pikpic"] .pp-clue-display { background:rgba(255,98,66,.08); border-color:rgba(255,98,66,.3); }
        body[data-game="pikpic"] .btn-primary { color:#fffdf7; }
        body[data-game="coolquip"]      { --c-brand:#ffc94b; --font-display:'Shrikhand', serif; background:radial-gradient(circle at 50% 8%,#261440,#160e24 78%); }
        body[data-game="squiggle"] {
            --c-brand:#e8336d; --font-display:'Luckiest Guy', sans-serif;
            --c-card:#fffdf6; --c-border:#d9d2bf;
            --c-ink:#2b2b31; --c-ink2:#585349; --c-ink3:#8b8577;
            --c-gold:#a8731f;
            background:radial-gradient(circle at 50% 8%,#f5f2e9,#eae6d8 78%);
        }
        body[data-game="squiggle"] #so-screen { background:#efeadd; }
        body[data-game="squiggle"] #sq-battle-screen { background:#efeadd; color:#2b2b31; }
        body[data-game="squiggle"] .sq-panel canvas { background:#f5f2e9; border-color:#cfc7b2; }
        body[data-game="squiggle"] .sq-vote-btn { background:rgba(0,0,0,0.05); border-color:#b9b09a; color:#2b2b31; }
        body[data-game="squiggle"] #sq-results-screen { background:rgba(243,239,229,0.97); color:#2b2b31; }
        body[data-game="squiggle"] #so-timer { text-shadow:none; }
        body[data-game="telestrations"] {
            --c-brand:#d81b7a; --font-display:'Titan One', sans-serif;
            --c-mint:#0aa6c9;
            --c-card:#fffdf6; --c-border:#e0d4be;
            --c-ink:#38292f; --c-ink2:#6b5560; --c-ink3:#95808a;
            --c-gold:#a8731f;
            background:radial-gradient(circle at 50% 8%,#f7f1e6,#eee5d2 78%);
        }
        body[data-game="telestrations"] #kit-screen { background:radial-gradient(circle at 50% 10%,#f7f1e6,#eae1cd 70%); }
        body[data-game="telestrations"] .kit-item-card { background:#fffdf6; border-color:#e0d4be; }
        body[data-game="telestrations"] .kit-magnet.chosen { color:#fff; box-shadow:0 0 14px rgba(216,27,122,.35); }
        body[data-game="telestrations"] .btn-primary { color:#fffdf7; }
        /* Lobby cards preview each game's font via inline --gf from JC_GAMES (renderGameShelf) */

        /* Title card — every game opens on a ~4s intro so everyone knows what
           they're playing (jcMaybeTitleCard shows it once per game start). */
        #jc-title-card { display:none; position:fixed; inset:0; z-index:390; flex-direction:column; align-items:center; justify-content:center; gap:14px; padding:32px 20px; text-align:center; color:#fff; background:radial-gradient(circle at 50% 12%, var(--tc-bg1,#221a3d), var(--tc-bg2,#05050a) 80%); }
        #jc-title-card.open { display:flex; animation:tc-in .45s ease-out; }
        #jc-title-card.closing { animation:tc-out .4s ease-in forwards; }
        @keyframes tc-in { from { opacity:0; } }
        @keyframes tc-out { to { opacity:0; } }
        #jc-tc-eyebrow { font-size:.72em; font-weight:800; letter-spacing:.3em; color:var(--tc-acc2,#ff5286); }
        #jc-tc-title { font-family:var(--font-display); font-size:clamp(30px,9vw,54px); line-height:1.05; color:var(--tc-acc,#ffc94b); text-shadow:0 3px 0 rgba(0,0,0,.45), 0 7px 22px rgba(0,0,0,.5); animation:tc-pop .5s cubic-bezier(.2,.9,.25,1.25) backwards; }
        @keyframes tc-pop { from { transform:scale(.7); opacity:0; } }
        #jc-tc-tag { font-size:.95em; color:var(--tc-ink,#f5eedd); opacity:.92; max-width:36ch; line-height:1.5; }
        #jc-tc-chips { display:flex; gap:8px; flex-wrap:wrap; justify-content:center; }
        #jc-tc-chips span { font-size:.66em; font-weight:800; letter-spacing:.08em; border:1px solid var(--tc-acc,#ffc94b); color:var(--tc-acc,#ffc94b); border-radius:99px; padding:6px 12px; opacity:.85; }
        @media (prefers-reduced-motion: reduce){ #jc-title-card.open, #jc-title-card.closing, #jc-tc-title { animation:none; } }

        /* ── Between-round standings beat (playtest: "who's ahead?") ── */
        #round-standings { display:none; position:fixed; inset:0; z-index:385; flex-direction:column; align-items:center; justify-content:center; padding:28px 18px; background:rgba(0,0,0,0.55); }
        #round-standings.open { display:flex; }
        #rs-card { background:var(--c-card); border:1.5px solid var(--c-border); border-radius:18px; padding:22px 20px; width:min(400px,92vw); max-height:76vh; overflow-y:auto; display:flex; flex-direction:column; gap:12px; }
        #rs-title { font-family:var(--font-display); font-size:1.02em; color:var(--c-brand); text-align:center; letter-spacing:.06em; }
        #rs-rows { display:flex; flex-direction:column; gap:7px; }
        .rs-row { display:flex; align-items:center; gap:10px; background:rgba(128,128,128,0.10); border-radius:10px; padding:9px 12px; color:var(--c-ink); font-weight:700; }
        .rs-place { min-width:1.8em; text-align:center; }
        .rs-name { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
        .rs-you { display:inline-block; font-size:.62em; font-weight:800; letter-spacing:.08em; background:var(--c-brand); color:#111; border-radius:99px; padding:2px 7px; margin-left:6px; vertical-align:1px; }
        .rs-delta { font-size:.78em; color:var(--c-mint,#5ee6c5); font-weight:800; }
        .rs-score { font-family:monospace; font-size:1.05em; color:var(--c-brand); min-width:2.5em; text-align:right; }
        #rs-sub { font-size:.8em; color:var(--c-ink3); text-align:center; }

        /* ── Universal winner podium ── */
        #podium-overlay { display:none; position:fixed; inset:0; z-index:400; background:radial-gradient(circle at 50% 18%, #221a3d, #05050a 75%); flex-direction:column; align-items:center; justify-content:center; gap:16px; padding:calc(env(safe-area-inset-top) + 24px) 16px calc(env(safe-area-inset-bottom) + 20px); color:#fff; overflow-y:auto; }
        #podium-overlay.open { display:flex; }
        #podium-title { font-family:var(--font-display); font-size:1.05em; color:var(--c-gold); text-shadow:0 0 16px rgba(255,215,0,0.55); text-align:center; line-height:1.4; }
        #podium-sub { font-size:0.92em; color:#cfd6e6; text-align:center; max-width:340px; line-height:1.5; margin-top:-4px; }
        #podium-stage { display:flex; align-items:flex-end; justify-content:center; gap:8px; width:min(440px,96%); margin-top:8px; }
        .podium-col { flex:1 1 0; display:flex; flex-direction:column; align-items:center; gap:4px; min-width:0; }
        .podium-name { font-weight:900; font-size:0.82em; text-align:center; word-break:break-word; line-height:1.15; max-width:100%; }
        .podium-score { font-family:monospace; font-size:0.74em; color:#ffd76b; }
        .podium-medal { font-size:1.5em; line-height:1; }
        .podium-bar { width:100%; border-radius:8px 8px 0 0; display:flex; align-items:center; justify-content:center; box-shadow:0 -2px 12px rgba(0,0,0,0.4) inset; }
        .podium-bar .podium-place { font-family:var(--font-display); font-size:0.9em; color:rgba(0,0,0,0.55); }
        .podium-1 .podium-bar { background:linear-gradient(180deg,#ffe14d,#c79200); height:120px; }
        .podium-2 .podium-bar { background:linear-gradient(180deg,#e2e2e2,#8d8d8d); height:90px; }
        .podium-3 .podium-bar { background:linear-gradient(180deg,#e6975a,#9c5a23); height:66px; }
        #podium-rest { width:min(440px,96%); display:flex; flex-direction:column; gap:5px; }
        .podium-rest-row { display:flex; justify-content:space-between; align-items:center; background:rgba(255,255,255,0.05); border-radius:8px; padding:8px 12px; font-size:0.85em; }
        .podium-rest-row .pr-rank { color:#8a93a8; font-family:monospace; margin-right:10px; }
        .podium-rest-row .pr-score { color:#ffd76b; font-family:monospace; }
        #podium-close { margin-top:8px; }

        /* ── Shared reveal engine (podium + round-standings animations) ──────
           One system for every game's "here's where everyone stands" moment.
           JS side: animateStandingsReveal() / jcCountUp() near showPodium().
           CUSTOMIZATION HOOKS for a future per-game bespoke pass — override on
           a game's own container (they inherit), e.g.
               #bb-round-list { --reveal-accent:#ff9800; --reveal-stagger:140ms; }
             --reveal-stagger     delay between successive rows      (default 90ms)
             --reveal-duration    one row's slide-in time            (default 420ms)
             --reveal-easing      easing for rows/badges/podium bars (springy default)
             --reveal-accent      leader-row ring color              (default --c-brand)
             --reveal-base-delay  flat delay before the first row    (default 0ms)   */
        :root { --reveal-stagger:90ms; --reveal-duration:420ms; --reveal-easing:cubic-bezier(.2,.9,.25,1.25); --reveal-accent:var(--c-brand); --reveal-base-delay:0ms; }
        .reveal-row { animation:reveal-row-in var(--reveal-duration) var(--reveal-easing) calc(var(--reveal-base-delay) + var(--reveal-stagger) * var(--i,0)) backwards; }
        @keyframes reveal-row-in { from { opacity:0; transform:translateY(12px) scale(.96); } }
        .reveal-row.reveal-top { box-shadow:0 0 0 1.5px var(--reveal-accent), 0 0 16px -4px var(--reveal-accent); }
        .reveal-badge { display:inline-block; animation:reveal-badge-pop .45s var(--reveal-easing) calc(var(--reveal-base-delay) + var(--reveal-stagger) * var(--i,0) + 180ms) backwards; }
        @keyframes reveal-badge-pop { from { transform:scale(0) rotate(-25deg); } }

        /* Podium reveal choreography: bars rise 3rd→2nd→1st, medals pop, names/
           scores fade up, gold bar shimmers + drops confetti for 1st place.
           NOTE: --pd-delay values MUST stay in sync with PD_DELAY in showPodium(). */
        #podium-overlay.open { animation:pd-fade-in .3s ease-out; }
        #podium-title, #podium-sub { animation:pd-fade-up .45s ease-out backwards; }
        .podium-col { position:relative; --pd-delay:0ms; }
        .podium-2 { --pd-delay:320ms; }
        .podium-1 { --pd-delay:640ms; }
        .podium-bar { transform-origin:bottom center; animation:pd-bar-rise .55s var(--reveal-easing) var(--pd-delay) backwards; }
        @keyframes pd-bar-rise { from { transform:scaleY(.05); } }
        .podium-medal { animation:pd-medal-pop .5s var(--reveal-easing) calc(var(--pd-delay) + 300ms) backwards; }
        @keyframes pd-medal-pop { 0% { transform:scale(0); opacity:0; } 70% { transform:scale(1.35); opacity:1; } 100% { transform:scale(1); opacity:1; } }
        .podium-name, .podium-score { animation:pd-fade-up .4s ease-out calc(var(--pd-delay) + 260ms) backwards; }
        @keyframes pd-fade-up { from { opacity:0; transform:translateY(8px); } }
        .podium-bar .podium-place { animation:pd-fade-in .35s ease-out calc(var(--pd-delay) + 430ms) backwards; }
        @keyframes pd-fade-in { from { opacity:0; } }
        .podium-1 .podium-bar { position:relative; overflow:hidden; }
        .podium-1 .podium-bar::after { content:''; position:absolute; inset:0; background:linear-gradient(115deg,transparent 32%,rgba(255,255,255,.5) 50%,transparent 68%); transform:translateX(-130%); animation:pd-shine 2.6s ease-in-out calc(var(--pd-delay) + 900ms) infinite; }
        @keyframes pd-shine { 0% { transform:translateX(-130%); } 45%, 100% { transform:translateX(130%); } }
        .pd-confetti { position:absolute; top:-22px; left:0; right:0; height:0; pointer-events:none; }
        .pd-confetti i { position:absolute; top:0; width:7px; height:11px; border-radius:2px; opacity:0; animation:pd-confetti-fall 1.5s ease-in forwards; }
        @keyframes pd-confetti-fall { 0% { opacity:0; transform:translate(0,-8px) rotate(0deg); } 12% { opacity:1; } 100% { opacity:0; transform:translate(var(--dx,0px),150px) rotate(520deg); } }
        @media (prefers-reduced-motion: reduce) {
            .reveal-row, .reveal-badge, #podium-overlay.open, #podium-title, #podium-sub, .podium-bar, .podium-medal, .podium-name, .podium-score, .podium-bar .podium-place { animation-duration:1ms !important; animation-delay:0ms !important; }
            .podium-1 .podium-bar::after, .pd-confetti i { animation:none !important; }
            /* Lobby: no card lift, no adaptive-shell retint sweep */
            #room-lobby, .tv-screen, .game-card, .rl-code, .rl-marquee, .tv-logo, .tv-code, #rl-start-btn { transition:none !important; }
            .game-card:hover { transform:none !important; }
        }

        /* ── TV / spectator screen ── */
        #tv-shell { display:none; }
        body.tv-mode #tv-shell { display:block; }
        /* TV mode never shows the phone-control chrome — hub, lobby, leave button, every
           per-game phone screen — only whichever #tv-* screen is currently active. */
        body.tv-mode #hub-screen, body.tv-mode #room-lobby, body.tv-mode #global-leave, body.tv-mode #global-host-lobby { display:none !important; }
        .tv-screen { position:fixed; inset:0; z-index:55; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:22px; padding:40px; color:#fff; background:radial-gradient(circle at 50% 20%, var(--c-card), #050508 75%); overflow:hidden; }
        .tv-logo { font-family:var(--font-display); font-size:3.4em; letter-spacing:6px; color:var(--c-brand); text-shadow:0 0 32px rgba(255,235,59,0.5); }
        .tv-code { font-family:var(--font-display); font-size:2.2em; letter-spacing:12px; color:#fff; background:rgba(255,255,255,0.06); border:2px solid rgba(255,235,59,0.4); border-radius:14px; padding:14px 32px; }
        #tv-qr { background:var(--c-brand); border-radius:12px; padding:14px; }
        #tv-qr canvas, #tv-qr img { display:block; width:220px !important; height:220px !important; }
        .tv-qr-cap { font-family:monospace; font-size:1.1em; color:var(--c-mint); }
        .tv-player-list { display:flex; flex-wrap:wrap; gap:10px; justify-content:center; max-width:min(900px,90vw); }
        .tv-player-chip { background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.16); border-radius:10px; padding:8px 18px; font-size:1.15em; font-weight:700; }
        .tv-game-name { font-family:var(--font-display); font-size:1.3em; color:#ffcc00; text-shadow:0 0 10px rgba(255,153,0,0.5); }
        .tv-sub { font-size:1.1em; color:#aaa; }
        /* ── TV lobby: adaptive pack shell (mirrors #room-lobby; other tv-* screens keep
           their neutral ground). JS sets the --shell-* vars from JC_GAMES on selection. */
        #tv-lobby { --shell-acc:var(--c-brand); --shell-bg1:#1b2740; --shell-bg2:#0d1322; --shell-font:var(--font-display);
            background:radial-gradient(circle at 50% 20%,
                color-mix(in oklab, var(--shell-bg1) 46%, #0a0e1a),
                color-mix(in oklab, var(--shell-bg2) 46%, #05070d) 78%);
            transition:background .45s ease; }
        #tv-lobby .tv-logo { color:var(--shell-acc); text-shadow:0 0 32px color-mix(in srgb, var(--shell-acc) 45%, transparent); transition:color .45s ease; }
        #tv-lobby .tv-code { border-color:color-mix(in srgb, var(--shell-acc) 55%, transparent); transition:border-color .45s ease; }
        #tv-lobby .tv-game-name { font-family:var(--shell-font); color:var(--shell-acc); text-shadow:none; transition:color .45s ease; }
        .tv-timer { font-family:var(--font-display); font-size:1.6em; color:#ff4444; text-shadow:0 0 10px #ff0000; }
        .tv-header-row { position:relative; width:100%; display:flex; align-items:center; justify-content:space-between; padding:0 12px; }
        /* PikPic */
        .tv-pp-clue { font-size:2.2em; font-weight:900; text-align:center; }
        .tv-pp-progress { font-family:monospace; font-size:1.1em; color:var(--c-mint); }
        .tv-pp-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(180px,1fr)); gap:18px; width:min(1200px,92vw); max-height:60vh; overflow-y:auto; }
        .tv-pp-card { position:relative; border-radius:14px; overflow:hidden; border:3px solid rgba(255,255,255,0.15); background:#111; }
        .tv-pp-card img { width:100%; height:160px; object-fit:cover; display:block; }
        .tv-pp-card .tv-pp-votes { position:absolute; bottom:0; left:0; right:0; background:rgba(0,0,0,0.72); padding:6px 10px; font-family:monospace; font-size:0.95em; }
        .tv-pp-card.tv-pp-correct { border-color:#4caf50; box-shadow:0 0 22px rgba(76,175,80,0.6); }
        /* Punch-Up */
        .tv-qp-prompt { font-size:1.8em; font-weight:900; text-align:center; max-width:min(1000px,90vw); }
        .tv-qp-versus { display:flex; align-items:stretch; gap:24px; width:min(1100px,92vw); }
        .tv-qp-side { flex:1; background:rgba(255,255,255,0.05); border:2px solid rgba(255,255,255,0.14); border-radius:16px; padding:18px; display:flex; flex-direction:column; gap:10px; align-items:center; text-align:center; transition:border-color .3s, background .3s; }
        .tv-qp-side.tv-qp-winner { border-color:var(--c-gold); background:rgba(255,215,0,0.1); }
        .tv-qp-name { font-weight:900; font-size:1.15em; color:#ffcc00; }
        .tv-qp-answer { font-size:1.3em; min-height:1.6em; }
        .tv-qp-vs { align-self:center; font-family:var(--font-display); font-size:1.4em; color:var(--c-hot); }
        .tv-qp-votebar { width:100%; height:16px; border-radius:8px; background:#222; overflow:hidden; }
        .tv-qp-votefill { height:100%; width:0%; background:linear-gradient(90deg,#1565c0,#00e5ff); transition:width .5s ease-out; }
        .tv-qp-votecount { font-family:monospace; color:var(--c-mint); }
        .tv-qp-progress { font-family:monospace; font-size:1em; color:var(--c-mint); }
        /* Rizz or Roast — battle cards reuse .tv-qp-*; only the audio-speaking glow is new */
        .tv-qp-side.tv-rr-speaking { border-color:#e040fb; background:rgba(224,64,251,0.12); }
        /* Squiggle Fight */
        .tv-sq-prompt { font-size:1.5em; font-weight:900; color:#fff; text-align:center; max-width:92vw; }
        .tv-sq-stage { display:flex; align-items:center; gap:28px; }
        .tv-sq-side { display:flex; flex-direction:column; align-items:center; gap:10px; }
        .tv-sq-side canvas { height:min(58vh,640px); aspect-ratio:450/800; background:#111; border:3px solid rgba(255,255,255,0.14); border-radius:12px; transition:border-color .3s, box-shadow .3s; }
        .tv-sq-side canvas.sq-winner { border-color:var(--c-gold); box-shadow:0 0 34px rgba(255,215,0,0.45); }
        .tv-sq-standings { display:flex; flex-direction:column; gap:8px; min-width:min(560px,90vw); }
        .tv-sq-row { display:flex; justify-content:space-between; gap:18px; background:rgba(255,255,255,0.05); border:2px solid rgba(255,255,255,0.12); border-radius:10px; padding:10px 18px; font-size:1.15em; }
        .tv-sq-row .pts { color:var(--c-brand); font-family:monospace; }
        /* Crop Detective TV — same viewport mechanics, living-room sized */
        .tv-cd-viewport { width:min(62vh,58vw); }
        #tv-cd-gallery img { width:100%; aspect-ratio:1; object-fit:cover; border-radius:12px; border:3px solid rgba(255,255,255,0.18); }
        /* Split Crew */
        .tv-sc-roster { display:flex; flex-wrap:wrap; gap:16px; justify-content:center; }
        .tv-sc-team { background:rgba(255,255,255,0.05); border:2px solid rgba(255,255,255,0.14); border-radius:14px; padding:14px 20px; min-width:220px; text-align:center; }
        .tv-sc-team.tv-sc-crashed { border-color:#b71c1c; background:rgba(183,28,28,0.12); opacity:0.7; }
        .tv-sc-team-driver { font-weight:900; font-size:1.1em; color:#ffcc00; }
        .tv-sc-team-crew { font-size:0.85em; color:#aaa; }
        .tv-sc-progress-bar { width:100%; height:10px; border-radius:5px; background:#222; overflow:hidden; margin-top:8px; }
        .tv-sc-progress-fill { height:100%; background:linear-gradient(90deg,#4caf50,#8bc34a); transition:width .4s ease-out; }
        #tv-sc-race-canvas { width:min(1400px,94vw); height:min(70vh,760px); }
        .tv-sc-reveal { width:min(1200px,92vw); display:flex; flex-wrap:wrap; gap:14px; justify-content:center; }
        /* Sleight of Hands */
        #tv-soh-canvas { position:absolute; inset:0; width:100%; height:100%; }

        /* ── Hub landing ── */
        #hub-screen { --spawna-ground:#111522; --spawna-shape:#f2e9dc; --spawna-ember:#ff754c; --spawna-edge:#2a2f3d; display:flex; flex-direction:column; align-items:stretch; position:absolute; inset:0; z-index:50; background:var(--spawna-ground); color:var(--spawna-shape); overflow-x:hidden; overflow-y:auto; scroll-behavior:smooth; }
        .hub-start { position:relative; min-height:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:18px; padding:calc(28px + env(safe-area-inset-top)) 24px calc(46px + env(safe-area-inset-bottom)); overflow:hidden; isolation:isolate; }
        .hub-start::after { content:""; position:absolute; width:min(76vw,620px); aspect-ratio:1; right:min(-28vw,-120px); bottom:min(-42vw,-240px); border:1px solid var(--spawna-edge); border-radius:50%; z-index:-1; }
        .hub-start::before { content:""; position:absolute; width:270px; height:270px; border-radius:50%; background:color-mix(in srgb,var(--spawna-ember) 10%,transparent); filter:blur(80px); z-index:-1; }
        .hub-brand { display:flex; align-items:center; gap:15px; margin-bottom:2px; transform:rotate(-1deg); }
        .hub-mark { width:64px; height:64px; color:var(--spawna-shape); }
        .hub-logo { margin:0; font-family:'Nunito',system-ui,sans-serif; font-size:3.15em; line-height:1; font-weight:900; letter-spacing:-.07em; color:var(--spawna-shape); text-shadow:none; }
        .hub-sub { font-family:'Nunito',system-ui,sans-serif; color:var(--spawna-ember); letter-spacing:.14em; font-size:.68em; font-weight:900; margin-top:-5px; }
        .hub-label { width:min(380px,92%); font-size:.68em; font-weight:900; letter-spacing:.14em; color:var(--spawna-shape); opacity:.68; text-transform:uppercase; margin-bottom:-12px; text-align:left; }
        #hubNameInput { width:min(380px,92%); padding:16px; font-size:1.1em; text-align:left; border-radius:16px; border:2px solid var(--spawna-edge); font-weight:900; letter-spacing:.1em; text-transform:uppercase; background:#242935; color:var(--spawna-shape); box-shadow:0 8px 24px rgba(0,0,0,.18); }
        .hub-btn-row { display:flex; gap:10px; width:min(380px,92%); align-items:stretch; }
        .hub-btn-row .btn { flex:1; border-radius:16px; text-transform:none; letter-spacing:0; font-size:.94em; }
        #hubCreateBtn { flex:1.65; background:var(--spawna-ember); color:var(--spawna-ground); box-shadow:0 8px 0 #b83428,0 16px 30px rgba(0,0,0,.24); }
        #hubCreateBtn:active { transform:translateY(5px); box-shadow:0 3px 0 #b83428; }
        #hubJoinBtn { background:transparent; color:var(--spawna-shape); border-color:var(--spawna-shape); }
        #hubCodeWrap { display:none; flex-direction:column; align-items:center; gap:10px; width:min(380px,92%); }
        #hubCodeInput { width:100%; padding:16px; font-size:1.4em; text-align:center; border-radius:14px; border:1px solid var(--spawna-edge); font-weight:800; text-transform:uppercase; letter-spacing:8px; background:#242935; color:var(--spawna-shape); max-width:220px; }
        #hubJoinConfirm { background:var(--spawna-shape); color:var(--spawna-ground); }
        .hub-games-link { position:absolute; bottom:calc(15px + env(safe-area-inset-bottom)); color:var(--spawna-shape); opacity:.48; font-size:.64em; font-weight:900; letter-spacing:.16em; text-decoration:none; text-transform:uppercase; }
        .hub-games { min-height:100%; padding:72px max(24px,calc((100vw - 900px)/2)) 90px; background:#f5f1e9; color:#171922; }
        .hub-games h2 { margin:0 0 26px; font-family:'Nunito',system-ui,sans-serif; font-size:clamp(2rem,6vw,4rem); letter-spacing:-.06em; }
        .hub-game-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; }
        .hub-game-preview { min-height:180px; display:flex; flex-direction:column; justify-content:flex-end; padding:20px; border-radius:20px; color:var(--game-ink,#fff); background:linear-gradient(145deg,var(--game-a),var(--game-b)); box-shadow:0 10px 24px rgba(17,21,34,.12); }
        .hub-game-preview > span { margin-bottom:auto; font-size:1.5rem; }
        .hub-game-preview h3 { margin:18px 0 3px; font-family:var(--game-font,'Nunito'),system-ui,sans-serif; font-size:clamp(1rem,2.4vw,1.35rem); line-height:1.05; }
        .hub-game-preview p { margin:0; opacity:.7; font-size:.72em; font-weight:800; letter-spacing:.08em; text-transform:uppercase; }
        .hub-game-preview.pikpic { --game-a:#f1ece2; --game-b:#e7e0d2; --game-ink:#28251f; --game-font:'Baloo 2'; }
        .hub-game-preview.wisecrack { --game-a:#261440; --game-b:#160e24; --game-font:'Shrikhand'; }
        .hub-game-preview.squiggle { --game-a:#f5f2e9; --game-b:#eae6d8; --game-ink:#2b2b31; --game-font:'Luckiest Guy'; }
        .hub-game-preview.sleight { --game-a:#1b2b21; --game-b:#0d1512; --game-font:'Bungee'; }
        .hub-game-preview.split { --game-a:#2b2416; --game-b:#131006; --game-font:'Bungee'; }
        .hub-game-preview.snap { --game-a:#f7f1e6; --game-b:#eee5d2; --game-ink:#38292f; --game-font:'Titan One'; }
        @media(max-width:620px){ .hub-game-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.hub-game-preview{min-height:150px;padding:16px} }
        #hubJoinConfirm { width:100%; }
        /* Keyboard focus is visible on every lobby-layer control (was outline:none) */
        #hub-screen :focus-visible, #room-lobby :focus-visible, #tv-shell :focus-visible {
            outline:3px solid var(--shell-acc, var(--c-brand)); outline-offset:2px; }

        /* ── Room lobby ── */
        /* ── Adaptive pack shell — a clean tokenized stage that retints to whichever
           cartridge the room is looking at. JS (jcShellTheme) sets the --shell-* vars
           from JC_GAMES; neutral defaults = brand yellow on the deep-blue stage.
           No texture under small text (the scanline pattern is gone on purpose). */
        #room-lobby { display:none;
            --shell-acc:var(--portal-coral); --shell-bg1:#1b2740; --shell-bg2:#0d1322; --shell-font:var(--font-display);
            position:absolute; inset:0; z-index:48;
            background:radial-gradient(circle at 50% 18%,
                color-mix(in oklab, var(--shell-bg1) 46%, #0a0e1a),
                color-mix(in oklab, var(--shell-bg2) 46%, #05070d) 78%);
            transition:background .45s ease;
            flex-direction:column; align-items:center;
            padding:5vh 16px calc(20px + env(safe-area-inset-bottom)); color:var(--c-ink);
            overflow-y:auto; -webkit-overflow-scrolling:touch; overscroll-behavior:contain;
            touch-action:pan-y; gap:12px; }
        .skip-link { position:absolute; left:-9999px; top:calc(8px + env(safe-area-inset-top)); z-index:10;
            background:var(--c-card); color:var(--c-ink); padding:12px 16px; border-radius:var(--radius-sm); font-weight:800; text-decoration:none; }
        .skip-link:focus { left:8px; }
        /* Wordmark: portal-mark SVG + JAKECRATE in solid white (the old white+amber
           two-tone split is retired). */
        .rl-logo { display:flex; align-items:center; justify-content:center; gap:10px;
            font-family:var(--font-display); font-size:1.5em; letter-spacing:3px; color:var(--c-ink);
            text-shadow:0 2px 0 rgba(0,0,0,.4); margin:0; font-weight:normal; }
        .rl-portal-mark { display:none; width:30px; height:30px; flex-shrink:0;
            filter:drop-shadow(0 2px 6px color-mix(in srgb, var(--portal-coral) 40%, transparent)); }
        .rl-spawna-mark { width:34px; height:34px; flex-shrink:0; color:var(--c-ink); }
        .rl-wordmark { color:var(--c-ink); }
        .rl-code { font-family:var(--font-display);
            font-size:1.5em; font-weight:normal; letter-spacing:8px;
            color:var(--shell-acc);
            background:rgba(0,0,0,0.38);
            border:2px solid color-mix(in srgb, var(--shell-acc) 70%, transparent);
            border-radius:var(--radius-sm);
            padding:13px 12px 13px 20px;
            box-shadow:var(--shadow-1);
            transition:color .45s ease, border-color .45s ease; }
        .rl-hint { color:var(--c-ink3); font-size:0.8em; font-weight:700; letter-spacing:1px; }
        .rl-code-label { font-size:0.66em; font-weight:700; letter-spacing:.24em; color:var(--c-ink3); }
        #rl-players { display:flex; flex-wrap:wrap; gap:8px; justify-content:center; max-width:420px; }
        .lobby-chip { background:rgba(255,255,255,0.08); border:1px solid #3a4a66; border-radius:20px; padding:7px 14px; font-weight:bold; font-size:0.9em; user-select:none; -webkit-user-select:none; }
        /* ── Cartridge rack — two-across grid of tiles, every visual from ONE JC_GAMES
           record (inline vars set by renderGameShelf): --ga accent, --gb1/--gb2 gradient,
           --gi name ink, --gf typeface, --gs per-face optical-size compensation. */
        #rl-game-pick { display:grid; grid-template-columns:1fr 1fr; gap:10px; width:min(380px,92%); margin-top:4px; }
        .game-card { position:relative; display:flex; flex-direction:column; justify-content:space-between;
            gap:8px; min-height:122px; text-align:left; padding:12px;
            font-family:inherit; font-size:1em; text-transform:none; flex-grow:0; /* undo the global button rule */
            cursor:pointer; user-select:none; -webkit-user-select:none;
            color:var(--gi, var(--c-ink));
            background:linear-gradient(150deg, var(--gb1, var(--c-card)), var(--gb2, #0d1322));
            border:1.5px solid color-mix(in srgb, var(--ga, var(--c-border)) 45%, transparent);
            border-radius:var(--radius); box-shadow:var(--shadow-1);
            transition:transform .12s ease, box-shadow .12s ease; }
        .game-card:hover { transform:translateY(-3px);
            box-shadow:0 0 0 1.5px var(--ga, var(--c-brand)), 0 10px 22px rgba(0,0,0,.45); }
        .game-card.selected { box-shadow:0 0 0 2.5px var(--ga, var(--c-brand)),
            0 0 24px color-mix(in srgb, var(--ga, var(--c-brand)) 40%, transparent), var(--shadow-2); }
        .game-card.selected::after { content:"✓"; position:absolute; top:8px; right:8px;
            width:22px; height:22px; border-radius:50%; background:var(--ga, var(--c-brand)); color:#0a0c12;
            font-weight:800; font-size:.8em; display:grid; place-items:center; }
        #rl-pick-title { font-family:var(--font-display); font-size:.78em; letter-spacing:.14em; color:var(--c-ink2); margin:4px 0 2px; text-align:center; }
        .game-card.soon { opacity:.45; cursor:default; pointer-events:none; }
        .gc-icon { font-size:2.05em; line-height:1; flex-shrink:0; filter:drop-shadow(0 2px 4px rgba(0,0,0,.35)); }
        .gc-name { font-family:var(--gf, var(--font-display)); font-size:calc(1.04rem * var(--gs, 1));
            line-height:1.18; text-wrap:balance; }
        .gc-foot { display:flex; align-items:center; justify-content:space-between; min-height:1.2em; gap:4px; }
        .gc-kit { font-size:.6em; font-weight:800; letter-spacing:.1em; color:var(--gi, var(--c-ink)); opacity:.85;
            border:1px solid color-mix(in srgb, var(--ga, var(--c-border)) 65%, transparent); border-radius:8px; padding:2px 7px; }
        .gc-voters { display:flex; flex-wrap:wrap; gap:1px; font-size:1.05em; line-height:1; min-height:1.1em; }
        /* Action bar flows inline beneath the game tiles — it used to be a sticky bottom
           dock (position:sticky; bottom:0 + margin-top:auto + a gradient), which overlapped
           the last cards of the 6-game grid and juddered while scrolling. Now START GAME and
           the preview marquee scroll WITH the content. */
        #rl-actionbar { width:min(380px,100%); padding:8px 0 2px; display:flex; flex-direction:column; align-items:center; gap:6px; }
        /* Marquee: the action bar doubles as the preview pane — name in the game's own
           face + the blurb, for whatever card is hovered/focused/selected. */
        .rl-marquee { font-family:var(--shell-font); font-size:1.08em; letter-spacing:.05em; color:var(--shell-acc);
            min-height:1.35em; transition:color .45s ease; text-shadow:0 2px 8px rgba(0,0,0,.5); text-align:center; }
        .rl-marquee-desc { font-size:.82em; font-weight:700; color:var(--c-ink2); text-align:center;
            min-height:2.5em; max-width:98%; line-height:1.25; }
        #rl-start-btn { width:100%; text-transform:uppercase; display:none;
            background:var(--shell-acc); transition:background .45s ease; }
        #rl-wait { font-weight:700; color:var(--c-ink3); font-size:0.85em; text-align:center; }
        /* Room code + invite live on one row; QR/share collapse into a panel */
        .rl-code-row { display:flex; align-items:center; gap:10px; }
        #rl-invite { display:none; flex-direction:column; align-items:center; gap:8px; }
        #rl-invite.open { display:flex; }
        /* Leave/Close live behind the ⋯ corner menu — rare, destructive actions
           shouldn't take permanent lobby real estate (and CLOSE was a misclick hazard) */
        .rl-topbar { position:absolute; top:calc(8px + env(safe-area-inset-top)); right:calc(10px + env(safe-area-inset-right)); z-index:6; }
        #rl-menu-btn { font-size:1.5em; line-height:1; padding:8px 14px; min-width:44px; min-height:44px; color:var(--c-ink2); }
        .btn-quiet { min-height:44px; }
        #rl-menu { position:absolute; right:0; top:44px; background:var(--c-card); border:1.5px solid var(--c-border); border-radius:12px; display:none; flex-direction:column; min-width:180px; overflow:hidden; box-shadow:0 8px 24px rgba(0,0,0,.5); }
        #rl-menu button { background:none; border:none; padding:14px 18px; color:var(--c-ink2); text-align:left; font-size:0.85em; font-weight:700; cursor:pointer; font-family:inherit; }
        #rl-menu button:active { background:rgba(255,255,255,.06); }
        #rl-menu #rl-close-btn { color:var(--c-danger); }

        /* ── Shared game HUD ── */
        #monitor-hud { position:absolute; top:calc(10px + env(safe-area-inset-top)); left:calc(12px + env(safe-area-inset-left)); display:flex; align-items:center; gap:8px; pointer-events:none; z-index:10; font-family:monospace; color:#fff; font-size:1em; text-shadow:2px 2px 2px #000; max-width:46vw; }
        #cam-title { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
        #rec-light { width:13px; height:13px; background:#ff0000; border-radius:50%; box-shadow:0 0 8px #ff0000; display:inline-block; opacity:0; flex-shrink:0; }
        @keyframes pulse { 50% { opacity:1; } }
        .recording { animation:pulse 1s infinite; }
        #nav-desk { position:absolute; top:calc(8px + env(safe-area-inset-top)); right:calc(12px + env(safe-area-inset-right)); display:flex; gap:6px; z-index:10; }
        .nav-btn { padding:7px 12px; background:rgba(25,25,30,0.9); color:white; border:1px solid #555; border-radius:6px; font-weight:bold; font-size:0.8em; cursor:pointer; white-space:nowrap; }
        #phase-hud { position:absolute; top:calc(48px + env(safe-area-inset-top)); left:50%; transform:translateX(-50%); display:flex; gap:12px; align-items:center; z-index:10; pointer-events:none; font-family:monospace; color:#fff; font-size:1.3em; font-weight:bold; text-shadow:0 0 8px rgba(255,255,255,0.4),2px 2px 2px #000; }
        #timer-hud { font-size:1.8em; color:var(--c-brand); text-shadow:0 0 12px rgba(255,235,59,0.8),2px 2px 2px #000; }
        /* Spotlight / poke HUDs — centered below the phase row so nothing overlaps */
        #poke-counter, #vp-points-hud { position:absolute; top:calc(88px + env(safe-area-inset-top)); left:50%; transform:translateX(-50%); z-index:10; font-family:monospace; font-weight:bold; pointer-events:none; text-align:center; white-space:nowrap; }
        #poke-counter { color:#ff5252; font-size:1em; text-shadow:0 0 8px rgba(255,60,60,0.6),1px 1px 2px #000; }
        #vp-points-hud { color:var(--c-brand); font-size:1.15em; text-shadow:0 0 10px rgba(255,200,0,0.8),1px 1px 2px #000; }
        /* Find Me — bottom-right corner, above the bottom dock. Anchored to the bottom (not a
           top:% offset) so it stays clear of #float-tools regardless of screen height — float-tools
           is pinned to top:50% and its footprint is a fixed pixel height, so a percentage-based
           position for this button could land inside it on shorter screens (that was the bug). */
        #findMeBtn { position:absolute; right:calc(6px + env(safe-area-inset-right)); bottom:calc(64px + env(safe-area-inset-bottom)); z-index:10; flex-grow:0; padding:9px 12px; background:rgba(25,25,30,0.92); color:#fff; border:1px solid #555; border-radius:10px; font-size:0.78em; font-weight:bold; box-shadow:0 2px 8px rgba(0,0,0,0.6); }
        /* MOVE/PAINT segmented toggle — both states always visible, active one lit.
           Shared by the rail control (#modeBtn) and the floating pill (#ts-mode-float). */
        .ts-mode-seg button { opacity:0.45; background:#26262e; border:1px solid #444; color:#fff; }
        .ts-mode-seg button.active { opacity:1; }
        .ts-mode-seg button.seg-move.active { background:#1565c0; border-color:#7CC4FF; box-shadow:0 0 12px rgba(21,101,192,0.7); }
        .ts-mode-seg button.seg-paint.active { background:#2e7d32; border-color:#7CFC9A; box-shadow:0 0 12px rgba(46,160,67,0.6); }
        #ts-mode-float { position:absolute; z-index:10; display:none; gap:4px; background:rgba(18,18,28,0.94); border:1px solid #555; border-radius:999px; padding:4px; box-shadow:0 2px 10px rgba(0,0,0,0.6); pointer-events:auto; touch-action:none; }
        #ts-mode-float button { flex-grow:0; padding:6px 10px; border-radius:999px; font-size:0.72em; font-weight:bold; touch-action:none; }

        /* The one shared toast (showToast). z-index must clear every screen/overlay it can
           fire over: game screens 55, lightbox 200, podium 400, reconnect overlay 600 — at
           25 it was literally invisible everywhere except the Sleight of Hands canvas. */
        #volunteer-toast { display:none; position:fixed; top:calc(92px + env(safe-area-inset-top)); left:50%; transform:translateX(-50%); z-index:650; background:rgba(13,21,37,0.97); color:var(--c-ink); font-family:monospace; padding:10px 22px; border-radius:10px; font-size:0.9em; text-align:center; pointer-events:none; border:1.5px solid var(--c-border); box-shadow:0 6px 24px rgba(0,0,0,.55); max-width:92vw; white-space:normal; animation:toast-in 0.25s ease-out; }
        @keyframes toast-in { from{opacity:0;transform:translateX(-50%) translateY(-8px)} to{opacity:1;transform:translateX(-50%) translateY(0)} }
        @keyframes btn-wiggle { 0%,88%,100%{transform:rotate(0deg)} 91%{transform:rotate(-3deg)} 95%{transform:rotate(3deg)} 98%{transform:rotate(-1deg)} }
        #whistleBtn { animation: btn-wiggle 5s ease-in-out infinite; }
        #score-list { max-height:52vh; overflow-y:auto; scrollbar-width:thin; scrollbar-color:#444 transparent; }
        #player-count { font-size:0.7em; color:#888; font-family:monospace; margin-left:4px; }
        #unified-scoreboard { background:var(--c-card); border:1px solid var(--c-border); border-radius:12px; padding:14px 16px; display:none; flex-direction:column; gap:8px; width:min(420px,92%); font-family:monospace; color:white; box-shadow:0 4px 24px rgba(0,0,0,0.7); }
        #unified-scoreboard .sb-title { font-size:0.9em; font-weight:bold; letter-spacing:2px; color:var(--c-brand); border-bottom:1px solid var(--c-border); padding-bottom:6px; text-align:center; }
        #unified-scoreboard .sb-row { display:flex; align-items:center; gap:0; padding:5px 2px; border-radius:4px; font-size:0.82em; }
        #unified-scoreboard .sb-row:nth-child(odd) { background:rgba(255,255,255,0.03); }
        #unified-scoreboard .sb-rank { width:22px; color:var(--c-ink3); font-size:0.9em; text-align:center; flex-shrink:0; }
        #unified-scoreboard .sb-name { flex:1; font-weight:bold; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding-right:4px; }
        #unified-scoreboard .sb-col { width:30px; text-align:center; font-size:0.85em; }
        #unified-scoreboard .sb-pts { width:46px; text-align:right; font-size:0.9em; font-weight:bold; color:var(--c-brand); flex-shrink:0; }
        #unified-scoreboard .sb-header { display:flex; align-items:center; font-size:0.68em; color:var(--c-ink3); padding:0 2px 2px; }
        #unified-scoreboard .sb-row.sb-leader { background:rgba(94,230,197,0.09); }
        #unified-scoreboard .sb-legend { font-size:0.6em; color:var(--c-ink3); text-align:center; letter-spacing:0.3px; padding-top:2px; border-top:1px solid var(--c-border); }
        /* keep old IDs for backward compat but hide them */
        #scoreboard, #so-scoreboard { display:none !important; }
        #scoreboard .sb-title { font-size:0.85em; font-weight:bold; letter-spacing:2px; color:var(--c-brand); border-bottom:1px solid #333; padding-bottom:6px; margin-bottom:2px; text-align:center; }
        #scoreboard .sb-header { display:flex; justify-content:space-between; font-size:0.65em; color:#666; padding:0 2px; }
        .sb-row { display:flex; align-items:center; gap:6px; padding:4px 2px; border-radius:4px; font-size:0.82em; }
        .sb-row:nth-child(odd) { background:rgba(255,255,255,0.03); }
        .sb-rank { width:18px; color:#666; font-size:0.9em; text-align:center; flex-shrink:0; }
        .sb-name { flex:1; font-weight:bold; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
        .sb-stat { width:44px; text-align:center; font-size:0.9em; }
        .sb-survivals { color:#81c784; }
        .sb-catches { color:#ef9a9a; }
        .sb-empty { color:#555; font-size:0.8em; text-align:center; padding:8px 0; }
        #pokeBtn { display:none; position:absolute; bottom:calc(26px + env(safe-area-inset-bottom)); left:50%; transform:translateX(-50%); z-index:16; padding:16px 46px; font-size:1.35em; font-weight:bold; letter-spacing:2px; color:#fff; background:var(--c-danger); border:none; border-radius:40px; box-shadow:0 6px 22px rgba(0,0,0,0.6); text-transform:uppercase; cursor:pointer; }
        #pokeBtn:active { transform:translateX(-50%) scale(0.94); }
        #pokeBtn:disabled { background:#666; opacity:0.55; }
        #lobbyDoneBtn { display:none; position:absolute; top:calc(12px + env(safe-area-inset-top)); left:50%; transform:translateX(-50%); z-index:17; padding:12px 30px; font-size:1em; font-weight:bold; letter-spacing:1px; color:#fff; background:#2e7d32; border:none; border-radius:30px; box-shadow:0 4px 16px rgba(0,0,0,0.5); text-transform:uppercase; cursor:pointer; }
        #framer-modal { display:none; width:300px; top:50%; transform:translate(-50%,-50%); z-index:65; }

        /* Unified rules/onboarding overlay — fixed so it also covers the ts full-screen canvas.
           z-index tops every game screen (max 250) but stays under podium (400) / reconnect (600). */
        #jc-rules-overlay { position:fixed; z-index:300; }
        /* GET READY strip — rides above the rules overlay (300) so the countdown/ready
           state stays visible while reading the how-to; under podium (400)/reconnect (600). */
        #jc-prep-strip { display:none; position:fixed; top:calc(10px + env(safe-area-inset-top)); left:50%; transform:translateX(-50%); z-index:310; align-items:center; gap:8px; background:rgba(14,17,23,0.95); border:1px solid var(--c-brand); border-radius:999px; padding:8px 18px; box-shadow:0 2px 14px rgba(0,0,0,0.7); }
        #jc-prep-text { font-size:0.72em; font-weight:800; letter-spacing:1px; color:var(--c-brand); text-transform:uppercase; white-space:nowrap; }
        #jc-rules-body .ob-line { font-size:0.95em; color:#cdd6e6; margin:10px 0; line-height:1.45; text-align:left; }
        #jc-rules-body .ob-line b { color:#ffd54f; }
        /* Shared helper-text style — the one class every game's small gray sub-label should use. */
        .jc-hint { font-size:0.78em; color:#7a8fa8; line-height:1.4; }
        .pavt { display:inline-flex; align-items:center; justify-content:center; width:22px; height:22px; border-radius:50%; font-size:0.78em; font-weight:900; color:#fff; vertical-align:middle; flex-shrink:0; }
        /* Spawnling avatar badge (generated in public/js/spawnling.js) — replaces .pavt where the generator loaded */
        .jc-sp { display:inline-block; vertical-align:middle; flex-shrink:0; }
        .pavt-sp { border-radius:26%; }
        /* Spawnling customizer (public/js/spawn-customize.js) */
        #sc-modal { display:none; position:fixed; inset:0; z-index:700; background:rgba(6,9,16,.72); align-items:center; justify-content:center; padding:18px; }
        #sc-modal .sc-card { background:linear-gradient(180deg,#141d31,#0e1526); border:1px solid rgba(255,255,255,.12); border-radius:20px; padding:20px; width:min(420px,94vw); display:flex; flex-direction:column; align-items:center; gap:12px; box-shadow:0 24px 60px rgba(0,0,0,.6); }
        #sc-modal .sc-head { font-family:var(--font-display,inherit); font-weight:800; font-size:1.15em; }
        #sc-modal .sc-preview { width:128px; height:128px; }
        #sc-modal .sc-build { font-family:monospace; font-size:.78em; color:#8695b2; letter-spacing:.02em; }
        #sc-modal .sc-row { display:flex; flex-wrap:wrap; gap:8px; justify-content:center; }
        #sc-modal .sc-btn { font-weight:600; font-size:.85em; cursor:pointer; border:1px solid rgba(255,255,255,.14); background:#16223a; color:#eaf0fb; border-radius:10px; padding:8px 12px; }
        #sc-modal .sc-btn:hover { border-color:var(--c-mint,#38e8b0); }
        #sc-modal .sc-ghost { background:transparent; color:#8695b2; }
        #sc-modal .sc-foot { display:flex; gap:10px; align-items:center; margin-top:4px; }
        @media (prefers-reduced-motion: no-preference){ #sc-modal .sc-preview svg { transition:filter .2s; } }
        /* ── Party Kit (generic renderer for games/<id>/game.json — kit-engine.js) ── */
        #kit-screen { display:none; position:absolute; inset:0; z-index:55; background:radial-gradient(circle at 50% 10%,#0a1a2e,#050508 70%); flex-direction:column; align-items:center; overflow-y:auto; color:var(--c-ink); padding:calc(env(safe-area-inset-top) + 16px) 16px calc(env(safe-area-inset-bottom) + 20px); gap:13px; }
        .kit-header { font-family:var(--font-display); font-size:0.72em; color:var(--c-brand); letter-spacing:1px; text-align:center; }
        .kit-item-card { background:rgba(255,255,255,0.06); border:1.5px solid var(--c-border); border-radius:14px; padding:12px; width:min(440px,94%); text-align:center; }
        .kit-item-card img { max-width:100%; max-height:38vh; border-radius:10px; display:block; margin:0 auto; }
        .kit-item-caption { font-size:1.1em; font-weight:bold; line-height:1.4; padding:6px 4px; }
        .kit-item-by { font-family:monospace; font-size:0.68em; color:var(--c-ink2); margin-top:6px; letter-spacing:1px; }
        .kit-item-subject { font-family:monospace; font-size:0.72em; color:var(--c-brand); letter-spacing:1px; margin-bottom:8px; font-weight:bold; }
        /* Ransom-note word magnets — cream tiles on the dark game UI. */
        .kit-magnet-hint { font-family:monospace; font-size:0.78em; color:var(--c-ink2); letter-spacing:1px; text-align:center; }
        .kit-magnet-tray { display:flex; flex-wrap:wrap; gap:8px; justify-content:center; align-items:center; width:min(500px,98%); max-height:44vh; overflow-y:auto; padding:6px 2px; }
        .kit-magnet { background:#f4ecd8; border:1px solid #d8cba8; border-radius:5px; padding:8px 12px; color:#2a2620; font-family:'Courier New',Courier,monospace; font-weight:bold; font-size:0.95em; cursor:pointer; box-shadow:1px 2px 3px rgba(0,0,0,0.28); transition:transform .1s; }
        .kit-magnet:active { transform:scale(0.93) !important; }
        .kit-magnet.chosen { background:var(--c-brand); color:#111; border-color:var(--c-brand); box-shadow:0 0 14px rgba(255,235,59,0.45); }
        .kit-answer-input { width:min(440px,94%); min-height:74px; background:var(--c-card); color:var(--c-ink); border:1.5px solid var(--c-border); border-radius:12px; padding:12px; font-size:1em; font-family:inherit; resize:none; }
        .kit-vote-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:10px; width:min(480px,96%); }
        .kit-vote-card { background:rgba(255,255,255,0.06); border:1.5px solid var(--c-border); border-radius:12px; padding:10px; cursor:pointer; text-align:center; display:flex; flex-direction:column; gap:6px; transition:transform .12s, border-color .12s; }
        .kit-vote-card:active { transform:scale(0.97); }
        .kit-vote-card.chosen { border-color:var(--c-brand); box-shadow:0 0 12px rgba(255,235,59,0.25); }
        .kit-vote-card.mine { opacity:0.55; cursor:default; }
        .kit-vote-card img { width:100%; max-height:120px; object-fit:cover; border-radius:8px; }
        .kit-vote-name { font-family:monospace; font-size:0.72em; color:var(--c-ink2); letter-spacing:1px; }
        .kit-tally-row { display:flex; justify-content:space-between; gap:12px; font-family:monospace; font-size:0.95em; width:min(360px,92%); padding:6px 10px; background:rgba(255,255,255,0.05); border-radius:9px; }
        .kit-progress { font-family:monospace; color:var(--c-ink2); font-size:0.82em; letter-spacing:1px; }
        .qp-answer-input { width:min(440px,94%); min-height:76px; resize:none; border-radius:12px; border:1.5px solid var(--c-border); background:var(--c-card); color:#fff; font-size:1.05em; padding:12px 14px; font-family:inherit; box-sizing:border-box; }
        .qp-mode-row { display:flex; gap:8px; width:min(440px,94%); }
        .qp-mode-row .btn { flex:1; }
        .qp-preview-img { width:min(260px,70%); border-radius:10px; display:none; border:3px solid #fff; }
        .qp-voice-badge { display:none; font-family:monospace; color:var(--c-brand); font-size:0.85em; letter-spacing:1px; }
        /* ── Doodle + Voice answer modals — full-screen like the PikPic lightbox (z:200),
           not the small settings-panel .modal class (same z as the qp screens, no backdrop) ── */
        /* overflow-y:auto + margin:auto on the card centers when it fits and scrolls when it
           doesn't — so the CLOSE / USE buttons are always reachable on short/landscape screens
           (a plain justify-content:center would clip the bottom off-screen with no way to scroll). */
        #qp-doodle-modal, #qp-voice-modal { display:none; position:fixed; inset:0; z-index:200; background:rgba(0,0,0,0.88); flex-direction:column; align-items:center; overflow-y:auto; gap:12px; padding:calc(env(safe-area-inset-top) + 12px) 16px calc(env(safe-area-inset-bottom) + 16px); }
        .qp-modal-card { margin:auto; background:#111726; border:1.5px solid var(--c-border); border-radius:16px; padding:16px; display:flex; flex-direction:column; gap:12px; align-items:center; width:min(380px,94%); }
        .qp-modal-topbar { display:flex; width:100%; align-items:center; justify-content:space-between; gap:8px; }
        #qp-doodle-canvas { background:#fff; border-radius:10px; touch-action:none; width:100%; max-width:360px; height:auto; cursor:crosshair; }
        .qp-voice-record-btn { width:80px; height:80px; border-radius:50%; border:4px solid #e91e63; background:#1a0010; color:#e91e63; font-size:2em; cursor:pointer; display:flex; align-items:center; justify-content:center; }
        .qp-voice-record-btn.recording { background:#e91e63; color:#fff; animation:rr-pulse 1s infinite; }
        .qp-voice-record-btn.done { border-color:#2e7d32; color:#2e7d32; background:#001a05; }
        .qp-battle-card { width:min(440px,94%); background:rgba(255,255,255,0.05); border:2px solid var(--c-border); border-radius:14px; padding:14px; display:flex; flex-direction:column; gap:9px; align-items:center; transition:border-color .15s, box-shadow .15s, transform .15s; }
        .qp-battle-card.qp-winner { border-color:var(--c-brand); box-shadow:0 0 0 3px rgba(255,235,59,.4),0 0 22px rgba(255,235,59,.5); transform:scale(1.02); }
        .qp-battle-card.qp-dim { opacity:.5; }
        .qp-battle-name { font-weight:bold; letter-spacing:1px; color:var(--c-ink2); }
        .qp-answer-text { font-size:1.15em; line-height:1.35; text-align:center; }
        .qp-answer-img { width:100%; max-width:280px; border-radius:8px; display:block; }
        .qp-answer-caption { font-size:0.95em; font-style:italic; text-align:center; margin-top:6px; line-height:1.3; }
        .qp-vs { font-weight:900; color:var(--c-ink3); letter-spacing:3px; font-size:0.85em; }
        .qp-vote-btn { border:none; border-radius:10px; padding:11px 22px; font-weight:bold; font-size:0.92em; cursor:pointer; letter-spacing:1px; text-transform:uppercase; background:var(--c-brand); color:#090b12; width:100%; max-width:200px; }
        .qp-vote-btn:disabled { opacity:.35; cursor:default; }
        .qp-scores { width:min(360px,92%); }
        .qp-score-row { display:flex; justify-content:space-between; padding:5px 9px; border-radius:6px; font-size:0.95em; }
        .qp-score-row:nth-child(odd){ background:rgba(255,255,255,0.03); }
        /* Result / end */
        .rr-winner-banner { font-size:1.6em; font-weight:900; text-align:center; color:var(--c-brand); }
        .rr-score-row { display:flex; justify-content:space-between; padding:6px 4px; font-family:monospace; font-size:0.9em; border-bottom:1px solid #1a0a2e; width:min(300px,88%); }

        /* ── Shared juice: directional sparks, impact rings, confetti, cork overlay ── */
        .sc-spark-p       { position:fixed; z-index:71; image-rendering:pixelated; pointer-events:none; animation:sc-spark .55s cubic-bezier(.2,.6,.6,1) forwards; }
        @keyframes sc-spark { 0%{transform:translate(0,0);opacity:1} 70%{transform:translate(var(--sx),var(--sy));opacity:1} 100%{transform:translate(var(--sx),calc(var(--sy) + var(--sg,40px)));opacity:0} }
        .sc-ring-p        { position:fixed; z-index:71; width:14px; height:14px; margin:-7px 0 0 -7px; border:3px solid #fff; border-radius:50%; pointer-events:none; animation:sc-ring .45s ease-out forwards; }
        @keyframes sc-ring { from{transform:scale(.4);opacity:.95} to{transform:scale(5);opacity:0} }
        .sc-confetti-p    { position:fixed; z-index:71; width:7px; height:11px; pointer-events:none; animation:sc-confetti 1.1s ease-in forwards; }
        @keyframes sc-confetti { 0%{transform:translate(0,0) rotate(0deg);opacity:1} 30%{transform:translate(calc(var(--cx)*.5),var(--cy)) rotate(calc(var(--cr)*.4));opacity:1} 100%{transform:translate(var(--cx),150px) rotate(var(--cr));opacity:0} }
        .sc-pop-canvas    { position:fixed; inset:0; z-index:72; pointer-events:none; }

        /* ── Game feel: live timer ring, waiting roster, screen-enter transition ── */
        /* @property lets the conic sweep interpolate smoothly (graceful step where unsupported). */
        @property --jc-timer-frac { syntax:'<number>'; inherits:false; initial-value:1; }
        .jc-timer { position:relative; display:inline-flex; align-items:center; justify-content:center;
            width:62px; height:62px; border-radius:50%; --jc-timer-frac:1; --jc-timer-col:var(--c-brand);
            background:conic-gradient(var(--jc-timer-col) calc(var(--jc-timer-frac) * 360deg), rgba(255,255,255,.13) 0deg);
            transition:--jc-timer-frac .95s linear; }
        .jc-timer::before { content:''; position:absolute; inset:5px; border-radius:50%; background:var(--c-card,#1a1030); }
        .jc-timer-num { position:relative; z-index:1; font-family:var(--font-display); font-weight:900; font-size:1.4em; line-height:1; color:var(--jc-timer-col); }
        .jc-timer--urgent { --jc-timer-col:#ff4747; animation:jc-timer-pulse .7s ease-in-out infinite; }
        .jc-timer--done   { --jc-timer-col:#ff4747; }
        @keyframes jc-timer-pulse { 0%,100%{transform:scale(1);} 50%{transform:scale(1.09);} }

        .jc-roster { display:flex; flex-direction:column; align-items:center; gap:10px; }
        .jc-roster-chips { display:flex; flex-wrap:wrap; justify-content:center; gap:8px; max-width:min(560px,94%); }
        .jc-chip { display:inline-flex; align-items:center; gap:6px; padding:5px 11px 5px 5px; border-radius:999px;
            background:rgba(255,255,255,.07); border:1.5px solid rgba(255,255,255,.14); font-weight:700; font-size:.9em;
            opacity:.5; transition:opacity .3s ease, background .3s ease, border-color .3s ease, transform .3s ease; }
        .jc-chip--done { opacity:1; background:color-mix(in srgb, var(--c-mint,#38e8b0) 16%, transparent);
            border-color:color-mix(in srgb, var(--c-mint,#38e8b0) 55%, transparent); }
        .jc-chip-face { width:24px; height:24px; border-radius:50%; overflow:hidden; flex:0 0 auto; background-size:cover;
            background-position:center; display:inline-flex; align-items:center; justify-content:center; }
        .jc-chip-face .pavt { width:24px; height:24px; }
        .jc-chip-name { white-space:nowrap; }
        .jc-chip-mark { font-size:.95em; opacity:.75; }
        .jc-chip--done .jc-chip-mark { color:var(--c-mint,#38e8b0); opacity:1; }
        .jc-roster-caption { font-size:.95em; font-weight:800; opacity:.85; text-align:center; }
        .jc-roster--burst .jc-chip { animation:jc-chip-check .5s cubic-bezier(.2,.9,.25,1.25); }
        @keyframes jc-chip-check { 0%{transform:scale(1);} 40%{transform:scale(1.16);} 100%{transform:scale(1);} }

        @keyframes jc-screen-in { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
        .jc-enter { animation:jc-screen-in .28s ease-out; }

        @media (prefers-reduced-motion: reduce) {
            .jc-timer { transition:none; }
            .jc-timer--urgent { animation:none; }
            .jc-roster--burst .jc-chip { animation:none; }
            .jc-enter { animation:none; }
        }
