    :root{
      color-scheme: light;
      --bg:#fff; --bg-subtle:#f7f7f7; --bg-hover:#f0f0f0;
      --surface:#fff; --surface-elevated:#fff;
      --border:#ebebeb; --border-strong:#ddd;
      --text:#222; --text-secondary:#717171; --text-tertiary:#b0b0b0;
      --primary:#222; --primary-hover:#000; --on-primary:#fff;
      /* Brand accent (2026-07-02, Saeed picked Option B): ONE warm orange used
         deliberately — Start/Play-again CTAs, active nav tab, active chips,
         selected picker rows. Never on danger/success/winner-gold surfaces,
         never on the login screen. Same orange the GTT how-to shipped with. */
      --accent:#e8590c; --accent-hover:#d9480f; --on-accent:#fff; --accent-soft:rgba(232,89,12,.10);
      --danger:#c13515; --danger-soft:#fdf0eb; --danger-soft-2:#fde9e4;
      --success:#008a05; --success-hover:#007a04; --success-soft:#e6f5e7;
      --winner-bg:#fff8e6; --winner-text:#b8860b;
      --shadow-md:0 2px 8px rgba(0,0,0,.06); --shadow-lg:0 6px 20px rgba(0,0,0,.08);
      --radius-sm:8px; --radius-md:12px; --radius-lg:16px; --radius-xl:20px; --radius-pill:999px;
      --header-h:56px; --nav-h:64px;
      --scrim:rgba(0,0,0,.45);
      --avatar-grad-from:#e4e4e4; --avatar-grad-to:#cfcfcf;
      --room-grad-from:#1a1a1a; --room-grad-to:#3a3a3a;
      --focus-ring:rgba(34,34,34,.08);
    }

    /* ===== Dark theme tokens ===== */
    [data-theme="dark"]{
      color-scheme: dark;
      --bg:#0e0e10; --bg-subtle:#1a1a1c; --bg-hover:#26262a;
      --surface:#1a1a1c; --surface-elevated:#26262a;
      --border:#2a2a2e; --border-strong:#3a3a3e;
      --text:#f5f5f5; --text-secondary:#9c9ca0; --text-tertiary:#6b6b6f;
      --primary:#f5f5f5; --primary-hover:#fff; --on-primary:#111;
      --accent:#ff9350; --accent-hover:#ffa76b; --on-accent:#161311; --accent-soft:rgba(255,147,80,.16);
      --danger:#ff6b54; --danger-soft:#2c1a17; --danger-soft-2:#321a18;
      --success:#3ec56a; --success-hover:#34b35e; --success-soft:#16291d;
      --winner-bg:#2a2410; --winner-text:#f5c451;
      --shadow-md:0 2px 8px rgba(0,0,0,.45); --shadow-lg:0 6px 20px rgba(0,0,0,.55);
      --scrim:rgba(0,0,0,.65);
      --avatar-grad-from:#3a3a3e; --avatar-grad-to:#26262a;
      --room-grad-from:#26262a; --room-grad-to:#3a3a3e;
      --focus-ring:rgba(245,245,245,.12);
    }

    html,body{transition:background-color .2s ease, color .2s ease}
    *{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
    html,body{margin:0;padding:0;background:var(--bg-subtle);color:var(--text);
      font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
      font-size:15px;line-height:1.45;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
    button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}

    /* ===== Arabic (lang=ar) ===== */
    /* Almarai — self-hosted, Arabic glyphs only (unicode-range). The files are
       fetched only when Arabic text actually renders, so EN/TR users never
       download them. fonts/almarai-*-arabic.woff2, ~32KB each, SIL OFL. */
    @font-face{font-family:'Almarai';font-style:normal;font-weight:400;font-display:swap;
      src:url('fonts/almarai-400-arabic.woff2') format('woff2');
      unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC}
    @font-face{font-family:'Almarai';font-style:normal;font-weight:700;font-display:swap;
      src:url('fonts/almarai-700-arabic.woff2') format('woff2');
      unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC}
    @font-face{font-family:'Almarai';font-style:normal;font-weight:800;font-display:swap;
      src:url('fonts/almarai-800-arabic.woff2') format('woff2');
      unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC}
    /* Arabic typography: Almarai first (Latin still falls through to the system
       stack because the font only covers Arabic ranges); connected script needs
       letter-spacing 0 everywhere; taller script wants more line room. */
    html[lang="ar"] body{
      font-family:'Almarai',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
      line-height:1.7;
    }
    html[lang="ar"] *{letter-spacing:0 !important}
    /* Room codes are Latin — keep their spaced, left-to-right look in Arabic.
       Covers: lobby hero code, QR-sheet code, in-game chip, legacy step box,
       and the join-code input (typing Latin into an RTL input scrambles it). */
    html[lang="ar"] .mstep-codebox,
    html[lang="ar"] .mstep-codebox:empty::before,
    html[lang="ar"] .mafia-code-hero .ccode,
    html[lang="ar"] #mafia-qr-sheet-code,
    html[lang="ar"] #join-code-input,
    html[lang="ar"] .mafia-ingame-code-val{letter-spacing:.1em !important;direction:ltr;unicode-bidi:isolate}
    /* RTL: directional glyphs mirror — play triangle, forward chevrons, back
       arrows. Checkmarks and other symmetric icons stay as they are. */
    [dir="rtl"] .menu-chevron,
    [dir="rtl"] .admin-tile-chevron,
    [dir="rtl"] .admin-user-row-chev,
    [dir="rtl"] .rchip-chev svg,
    [dir="rtl"] .theme-option > svg:not(.theme-option-check),
    [dir="rtl"] .join-scan-chev,
    [dir="rtl"] .mafia-xtra-trigger-chev,
    [dir="rtl"] .mafia-join-another svg,
    [dir="rtl"] .mafia-narr-next svg,
    [dir="rtl"] .icon-btn[data-i18n-aria="common.leaveGame"] svg,
    [dir="rtl"] .icon-btn[data-i18n-aria="common.back"] svg{transform:scaleX(-1)}
    a{color:var(--text);text-decoration:none;cursor:pointer}
    /* Desktop: the app reads as an APP, not a document — no I-beam text cursor
       hovering over labels/descriptions anywhere (it looks like a stray vertical
       line next to icons; Saeed flagged it). Typing fields keep the text cursor;
       interactive elements all set cursor:pointer themselves. */
    body{cursor:default}
    input,textarea{cursor:text}

    .app{max-width:480px;min-height:100vh;margin:0 auto;background:var(--bg);position:relative;display:flex;flex-direction:column}
    @media(min-width:600px){.app{box-shadow:var(--shadow-lg)}}

    .screen{display:none;flex:1;flex-direction:column;min-height:100vh}
    .screen.active{display:flex}
    /* Pre-paint screen override (set by the bootstrap script in <head>).
       When the user is already signed in OR following a deep-link into a
       lobby (?room=&game=X), this rule shows the right destination screen
       and hides Login *before paint*, eliminating the flash of login or the
       flash of "How many players?" Step 1 that otherwise appeared during
       the async auth check. The body init script syncs .active to match,
       then clears this attr so JS-driven goTo() works normally from then on. */
    html[data-boot-screen="games"] #screen-login{display:none}
    html[data-boot-screen="games"] #screen-games{display:flex}
    html[data-boot-screen="friends"] #screen-login{display:none}
    html[data-boot-screen="friends"] #screen-friends{display:flex}
    html[data-boot-screen="profile"] #screen-login{display:none}
    html[data-boot-screen="profile"] #screen-profile{display:flex}
    html[data-boot-screen="edit-profile"] #screen-login{display:none}
    html[data-boot-screen="edit-profile"] #screen-edit-profile{display:flex}
    html[data-boot-screen="feedback-board"] #screen-login{display:none}
    html[data-boot-screen="feedback-board"] #screen-feedback-board{display:flex}
    html[data-boot-screen="admin"] #screen-login{display:none}
    html[data-boot-screen="admin"] #screen-admin{display:flex}
    html[data-boot-screen="admin-feedback"] #screen-login{display:none}
    html[data-boot-screen="admin-feedback"] #screen-admin-feedback{display:flex}
    html[data-boot-screen="admin-stats"] #screen-login{display:none}
    html[data-boot-screen="admin-stats"] #screen-admin-stats{display:flex}
    html[data-boot-screen="admin-maintenance"] #screen-login{display:none}
    html[data-boot-screen="admin-maintenance"] #screen-admin-maintenance{display:flex}
    html[data-boot-screen="admin-announce"] #screen-login{display:none}
    html[data-boot-screen="admin-announce"] #screen-admin-announce{display:flex}
    html[data-boot-screen="admin-users"] #screen-login{display:none}
    html[data-boot-screen="admin-users"] #screen-admin-users{display:flex}

    /* Reconnect veil — covers the screen during a ?room= refresh / phone reopen
       so the lobby never flashes before the app routes to the right in-game
       screen. Shown by the boot script (html[data-reconnecting]); hidden by
       autoOpenFromRoomUrl once routing completes. Universal across all games. */
    #huddle-reconnect-veil{display:none}
    html[data-reconnecting] #huddle-reconnect-veil{
      display:flex;position:fixed;inset:0;z-index:9999;
      align-items:center;justify-content:center;background:var(--bg,#fff);
    }
    .huddle-reconnect-spinner{
      width:34px;height:34px;border-radius:50%;
      border:3px solid var(--border,#e5e7eb);border-top-color:var(--text,#111827);
      animation:huddleReconnectSpin .8s linear infinite;
    }
    @keyframes huddleReconnectSpin{to{transform:rotate(360deg)}}

    .header{position:sticky;top:0;z-index:10;height:calc(var(--header-h) + env(safe-area-inset-top,0px));background:var(--bg);
      border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;padding:env(safe-area-inset-top,0px) 8px 0 8px;gap:8px}
    .header-title{font-size:17px;font-weight:600;letter-spacing:-.01em;flex:1;text-align:start;padding-inline-start:8px}
    .header-title.center{text-align:center}
    .icon-btn{width:44px;height:44px;border-radius:var(--radius-pill);border:none;background:transparent;
      display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text);transition:background .15s ease;flex-shrink:0}
    .icon-btn:hover{background:var(--bg-hover)}

    .page{flex:1;padding:16px 16px calc(var(--nav-h) + 24px)}
    .page.no-nav{padding-bottom:24px}
    .page-title{font-size:26px;font-weight:700;letter-spacing:-.02em;margin:8px 0 16px}
    /* Big in-page title row (Friends/Profile, 2026-07-06 redesign) — replaces
       the sticky .header on those screens; optional sub-line + trailing button. */
    .page-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin:calc(env(safe-area-inset-top,0px) + 6px) 0 16px}
    .page-top .page-title{margin:0;font-weight:800}
    .page-top-sub{font-size:13px;color:var(--text-secondary);margin-top:3px}
    .page-top-sub:empty{display:none}
    .icon-btn-raised{background:var(--bg-subtle)}
    .section-title{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;color:var(--text-secondary);margin:24px 0 12px}

    /* Bottom nav */
    .bottom-nav{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:480px;
      height:calc(var(--nav-h) + env(safe-area-inset-bottom,0px));padding-bottom:env(safe-area-inset-bottom,0px);
      background:var(--bg);border-top:1px solid var(--border);display:flex;z-index:20}
    .nav-item{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
      color:var(--text-tertiary);font-size:11px;font-weight:500;border:none;background:transparent;cursor:pointer;padding:8px 0}
    .nav-item.active{color:var(--accent)}
    .nav-item svg{width:24px;height:24px}

    /* Buttons */
    .btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:48px;padding:0 20px;
      border-radius:var(--radius-md);border:1px solid transparent;font-weight:600;font-size:15px;cursor:pointer;
      transition:all .15s ease;width:100%}
    .btn-primary{background:var(--primary);color:var(--on-primary)}
    .btn-primary:hover{background:var(--primary-hover)}
    /* Brand-accent CTA — reserved for the ONE main action of a screen
       (Start game / Play again). Everything else stays .btn-primary. */
    .btn-accent{background:var(--accent);color:var(--on-accent)}
    .btn-accent:hover{background:var(--accent-hover)}
    /* Destructive CTA — account deletion only. Kept visually distinct from
       .btn-accent so a red button never reads as "the main action". */
    .btn-danger{background:var(--danger);color:#fff}
    .btn-danger:hover{background:var(--danger);filter:brightness(1.08)}
    .btn-outline{background:var(--bg);border-color:var(--border-strong);color:var(--text)}
    .btn-outline:hover{background:var(--bg-subtle)}
    .btn-ghost{background:transparent;color:var(--text)}
    .btn-ghost:hover{background:var(--bg-subtle)}
    .btn-sm{height:36px;padding:0 14px;font-size:14px;width:auto;border-radius:var(--radius-sm)}
    .btn-lg{height:56px;font-size:16px;border-radius:var(--radius-lg)}
    .btn-row{display:flex;gap:10px}
    .btn-row .btn{flex:1}
    /* Universal disabled state — applies to BOTH `disabled` (mid-flight RPC)
       and `aria-disabled="true"` (validation gate). Before this rule the
       four Start buttons looked identical whether dead or alive, so users
       tapped a frozen button with no feedback. Visible opacity + cursor
       turns "looks healthy but does nothing" into "obviously not ready". */
    .btn:disabled,
    .btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
    .btn:disabled:hover,
    .btn[aria-disabled="true"]:hover{background:var(--primary)}
    .btn-accent:disabled:hover,
    .btn-accent[aria-disabled="true"]:hover{background:var(--accent)}
    /* Without this the generic rule above repaints a disabled danger button
       with the PRIMARY colour on hover — i.e. the delete button would turn
       into a normal-looking button exactly when it is not usable. */
    .btn-danger:disabled:hover,
    .btn-danger[aria-disabled="true"]:hover{background:var(--danger);filter:none}
    
    [hidden]{display:none !important}
    /* Google brand button — white surface in both themes per Google's brand
       guidelines for "Continue with Google" (dark text on white).
       Uses --surface-elevated so dark mode picks up the slightly lifted card
       background rather than pure white (which would scream on a dark page). */
    .btn-google{background:var(--surface-elevated);color:var(--text);
      border:1px solid var(--border-strong);gap:12px}
    .btn-google:hover{background:var(--bg-hover)}
    .btn-google:disabled{opacity:.6;cursor:not-allowed}
    [data-theme="light"] .btn-google{background:#fff;color:#3c4043}

    /* Inputs */
    .field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
    .field label{font-size:13px;font-weight:500;color:var(--text-secondary)}
    .input{height:52px;padding:0 16px;border-radius:var(--radius-md);border:1px solid var(--border-strong);
      background:var(--bg);outline:none;width:100%;transition:border .15s ease,box-shadow .15s ease}
    .input:focus{border-color:var(--text);box-shadow:0 0 0 3px var(--focus-ring)}
    .search{position:relative;margin-bottom:16px}
    .search input{padding-inline-start:44px}
    .search-icon{position:absolute;top:50%;inset-inline-start:16px;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}

    /* Chips */
    .player-picker{display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;margin-bottom:20px;scrollbar-width:none}
    .player-picker::-webkit-scrollbar{display:none}
    .chip{flex:0 0 auto;height:38px;padding:0 16px;border-radius:var(--radius-pill);border:1px solid var(--border-strong);
      background:var(--bg);font-size:14px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;
      white-space:nowrap;transition:all .15s ease}
    .chip:hover{border-color:var(--text)}
    .chip.active{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}

    /* Player count picker (Games — step 1) */
    .badge{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;border-radius:var(--radius-pill);
      font-size:11px;font-weight:600;background:var(--bg-subtle);color:var(--text-secondary)}
    .badge svg{width:12px;height:12px}

    /* ===== Mafia "Big Play" home (Games tab) ===== */
    /* One giant round Play button straight into the lobby, centered on the
       screen. Standard theme tokens throughout so light and dark both work.
       The pulse ring is skipped for reduced-motion users. Bottom padding
       reserves room for the fixed nav. */
    .bigplay{position:relative;flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
      text-align:center;padding:24px 24px calc(var(--nav-h) + 24px)}
    /* Home-screen EN/TR language pill (top-right). Selected segment uses the
       accent, mirroring the app-wide accent-selected-state pattern. */
    .bigplay-lang{position:absolute;top:calc(env(safe-area-inset-top, 0px) + 14px);inset-inline-end:14px;display:flex;gap:2px;padding:3px;
      border:1px solid var(--border);background:var(--bg-subtle);border-radius:999px}
    .bigplay-lang-opt{border:0;background:transparent;color:var(--text-secondary);cursor:pointer;
      font:inherit;font-size:12px;font-weight:700;letter-spacing:.04em;padding:5px 11px;border-radius:999px}
    .bigplay-lang-opt:hover{color:var(--text)}
    .bigplay-lang-opt.active{background:var(--accent);color:var(--on-accent)}
    .bigplay-wordmark{margin:0;font-size:30px;font-weight:800;letter-spacing:-.02em}
    .bigplay-tagline{margin:6px 0 34px;font-size:13.5px;color:var(--text-secondary)}
    .bigplay-btn{width:158px;height:158px;border-radius:50%;border:0;background:var(--accent);cursor:pointer;
      display:flex;align-items:center;justify-content:center;position:relative;
      box-shadow:0 0 0 14px var(--accent-soft),var(--shadow-lg);
      transition:transform .15s ease,background .15s ease}
    .bigplay-btn:hover{background:var(--accent-hover)}
    .bigplay-btn:active{transform:scale(.97)}
    /* physical margin-left (not inline-start): the play triangle points right in
       ALL languages, so its optical-centering nudge must stay rightward in RTL too */
    .bigplay-btn svg{width:52px;height:52px;fill:var(--on-accent);margin-left:8px}
    @media (prefers-reduced-motion: no-preference){
      .bigplay-btn::after{content:"";position:absolute;inset:-14px;border-radius:50%;
        border:2px solid var(--accent);opacity:0;animation:bigplayPulse 2.4s ease-out infinite}
      @keyframes bigplayPulse{0%{transform:scale(.92);opacity:.5}70%{transform:scale(1.14);opacity:0}100%{opacity:0}}
    }
    .bigplay-word{margin-top:20px;font-size:15px;font-weight:800;letter-spacing:.14em;text-transform:uppercase}
    .bigplay-meta{font-size:12.5px;color:var(--text-secondary);margin-top:6px}
    .bigplay-pills{display:flex;gap:10px;margin-top:32px}
    .bigplay-pills button{border:1px solid var(--border);background:var(--bg-subtle);color:var(--text);
      font:inherit;font-size:13px;font-weight:600;border-radius:var(--radius-pill);padding:10px 16px;cursor:pointer;
      transition:background .15s ease,border-color .15s ease}
    .bigplay-pills button:hover{border-color:var(--border-strong);background:var(--bg-hover)}

    /* Tabs */
    .tabs{display:flex;gap:6px;border-bottom:1px solid var(--border);margin-bottom:16px;overflow-x:auto;scrollbar-width:none}
    .tabs::-webkit-scrollbar{display:none}
    .tab{padding:12px 4px;margin-inline-end:18px;background:none;border:none;font-weight:500;font-size:15px;
      color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap}
    .tab.active{color:var(--text);border-bottom-color:var(--text)}

    /* Friend rows */
    .friend-row{display:flex;align-items:center;gap:12px;padding:12px 4px;border-bottom:1px solid var(--border)}
    .friend-row:last-child{border-bottom:none}
    .friend-row .friend-info{flex:1;min-width:0}
    .friend-row .friend-name{font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .friend-row .friend-status{font-size:13px;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .friend-row-actions{display:flex;gap:6px;align-items:center;flex-shrink:0}
    .friend-empty{padding:24px 4px;text-align:center;color:var(--text-secondary);font-size:14px;line-height:1.5}
    /* Skeleton row — surfaced while the first friends fetch is in flight so
       users on slow networks don't see the misleading "no friends yet" hero
       before their real friends arrive. Reusable container + shimmer pulse. */
    .huddle-skeleton-list{display:flex;flex-direction:column;gap:0}
    .huddle-skeleton-row{display:flex;align-items:center;gap:12px;padding:12px 4px;border-bottom:1px solid var(--border)}
    .huddle-skeleton-circle{width:40px;height:40px;border-radius:50%;background:var(--bg-subtle);position:relative;overflow:hidden;flex-shrink:0}
    .huddle-skeleton-bar{height:12px;border-radius:6px;background:var(--bg-subtle);position:relative;overflow:hidden}
    .huddle-skeleton-bar.short{width:55%}
    .huddle-skeleton-bar.tiny{width:30%;height:10px;margin-top:6px}
    .huddle-skeleton-stack{flex:1;display:flex;flex-direction:column;gap:0}
    .huddle-skeleton-circle::after,.huddle-skeleton-bar::after{
      content:"";position:absolute;inset:0;
      background:linear-gradient(90deg,transparent 0,rgba(255,255,255,.45) 50%,transparent 100%);
      animation:huddle-skel-shimmer 1.4s ease-in-out infinite;
    }
    [data-theme="dark"] .huddle-skeleton-circle::after,
    [data-theme="dark"] .huddle-skeleton-bar::after{
      background:linear-gradient(90deg,transparent 0,rgba(255,255,255,.07) 50%,transparent 100%);
    }
    @keyframes huddle-skel-shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
    @media (prefers-reduced-motion: reduce){
      .huddle-skeleton-circle::after,.huddle-skeleton-bar::after{animation:none}
    }
    /* Offline banner — slim pill at the very top of the viewport, above all
       app chrome. Neutral grey, soft pulse on the dot so the user knows the
       app is working on it. Sits in safe-area-inset-top on iOS notch phones. */
    .huddle-offline-banner{
      position:fixed;left:50%;top:calc(env(safe-area-inset-top,0px) + 8px);
      transform:translateX(-50%);
      display:flex;align-items:center;gap:8px;
      padding:8px 14px;border-radius:999px;
      background:var(--bg-subtle);color:var(--text);
      border:1px solid var(--border-strong);
      font-size:13px;font-weight:600;letter-spacing:.01em;
      box-shadow:var(--shadow-md);
      z-index:9999;pointer-events:none;
    }
    .huddle-offline-banner[hidden]{display:none}
    .huddle-offline-dot{
      width:8px;height:8px;border-radius:50%;background:var(--text-secondary);
      animation:huddle-offline-pulse 1.4s ease-in-out infinite;
    }
    @keyframes huddle-offline-pulse{0%,100%{opacity:.35}50%{opacity:1}}
    @media (prefers-reduced-motion: reduce){.huddle-offline-dot{animation:none;opacity:.7}}

    /* ===== Announcement banner (in-flow strip at the top of the app) =====
       Admin-posted, shown to everyone, dismissible. Accent-soft tint so it
       reads as "news" without shouting. Themes via CSS vars (dark + light). */
    .huddle-announce{
      display:flex;align-items:center;gap:10px;
      padding:10px;padding-inline-start:14px;
      background:var(--accent-soft);
      border-bottom:1px solid var(--border);
      color:var(--text);
    }
    .huddle-announce[hidden]{display:none}
    .huddle-announce-icon{width:17px;height:17px;flex-shrink:0;color:var(--accent)}
    .huddle-announce-text{
      flex:1;min-width:0;font-size:13px;font-weight:600;line-height:1.35;
      overflow-wrap:anywhere
    }
    .huddle-announce-close{
      flex-shrink:0;width:28px;height:28px;border:none;background:transparent;
      color:var(--text-secondary);cursor:pointer;border-radius:var(--radius-pill);
      display:flex;align-items:center;justify-content:center;
      transition:background .15s ease
    }
    .huddle-announce-close:hover{background:var(--bg-hover)}
    .huddle-announce-close svg{width:16px;height:16px}

    /* ===== Maintenance screen (full-screen overlay; admins bypass) =====
       Shown via html[data-maintenance] to non-admin players when the owner
       flips maintenance ON. Opaque theme background so nothing shows behind. */
    #huddle-maintenance{display:none}
    html[data-maintenance] #huddle-maintenance{
      display:flex;position:fixed;inset:0;z-index:100000;
      align-items:center;justify-content:center;
      padding:24px calc(24px + env(safe-area-inset-right,0px)) 24px calc(24px + env(safe-area-inset-left,0px));
      background:var(--bg)
    }
    .huddle-maintenance-card{
      display:flex;flex-direction:column;align-items:center;text-align:center;
      gap:14px;max-width:340px
    }
    .huddle-maintenance-icon{
      width:64px;height:64px;flex-shrink:0;border-radius:var(--radius-pill);
      display:flex;align-items:center;justify-content:center;
      background:var(--bg-subtle);border:1px solid var(--border);color:var(--text-secondary)
    }
    .huddle-maintenance-icon svg{width:30px;height:30px}
    .huddle-maintenance-title{
      margin:0;font-size:22px;font-weight:800;letter-spacing:-.02em;color:var(--text)
    }
    .huddle-maintenance-msg{
      margin:0;font-size:14.5px;line-height:1.5;color:var(--text-secondary);
      overflow-wrap:anywhere
    }
    /* Rich empty state for the Friends "All" tab — visual cue for new users to use the search bar */
    .friends-empty-hero{display:flex;flex-direction:column;align-items:center;text-align:center;padding:36px 24px 24px;gap:14px}
    .friends-empty-icon{width:80px;height:80px;border-radius:50%;background:var(--bg-subtle);display:flex;align-items:center;justify-content:center;color:var(--text-secondary)}
    .friends-empty-icon svg{width:40px;height:40px}
    .friends-empty-title{font-size:20px;font-weight:700;color:var(--text);letter-spacing:-.01em;margin-top:4px}
    .friends-empty-sub{font-size:14px;color:var(--text-secondary);max-width:280px;line-height:1.5}
    /* Subtle glow on the search bar when it's the focal point for a new user */
    .search.search-glow{box-shadow:0 0 0 3px var(--focus-ring);animation:friendsSearchPulse 2s ease-in-out infinite}
    @keyframes friendsSearchPulse{0%,100%{box-shadow:0 0 0 0 var(--focus-ring)}50%{box-shadow:0 0 0 6px var(--focus-ring)}}
    /* One-shot pulse fired when the user taps the header "add friend" icon —
       the class is removed in JS on animationend so the next tap can replay it. */
    .search.search-tap-pulse{animation:friendsSearchTapPulse .9s ease-out}
    @keyframes friendsSearchTapPulse{
      0%{box-shadow:0 0 0 0 var(--focus-ring)}
      40%{box-shadow:0 0 0 8px var(--focus-ring)}
      100%{box-shadow:0 0 0 0 rgba(0,0,0,0)}
    }

    /* Custom confirm dialog — replaces native confirm(). Reuses the sheet-backdrop scrim. */
    .hc-backdrop{align-items:center;justify-content:center;padding:24px}
    .hc-dialog{background:var(--surface-elevated);border-radius:var(--radius-lg);padding:22px 22px 16px;max-width:340px;width:100%;
      box-shadow:0 20px 48px rgba(0,0,0,.18);border:1px solid var(--border);
      transform:scale(.96);opacity:0;transition:transform .18s ease, opacity .18s ease}
    [data-theme="dark"] .hc-dialog{box-shadow:0 20px 48px rgba(0,0,0,.6)}
    .hc-backdrop.active .hc-dialog{transform:scale(1);opacity:1}
    .hc-title{font-size:17px;font-weight:700;color:var(--text);margin-bottom:6px;line-height:1.3}
    .hc-body{font-size:14px;color:var(--text-secondary);line-height:1.5;margin-bottom:18px}
    .hc-actions{display:flex;gap:8px;justify-content:flex-end}
    .hc-actions .btn{padding:10px 16px;font-size:14px;min-width:88px}
    .hc-confirm.is-danger{background:var(--danger);color:#fff}
    .hc-confirm.is-danger:hover{filter:brightness(1.05)}
    .friend-remove-btn{background:none;border:none;color:var(--text-secondary);font-size:13px;padding:6px 10px;cursor:pointer;border-radius:var(--radius-sm)}
    .friend-remove-btn:hover{background:var(--bg-subtle);color:var(--text)}
    /* Compact "who you're acting on" header inside the friend action sheet —
       avatar + name so the destructive action below has unambiguous context. */
    .friend-menu-header{
      display:flex;align-items:center;gap:12px;
      padding:10px 16px 12px;margin:0 4px 4px;
      border-bottom:1px solid var(--border);
    }
    .friend-menu-header .friend-menu-name{font-size:15px;font-weight:600;color:var(--text);line-height:1.2}
    .friend-menu-header .friend-menu-handle{font-size:13px;color:var(--text-secondary);margin-top:2px}
    /* Offline-friend row — dim avatar + soften name. Discord/Instagram pattern:
       presence is signalled by the green dot, absence by visual recession (not text). */
    .friend-row.is-offline .av{opacity:.55;filter:grayscale(.4)}
    .friend-row.is-offline .friend-name{color:var(--text-secondary);font-weight:600}
    .friend-status-pill{display:inline-flex;align-items:center;gap:4px;font-size:13px;color:var(--success);font-weight:600;padding:6px 10px}
    /* "Table & Tiles" friends redesign (2026-07-06): request rows live in a
       bordered card; accepted friends render as lobby-seat-style avatar chips.
       Tapping a chip opens the same ⋯ friend menu (whole chip = the button). */
    .friends-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);overflow:hidden}
    .friends-card .friend-row{padding:12px 14px}
    .friends-crew{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
    .friend-chip{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;
      padding:12px 4px 10px;border:1px solid var(--border);border-radius:14px;background:var(--bg);
      cursor:pointer;transition:background .15s ease,border-color .15s ease}
    .friend-chip:hover{background:var(--bg-subtle)}
    .friend-chip:active{background:var(--bg-hover)}
    .friend-chip-name{font-size:11.5px;font-weight:600;color:var(--text);
      max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .friend-chip.is-offline .av{opacity:.55;filter:grayscale(.4)}
    .friend-chip.is-offline .friend-chip-name{color:var(--text-secondary)}
    .friend-chip-add{border:1.5px dashed var(--border-strong);background:var(--bg-subtle)}
    .friend-chip-add:hover{border-color:var(--text)}
    .friend-chip-plus{width:46px;height:46px;border-radius:50%;display:flex;align-items:center;justify-content:center;
      font-size:24px;font-weight:600;color:var(--text-secondary)}
    .friend-chip-add .friend-chip-name{color:var(--text-secondary)}
    #friends-search-results:not(:empty){margin-top:8px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);overflow:hidden}
    #friends-search-results .friend-row{padding:10px 12px}
    #friends-search-results .friend-row:last-child{border-bottom:none}
    .friends-search-msg{padding:12px;font-size:13px;color:var(--text-secondary);text-align:center}
    .avatar{width:44px;height:44px;border-radius:var(--radius-pill);
      background:linear-gradient(135deg,#e4e4e4 0%,#cfcfcf 100%);
      display:flex;align-items:center;justify-content:center;font-weight:600;color:var(--text);
      flex-shrink:0;position:relative;font-size:15px}
    .avatar.online::after{content:"";position:absolute;bottom:0;inset-inline-end:0;width:12px;height:12px;
      background:var(--success);border:2px solid var(--bg);border-radius:var(--radius-pill)}
    .friend-info{flex:1;min-width:0}
    .friend-name{font-weight:600;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .friend-status{font-size:13px;color:var(--text-secondary)}

    /* Lobby — Invite friends section */
    .lobby-invite-section{margin-top:18px}
    /* Borderless list — rows live directly on the sheet surface, separated by hairlines
       only. Avoids the "card-inside-a-card" feel of the previous bordered container.
       Row density: 10px vertical padding + 40px avatar = ~60px tap-target rows,
       comfortable on mobile and dense enough to surface ~5-6 friends without scrolling. */
    /* Defensive override: .sheet-body sets white-space:pre-line, which makes the HTML
       whitespace between rendered child divs render as literal blank lines and visually
       bloats each invite row. Reset here so rows are flush regardless of source indent. */
    #lobby-invite-sheet-content{white-space:normal}
    .lobby-invite-list{display:flex;flex-direction:column;gap:2px;background:transparent}
    /* "Tap the Person": each tile IS the button — tap to invite, tap again to
       cancel. Rounded rows with a soft hover, no separators; the invited row
       gets an accent tint + accent ring on the avatar. */
    .lobby-invite-tile{display:flex;align-items:center;gap:10px;padding:8px 8px;width:100%;
      border:0;background:none;font:inherit;color:var(--text);text-align:start;cursor:pointer;
      border-radius:12px;transition:background .12s ease}
    .lobby-invite-tile:hover:not(:disabled){background:var(--bg-subtle)}
    .lobby-invite-tile:disabled{cursor:default}
    .lobby-invite-tile.is-invited{background:var(--accent-soft)}
    .lobby-invite-tile.is-invited .av{box-shadow:0 0 0 2px var(--accent)}
    /* Offline-friend dimming mirrors the Friends-screen pattern (.friend-row.is-offline)
       so users see a consistent visual hierarchy between the two surfaces. */
    .lobby-invite-tile.is-offline .av{opacity:.55;filter:grayscale(.4)}
    .lobby-invite-tile.is-offline .friend-name{color:var(--text-secondary)}
    /* Tight section header — separates Online from Offline groups in the invite list.
       Only rendered when BOTH groups have entries (see renderLobbyInviteSheetContent). */
    .lobby-invite-section{
      display:flex;align-items:center;gap:6px;
      padding:10px 4px 4px;
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-tertiary);
    }
    .lobby-invite-section-count{
      color:var(--text-tertiary);font-weight:600;letter-spacing:0;text-transform:none;
    }
    /* Highlighted how-it-works hint — one line, accent-tinted, top of the sheet. */
    .lobby-invite-hint{display:flex;align-items:center;gap:9px;background:var(--accent-soft);
      border:1.5px solid var(--accent);border-radius:12px;padding:9px 12px;margin:2px 0 10px}
    .lobby-invite-hint-icon{font-size:16px;flex-shrink:0;line-height:1}
    .lobby-invite-hint-txt{font-size:12px;font-weight:700;color:var(--accent);line-height:1.35}
    /* Search input — only rendered when friend count crosses the scan-friction threshold
       (set in renderLobbyInviteSheetContent). Sits flush with the row left-edge for visual
       alignment. */
    .lobby-invite-search-wrap{position:relative;margin-bottom:6px}
    .lobby-invite-search-wrap svg{position:absolute;inset-inline-start:10px;top:50%;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}
    .lobby-invite-search{
      width:100%;
      padding:9px 12px;padding-inline-start:36px;
      background:var(--bg-subtle);
      border:1px solid transparent;
      border-radius:var(--radius-lg);
      font-size:14px;
      color:var(--text);
      outline:none;
      transition:border-color .15s ease, background .15s ease;
    }
    .lobby-invite-search:focus{border-color:var(--primary);background:var(--bg)}
    .lobby-invite-search::placeholder{color:var(--text-secondary)}
    .lobby-invite-no-match{padding:18px 4px;text-align:center;color:var(--text-secondary);font-size:13px}
    .lobby-invite-tile .friend-info{flex:1;min-width:0}
    .lobby-invite-actions{display:flex;gap:6px;align-items:center;flex-shrink:0}
    /* Row-end state labels. "Tap to invite" = quiet self-explaining affordance;
       "Invited ✓ / tap to cancel" = accent, with the cancel hint exactly where
       it applies; "Joined" = passive green confirmation (text + check only). */
    .lobby-invite-tap{font-size:11px;font-weight:600;color:var(--text-tertiary);flex-shrink:0}
    .lobby-invite-sent{font-size:11px;font-weight:800;color:var(--accent);text-align:end;line-height:1.3;flex-shrink:0}
    .lobby-invite-sent small{display:block;font-size:9px;font-weight:600;color:var(--text-secondary)}
    .lobby-invite-btn.joined{border:0;color:var(--success);background:transparent;cursor:default;
      font-weight:600;font-size:13px;padding:8px 6px;display:inline-flex;align-items:center;gap:5px}
    .lobby-invite-btn.joined svg{opacity:.85}
    .lobby-invite-empty{padding:14px;border:1px dashed var(--border);border-radius:var(--radius-lg);
      color:var(--text-secondary);font-size:13px;text-align:center;cursor:pointer;background:var(--bg)}
    .lobby-invite-empty:hover{background:var(--bg-subtle);color:var(--text)}

    /* Incoming invite banner (top-of-screen) */
    .invite-banner{position:fixed;top:0;left:0;right:0;z-index:9999;
      padding:calc(env(safe-area-inset-top, 0px) + 10px) 14px 12px;
      background:var(--bg);border-bottom:1px solid var(--border);
      box-shadow:0 4px 16px rgba(0,0,0,.08);
      transform:translateY(-110%);transition:transform .28s ease;
      display:flex;align-items:center;gap:12px}
    [data-theme="dark"] .invite-banner{box-shadow:0 4px 20px rgba(0,0,0,.55)}
    .invite-banner.show{transform:translateY(0)}
    .invite-banner-body{flex:1;min-width:0}
    .invite-banner-text{font-size:14px;line-height:1.35;color:var(--text);overflow:hidden;text-overflow:ellipsis}
    .invite-banner-text strong{font-weight:700}
    .invite-banner-actions{display:flex;gap:6px;flex-shrink:0}
    .invite-banner-actions .btn{padding:7px 12px;font-size:13px;border-radius:var(--radius-pill)}

    /* Friend-request banner — shares the invite-banner shell; adds a thin
       countdown bar along the bottom edge that empties over the auto-dismiss
       window (restarted from JS each time the banner shows). */
    .friend-banner-progress{
      position:absolute;left:0;right:0;bottom:0;height:3px;
      background:var(--accent);transform-origin:left;transform:scaleX(0);
      pointer-events:none;
    }
    /* RTL: drain the bar toward the reading direction (right→left). */
    [dir="rtl"] .friend-banner-progress{transform-origin:right}
    /* Respect reduced-motion: no shrinking bar, just a static rule. The 25s
       auto-dismiss timer is JS-driven, so the behaviour is unchanged. */
    @media (prefers-reduced-motion: reduce){
      .friend-banner.show .friend-banner-progress{animation:none;transform:scaleX(1);opacity:.35}
    }
    .friend-banner.show .friend-banner-progress{
      animation:friend-banner-countdown var(--fb-secs,25s) linear forwards;
    }
    @keyframes friend-banner-countdown{from{transform:scaleX(1)}to{transform:scaleX(0)}}

    /* "+ add friend" badge pinned to lobby avatars. Lives on the .av-shell
       wrapper (same sibling pattern as the presence dot — .av clips its own
       overflow, so the badge must sit OUTSIDE it). States: default = orange
       "+" (send request), .incoming = green (they already asked — tap accepts),
       .sent = quiet gray check, not tappable. */
    .av-friend-badge{
      position:absolute;
      inset-inline-end:calc(var(--size) * -0.08);
      bottom:calc(var(--size) * -0.08);
      width:max(21px, calc(var(--size) * .36));
      height:max(21px, calc(var(--size) * .36));
      display:flex;align-items:center;justify-content:center;
      background:var(--accent);color:var(--on-accent);
      border:2px solid var(--bg);border-radius:50%;
      padding:0;cursor:pointer;font:inherit;
      box-shadow:0 1px 4px rgba(0,0,0,.2);
      z-index:2;
      transition:transform .12s ease;
    }
    .av-friend-badge svg{width:58%;height:58%}
    .av-friend-badge:active{transform:scale(.9)}
    .av-friend-badge.incoming{background:var(--success);color:#fff}
    /* 'sent' stays visually quiet (it's a status, not a call to action) but IS
       tappable — it opens the "cancel this request" popup, so keep the pointer. */
    .av-friend-badge.sent{background:var(--bg-hover);color:var(--text-secondary);box-shadow:none}

    /* Add-friend popup — centered dialog, same pattern as the roles editor
       (#mafia-roles-backdrop). Compact: avatar, question, one accent CTA. */
    #friend-add-backdrop{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.45);
      opacity:0;pointer-events:none;transition:opacity .2s ease;
      display:flex;align-items:center;justify-content:center;padding:16px}
    #friend-add-backdrop.active{opacity:1;pointer-events:auto}
    .friend-add-dialog{width:100%;max-width:340px;background:var(--bg);
      border-radius:20px;padding:26px 18px 16px;position:relative;text-align:center;
      transform:scale(.95);transition:transform .2s cubic-bezier(.3,.9,.4,1);
      box-shadow:0 22px 60px rgba(0,0,0,.4)}
    #friend-add-backdrop.active .friend-add-dialog{transform:scale(1)}
    .friend-add-avatar{display:flex;justify-content:center;margin-bottom:12px}
    .friend-add-title{font-size:18px;font-weight:800;line-height:1.3;margin-bottom:6px;overflow-wrap:anywhere}
    .friend-add-body{font-size:13.5px;color:var(--text-secondary);line-height:1.5}

    /* Profile — "Player Card" (2026-07-06 redesign). The card is DELIBERATELY
       dark in both themes (same choice as the old room-code card): it uses the
       --room-grad-* tokens and fixed white text, which is the documented
       exception to the no-hardcoded-white rule for stay-dark gradients. */
    .profile-card{position:relative;overflow:hidden;border-radius:var(--radius-xl);
      padding:26px 18px 28px;text-align:center;
      background:linear-gradient(150deg,var(--room-grad-from),var(--room-grad-to));
      display:flex;flex-direction:column;align-items:center}
    .profile-card .av{box-shadow:0 0 0 3px rgba(255,255,255,.25)}
    .profile-card-name{font-size:22px;font-weight:800;letter-spacing:-.01em;margin-top:12px;color:#fff}
    .profile-card-username{font-size:13.5px;color:rgba(255,255,255,.65)}
    .profile-card-edit{position:absolute;top:12px;inset-inline-end:12px;width:38px;height:38px;
      border-radius:var(--radius-pill);border:none;cursor:pointer;
      background:rgba(255,255,255,.14);color:#fff;
      display:flex;align-items:center;justify-content:center;transition:background .15s ease}
    .profile-card-edit:hover{background:rgba(255,255,255,.24)}
    .menu-list{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--bg)}
    .menu-item{display:flex;align-items:center;gap:14px;padding:14px 16px;border-bottom:1px solid var(--border);
      cursor:pointer;transition:background .15s ease;background:var(--bg)}
    .menu-item:last-child{border-bottom:none}
    .menu-item:hover{background:var(--bg-subtle)}
    .menu-item svg.menu-icon{width:20px;height:20px;color:var(--text-secondary);flex-shrink:0}
    .menu-item .menu-label{flex:1;font-weight:500}
    .menu-item .menu-value{color:var(--text-secondary);font-size:14px}
    .menu-item .menu-chevron{color:var(--text-tertiary)}
    .menu-item.danger .menu-label,.menu-item.danger svg.menu-icon{color:var(--danger)}
    .menu-item.menu-item-info{cursor:default}
    .menu-item.menu-item-info:hover{background:var(--bg)}
    .menu-item.menu-item-info .menu-label{display:flex;flex-direction:column;gap:2px;min-width:0}
    .menu-item.menu-item-info .menu-info-caption{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-tertiary)}
    .menu-item.menu-item-info .menu-info-value{font-size:14px;font-weight:500;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    /* Small inline pill used on menu rows (e.g. Admin → "Owner") */
    .menu-pill{
      display:inline-flex;align-items:center;height:20px;padding:0 8px;
      border-radius:var(--radius-pill);border:1px solid var(--border-strong);
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
      flex-shrink:0
    }

    /* ===== Admin panel ===== */
    .admin-page{padding-top:8px}
    .admin-hero{padding:8px 0 20px}   /* 0 side-pad so hero aligns with the tile grid */
    .admin-hero-badge{
      display:inline-flex;align-items:center;gap:6px;
      padding:5px 11px;border-radius:var(--radius-pill);
      background:var(--accent-soft);border:none;
      color:var(--accent);font-size:11px;font-weight:800;
      letter-spacing:.06em;text-transform:uppercase;margin-bottom:14px
    }
    .admin-hero-badge svg{width:13px;height:13px}
    .admin-hero-title{font-size:30px;font-weight:800;letter-spacing:-.02em;margin:0 0 8px}
    .admin-hero-sub{margin:0;color:var(--text-secondary);font-size:14px;line-height:1.5;max-width:34ch}
    .admin-grid{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:1fr;gap:12px}

    /* Colourful tiles — each carries its tool's --tc (set inline in the HTML).
       Vertical layout: solid colour icon chip on top, title (+ optional badge),
       desc, and a corner chevron. Soft tinted card + hairline colour border so
       the tint reads in BOTH themes. Disabled Reports tile stays neutral grey. */
    .admin-tile{
      --tc:var(--border-strong);
      position:relative;text-align:start;
      display:flex;flex-direction:column;
      padding:15px 15px 16px;
      background:color-mix(in srgb,var(--tc) 12%,var(--bg));
      border:1px solid color-mix(in srgb,var(--tc) 26%,transparent);
      border-radius:20px;
      color:var(--text);font:inherit;cursor:pointer;
      transition:transform .15s ease, box-shadow .15s ease;
      min-height:132px
    }
    .admin-tile.is-live:hover{transform:translateY(-2px);box-shadow:0 8px 22px color-mix(in srgb,var(--tc) 30%,transparent)}
    .admin-tile.is-live:active{transform:translateY(0)}
    .admin-tile:disabled{cursor:not-allowed;background:var(--bg-subtle);border-color:var(--border)}
    .admin-tile-icon{
      width:42px;height:42px;flex-shrink:0;margin-bottom:12px;
      display:flex;align-items:center;justify-content:center;
      border-radius:13px;
      background:var(--tc);color:#fff
    }
    .admin-tile:disabled .admin-tile-icon{background:var(--border-strong);color:var(--text-tertiary)}
    .admin-tile-icon svg{width:22px;height:22px}
    .admin-tile-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
    /* Title + optional status/count badge share a flex row — flexbox guarantees
       they never collide for any badge width. Chevron sits bottom-right, so the
       DESC keeps a little right-clearance. */
    .admin-tile-titlerow{display:flex;align-items:center;gap:6px}
    .admin-tile-titlerow > .admin-tile-title{flex:1;min-width:0;overflow-wrap:anywhere}
    .admin-tile-title{font-size:15px;font-weight:800;line-height:1.2;letter-spacing:-.01em}
    .admin-tile-desc{font-size:12.5px;line-height:1.4;color:var(--text-secondary);padding-inline-end:22px}
    .admin-tile-chevron{position:absolute;inset-inline-end:13px;bottom:13px;color:var(--tc);opacity:.75}
    .admin-tile-badge{
      display:inline-flex;align-items:center;height:20px;padding:0 8px;
      border-radius:var(--radius-pill);flex-shrink:0;
      font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase
    }
    /* "1 new" count pill — solid tool colour. */
    .admin-tile-badge-next{background:var(--tc);color:#fff}
    /* "On" pill — a control (maintenance / announcement) is currently live.
       Text mixed toward --text so the light amber stays legible on its own tint. */
    .admin-tile-badge-live{
      background:color-mix(in srgb,var(--tc) 22%,var(--bg));
      color:color-mix(in srgb,var(--tc) 62%,var(--text))
    }
    /* "Coming soon" pill sits IN FLOW at the bottom of the disabled Reports tile. */
    .admin-tile-body > .admin-tile-badge{
      align-self:flex-start;margin-top:8px;
      background:var(--bg-hover);color:var(--text-tertiary)
    }
    .admin-footnote{
      margin:20px 4px 0;color:var(--text-tertiary);
      font-size:12px;line-height:1.5;text-align:center
    }

    /* ===== Admin → settings editors (Maintenance mode + Announcements) ===== */
    /* Per-tool accent, scoped to each editor screen. */
    #screen-admin-maintenance{--tc:#d97706}   /* amber-600: darker than #f59e0b so white icons + tinted text pass contrast in light mode */
    #screen-admin-announce{--tc:#8b5cf6}
    .admin-settings-page{padding-top:10px}
    /* Coloured icon header — gives each editor its tool identity. */
    .admin-settings-head{display:flex;align-items:center;gap:13px;margin:2px 0 16px}
    .admin-settings-head-ic{
      width:46px;height:46px;flex-shrink:0;border-radius:13px;
      display:flex;align-items:center;justify-content:center;
      background:var(--tc,var(--accent));color:#fff
    }
    .admin-settings-head-ic svg{width:23px;height:23px}
    .admin-settings-head-title{font-size:18px;font-weight:800;letter-spacing:-.01em;line-height:1.15}
    .admin-settings-head-sub{font-size:12.5px;color:var(--text-secondary);margin-top:2px}
    .admin-settings-lead{
      margin:0 0 16px;color:var(--text-secondary);
      font-size:13.5px;line-height:1.5
    }
    /* On/off toggle row — iOS-style switch, accent when on. */
    .admin-toggle-row{
      display:flex;align-items:center;gap:14px;width:100%;text-align:start;
      padding:14px 16px;margin-bottom:18px;
      background:var(--surface);border:1px solid var(--border);
      border-radius:var(--radius-lg);color:var(--text);font:inherit;cursor:pointer;
      transition:border-color .15s ease,background .15s ease
    }
    .admin-toggle-row[aria-pressed="true"]{
      border-color:var(--tc,var(--accent));
      background:color-mix(in srgb,var(--tc,var(--accent)) 9%,var(--bg))
    }
    .admin-toggle-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
    .admin-toggle-name{font-size:15px;font-weight:700;letter-spacing:-.01em}
    .admin-toggle-tag{font-size:12px;line-height:1.35;color:var(--text-secondary)}
    .admin-toggle-switch{
      position:relative;width:44px;height:26px;flex-shrink:0;border-radius:999px;
      background:var(--border-strong);transition:background-color .15s ease
    }
    .admin-toggle-switch::after{
      content:"";position:absolute;top:3px;inset-inline-start:3px;width:20px;height:20px;border-radius:50%;
      background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.28);transition:transform .15s ease
    }
    .admin-toggle-row[aria-pressed="true"] .admin-toggle-switch{background:var(--tc,var(--accent))}
    .admin-toggle-row[aria-pressed="true"] .admin-toggle-switch::after{transform:translateX(18px)}
    [dir="rtl"] .admin-toggle-row[aria-pressed="true"] .admin-toggle-switch::after{transform:translateX(-18px)}
    /* Message fields grouped into one card — cleaner than loose stacked fields. */
    .admin-settings-fields{
      background:var(--surface);border:1px solid var(--border);
      border-radius:var(--radius-lg);padding:4px 16px 16px
    }
    .admin-settings-field{padding-top:14px}
    .admin-settings-field label{
      display:block;font-size:12.5px;font-weight:600;color:var(--text-secondary);margin-bottom:6px
    }
    .admin-settings-textarea{
      width:100%;box-sizing:border-box;resize:vertical;min-height:48px;line-height:1.45;
      font:inherit;font-size:14px
    }
    .admin-settings-hint{
      margin:8px 0 0;color:var(--text-tertiary);font-size:12px;line-height:1.45
    }
    .admin-settings-preview-label{
      margin:22px 0 8px;color:var(--text-tertiary);
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase
    }
    .admin-announce-preview{
      border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden
    }
    .admin-announce-preview.is-empty{
      padding:16px;color:var(--text-tertiary);font-size:13px;text-align:center;
      background:var(--bg-subtle)
    }
    /* The preview reuses the real .huddle-announce strip; strip its fixed edges
       so it sits cleanly inside the rounded preview frame. */
    .admin-announce-preview-strip{border-bottom:none}
    .admin-settings-save{
      width:100%;margin-top:22px;height:52px;font-size:15px;font-weight:800;
      border:none;border-radius:15px;
      background:linear-gradient(135deg,#f97316,#ea580c);color:#fff;
      box-shadow:0 8px 20px rgba(249,115,22,.28)
    }
    .admin-settings-save.is-saved{
      background:var(--success,#2e7d32);box-shadow:none
    }

    /* ===== Admin → Users (list + detail sheet) ===== */
    /* indigo tool accent — also on the detail sheet (a sibling of the screen,
       so the screen's --tc would not otherwise cascade into it). */
    #screen-admin-users,#admin-user-backdrop{--tc:#6366f1}
    .admin-users-page{padding-top:8px}
    .admin-users-count{
      margin:2px 0 10px;color:var(--text-tertiary);
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase
    }
    .admin-user-row{
      width:100%;text-align:start;display:flex;align-items:center;gap:12px;
      padding:12px 14px;margin-bottom:10px;
      background:var(--surface);border:1px solid var(--border);
      border-radius:16px;color:var(--text);font:inherit;cursor:pointer;
      box-shadow:0 3px 12px rgba(0,0,0,.04);
      transition:border-color .15s ease,background .15s ease,transform .15s ease
    }
    [data-theme="dark"] .admin-user-row{box-shadow:none}
    .admin-user-row:hover{border-color:var(--tc);background:var(--bg-subtle)}
    .admin-user-row-av{flex-shrink:0;width:40px;height:40px}
    .admin-user-row-body{flex:1;min-width:0}
    .admin-user-row-name{
      font-size:14.5px;font-weight:600;color:var(--text);
      display:flex;align-items:center;gap:6px;
      overflow:hidden;white-space:nowrap;text-overflow:ellipsis
    }
    .admin-user-row-sub{
      font-size:12.5px;color:var(--text-secondary);margin-top:2px;
      overflow:hidden;white-space:nowrap;text-overflow:ellipsis
    }
    .admin-user-row-chev{color:var(--text-tertiary);flex-shrink:0}

    /* User detail sheet (bottom drawer; centered card on wide screens) */
    .admin-user-sheet{
      background:var(--surface-elevated);
      border-radius:var(--radius-lg) var(--radius-lg) 0 0;
      padding:6px 20px calc(20px + env(safe-area-inset-bottom));
      width:100%;max-width:480px;
      box-shadow:0 -8px 24px rgba(0,0,0,.08);
      transform:translateY(100%);transition:transform .22s ease
    }
    [data-theme="dark"] .admin-user-sheet{box-shadow:0 -8px 24px rgba(0,0,0,.4)}
    .sheet-backdrop.active .admin-user-sheet{transform:translateY(0)}
    .admin-user-handle{width:36px;height:4px;border-radius:2px;background:var(--border-strong);margin:8px auto 14px;opacity:.55}
    .admin-user-head{display:flex;align-items:center;gap:14px;margin-bottom:16px}
    .admin-user-head-text{min-width:0;flex:1}
    .admin-user-head-name{
      font-size:18px;font-weight:700;color:var(--text);letter-spacing:-.01em;
      display:flex;align-items:center;gap:8px;flex-wrap:wrap
    }
    .admin-user-head-handle{font-size:13px;color:var(--text-secondary);margin-top:2px}
    .admin-user-info{
      border:1px solid var(--border);border-radius:var(--radius-md);
      overflow:hidden;margin-bottom:16px
    }
    .admin-user-info-row{
      display:flex;align-items:center;justify-content:space-between;gap:12px;
      padding:11px 14px;font-size:13.5px
    }
    .admin-user-info-row + .admin-user-info-row{border-top:1px solid var(--border)}
    .admin-user-info-row > span:first-child{color:var(--text-secondary);flex-shrink:0}
    .admin-user-info-val{color:var(--text);font-weight:500;min-width:0;text-align:end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .admin-user-actions{display:flex;gap:10px}
    .admin-user-act{flex:1}
    .admin-user-warn label{display:block;font-size:13px;font-weight:600;color:var(--text-secondary);margin-bottom:6px}
    .admin-user-warn-actions{display:flex;gap:10px;margin-top:12px}
    .admin-user-warn-actions .btn{flex:1}
    @media(min-width:600px){
      .admin-user-sheet{border-radius:var(--radius-lg);margin-bottom:24px}
      .admin-user-handle{display:none}
    }

    /* Player warning modal — always centered (override the sheet's bottom align) */
    #huddle-warn-backdrop{align-items:center}
    .huddle-warn-sheet{
      background:var(--surface-elevated);border:1px solid var(--border);
      border-radius:var(--radius-xl);
      padding:26px 24px calc(22px + env(safe-area-inset-bottom,0px));
      width:calc(100% - 40px);max-width:360px;
      display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;
      box-shadow:var(--shadow-lg)
    }
    .huddle-warn-icon{
      width:52px;height:52px;border-radius:var(--radius-pill);flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      background:var(--danger-soft);color:var(--danger)
    }
    .huddle-warn-icon svg{width:26px;height:26px}
    .huddle-warn-title{font-size:18px;font-weight:800;letter-spacing:-.01em;color:var(--text)}
    .huddle-warn-msg{font-size:14.5px;line-height:1.5;color:var(--text-secondary);overflow-wrap:anywhere;white-space:pre-wrap}
    .huddle-warn-ok{width:100%;margin-top:6px;height:46px}

    /* ===== Admin → Feedback moderation ===== */
    #screen-admin-feedback{--tc:#ec4899}   /* pink tool accent */
    .admin-fb-page{padding-top:8px}
    .admin-fb-toolbar{
      display:flex;align-items:center;gap:10px;
      flex-wrap:wrap;
      margin:4px 0 14px
    }
    .admin-fb-chips{
      display:flex;gap:6px;flex:1;flex-wrap:wrap;min-width:0
    }
    .admin-fb-chip{
      display:inline-flex;align-items:center;gap:6px;
      height:32px;padding:0 12px;
      background:var(--bg-subtle);
      border:1px solid var(--border);
      color:var(--text-secondary);
      border-radius:var(--radius-pill);
      font-size:13px;font-weight:600;
      cursor:pointer;
      transition:background .15s ease,border-color .15s ease,color .15s ease;
      white-space:nowrap
    }
    .admin-fb-chip:hover{background:var(--bg-hover)}
    .admin-fb-chip.active{
      background:color-mix(in srgb,var(--tc) 14%,var(--bg));
      border-color:var(--tc);
      color:color-mix(in srgb,var(--tc) 62%,var(--text))   /* legible on the light tint */
    }
    .admin-fb-chip .count{
      display:inline-flex;align-items:center;justify-content:center;
      min-width:18px;height:18px;padding:0 5px;border-radius:var(--radius-pill);
      background:var(--bg);border:1px solid var(--border);
      color:var(--text-secondary);
      font-size:11px;font-weight:700
    }
    .admin-fb-chip.active .count{
      background:var(--tc);color:#fff;border-color:var(--tc)
    }
    .admin-fb-sort-btn{
      display:inline-flex;align-items:center;gap:6px;
      height:32px;padding:0 12px;
      background:transparent;
      border:1px solid var(--border);
      border-radius:var(--radius-pill);
      color:var(--text);
      font-size:13px;font-weight:500;
      cursor:pointer;
      transition:background .15s ease
    }
    .admin-fb-sort-btn:hover{background:var(--bg-subtle)}

    .admin-fb-row{
      position:relative;
      background:var(--surface);
      border:1px solid var(--border);
      border-radius:16px;
      padding:14px 14px 12px;
      margin-bottom:12px;
      box-shadow:0 3px 12px rgba(0,0,0,.04)
    }
    [data-theme="dark"] .admin-fb-row{box-shadow:none}
    .admin-fb-row.is-done{opacity:.72}
    .admin-fb-row-top{
      display:flex;align-items:center;gap:10px;
      margin-bottom:8px
    }
    .admin-fb-author{
      display:flex;align-items:center;gap:8px;
      min-width:0;flex:1
    }
    .admin-fb-avatar{
      width:32px;height:32px;border-radius:var(--radius-pill);
      flex-shrink:0;overflow:hidden;
      background:var(--tc,var(--text-secondary));
      display:flex;align-items:center;justify-content:center;
      color:#fff;
      font-size:13px;font-weight:800
    }
    .admin-fb-author-name{
      font-size:13.5px;font-weight:600;color:var(--text);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
      min-width:0
    }
    .admin-fb-author-handle{
      font-size:12px;color:var(--text-tertiary);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap
    }
    .admin-fb-row-meta{
      display:flex;align-items:center;gap:6px;flex-shrink:0
    }
    .admin-fb-cat{
      display:inline-flex;align-items:center;gap:4px;
      color:var(--text-tertiary);
      font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase
    }
    /* "Blocked" author chip — danger-tinted, sits in the row's top-right meta. */
    .admin-fb-blocked-chip{
      display:inline-flex;align-items:center;flex-shrink:0;
      height:20px;padding:0 8px;border-radius:var(--radius-pill);
      background:var(--danger-soft);color:var(--danger);
      border:1px solid var(--danger-soft-2);
      font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
      white-space:nowrap
    }
    .admin-fb-cat svg{width:11px;height:11px}
    .admin-fb-text{
      font-size:14px;line-height:1.5;color:var(--text);
      white-space:pre-wrap;word-wrap:break-word;overflow-wrap:anywhere;
      margin-bottom:10px
    }
    .admin-fb-row-footer{
      display:flex;align-items:center;gap:8px
    }
    .admin-fb-footer-left{
      display:flex;align-items:center;gap:6px;flex:1;min-width:0;
      color:var(--text-tertiary);font-size:12px
    }
    .admin-fb-footer-left .dot{
      width:3px;height:3px;border-radius:50%;background:var(--text-tertiary);flex-shrink:0
    }
    /* Heart + vote count in the tool accent. */
    .admin-fb-footer-left > span:first-child{color:var(--tc);font-weight:700}
    .admin-fb-status{
      display:inline-flex;align-items:center;height:20px;padding:0 8px;
      border-radius:var(--radius-pill);
      font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase
    }
    .admin-fb-status-new{background:color-mix(in srgb,var(--tc) 15%,var(--bg));color:color-mix(in srgb,var(--tc) 62%,var(--text))}
    .admin-fb-status-done{
      background:var(--success-soft);
      color:var(--success)
    }
    .admin-fb-overflow{
      width:32px;height:32px;border-radius:var(--radius-pill);
      background:transparent;border:none;cursor:pointer;
      color:var(--text-secondary);
      display:inline-flex;align-items:center;justify-content:center;
      transition:background .15s ease,color .15s ease;
      flex-shrink:0
    }
    .admin-fb-overflow:hover{background:var(--bg-subtle);color:var(--text)}
    .admin-fb-overflow svg{width:18px;height:18px}
    .admin-fb-empty{text-align:center;padding:48px 24px;color:var(--text-secondary)}
    .admin-fb-empty-emoji{font-size:36px;margin-bottom:10px}
    .admin-fb-empty-title{font-size:15px;font-weight:600;color:var(--text);margin-bottom:6px}

    /* ===== Admin → Stats dashboard ===== */
    .admin-stats-page{padding-top:8px}

    /* Period selector — single segmented control controlling every card */
    .admin-stats-period{
      display:flex;gap:6px;
      background:var(--bg-subtle);
      border:1px solid var(--border);
      border-radius:var(--radius-pill);
      padding:4px;
      margin:4px 0 18px;
    }
    .admin-stats-period-btn{
      flex:1;height:32px;padding:0 8px;
      background:transparent;border:none;
      color:var(--text-secondary);
      font-size:13px;font-weight:600;
      border-radius:var(--radius-pill);
      cursor:pointer;
      transition:background .15s ease,color .15s ease;
    }
    .admin-stats-period-btn:hover{color:var(--text)}
    .admin-stats-period-btn.active{
      background:var(--bg);
      color:var(--text);
      box-shadow:var(--shadow-md);
    }

    /* ===== Stats — "Color" dashboard =====================================
       Metric palette scoped to the Stats screen ONLY — the rest of the app
       keeps its mono + orange look. Card tints use color-mix against --bg so
       one hue reads correctly in both light and dark. */
    #screen-admin-stats{--v-indigo:#6366f1;--v-orange:#f97316;--v-emerald:#10b981;--v-pink:#ec4899}

    /* Hero — brand-orange gradient card + repeat-rate gauge */
    .admin-stats-hero{
      border:none;border-radius:var(--radius-xl);
      padding:18px;margin-bottom:12px;color:#fff;
      background:linear-gradient(135deg,#f97316,#ea580c);
      box-shadow:0 10px 26px rgba(249,115,22,.30);
      display:block;overflow:hidden;cursor:pointer;
      transition:transform .15s ease;
    }
    .admin-stats-hero:hover{transform:translateY(-1px)}
    .admin-stats-hero:active{transform:translateY(0)}
    .astat-hero-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
    .astat-hero-eyebrow{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;opacity:.92}
    .astat-hero-pill{
      display:inline-flex;align-items:center;gap:3px;flex-shrink:0;
      background:rgba(255,255,255,.22);color:#fff;
      font-size:11.5px;font-weight:700;padding:4px 10px;border-radius:var(--radius-pill);white-space:nowrap;
    }
    .astat-hero-mid{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:6px}
    .astat-hero-num{font-size:46px;font-weight:800;letter-spacing:-.03em;line-height:1}
    .astat-hero-sub{font-size:12px;opacity:.92;margin-top:3px;line-height:1.35}
    .astat-gauge{flex-shrink:0;line-height:0;text-align:center}
    .astat-gauge-cap{font-size:13px;font-weight:800;letter-spacing:-.01em;margin-top:-2px}

    /* Colored metric cards */
    .admin-stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}
    .astat-card{
      border:none;border-radius:18px;padding:14px;
      display:block;overflow:hidden;cursor:pointer;
      transition:transform .15s ease;
    }
    .astat-card:hover{transform:translateY(-1px)}
    .astat-card:active{transform:translateY(0)}
    .astat-card-ic{width:34px;height:34px;border-radius:11px;display:flex;align-items:center;justify-content:center;margin-bottom:10px;color:#fff}
    .astat-card-ic svg{width:18px;height:18px}
    .astat-card-num{font-size:26px;font-weight:800;letter-spacing:-.02em;line-height:1}
    .astat-card-lbl{font-size:12px;font-weight:600;color:var(--text-secondary);margin-top:2px}
    .astat-card-delta{font-size:11.5px;font-weight:700;margin-top:8px;display:inline-flex;align-items:center;gap:3px}
    .astat-card-delta.admin-stats-delta-down{color:var(--danger)}
    .astat-card-delta.admin-stats-delta-flat{color:var(--text-tertiary)}
    /* per-color tint + accent (number, icon bg, up-delta) */
    .astat-c-indigo{background:color-mix(in srgb,var(--v-indigo) 13%,var(--bg))}
    .astat-c-indigo .astat-card-num,.astat-c-indigo .astat-card-delta.admin-stats-delta-up{color:var(--v-indigo)}
    .astat-c-indigo .astat-card-ic{background:var(--v-indigo)}
    .astat-c-orange{background:color-mix(in srgb,var(--v-orange) 13%,var(--bg))}
    .astat-c-orange .astat-card-num,.astat-c-orange .astat-card-delta.admin-stats-delta-up{color:var(--v-orange)}
    .astat-c-orange .astat-card-ic{background:var(--v-orange)}
    .astat-c-emerald{background:color-mix(in srgb,var(--v-emerald) 13%,var(--bg))}
    .astat-c-emerald .astat-card-num,.astat-c-emerald .astat-card-delta.admin-stats-delta-up{color:var(--v-emerald)}
    .astat-c-emerald .astat-card-ic{background:var(--v-emerald)}
    .astat-c-pink{background:color-mix(in srgb,var(--v-pink) 13%,var(--bg))}
    .astat-c-pink .astat-card-num,.astat-c-pink .astat-card-delta.admin-stats-delta-up{color:var(--v-pink)}
    .astat-c-pink .astat-card-ic{background:var(--v-pink)}

    /* Delta arrows */
    .admin-stats-delta-up::before   { content:'\2191'; font-weight:700 }   /* ↑ */
    .admin-stats-delta-down::before { content:'\2193'; font-weight:700 }   /* ↓ */
    .admin-stats-delta-flat::before { content:'\2192'; font-weight:700 }   /* → */

    /* Bottom card — game-activity bar chart (reuses #admin-stats-breakdown) */
    .admin-stats-breakdown:empty{display:none}
    .admin-stats-breakdown{
      background:var(--surface);border:1px solid var(--border);
      border-radius:18px;padding:16px;margin-bottom:12px;
    }
    .astat-week-h{font-size:13.5px;font-weight:700;margin-bottom:14px;color:var(--text)}
    .astat-bars{display:flex;align-items:flex-end;gap:8px;height:80px}
    .astat-bar{flex:1;height:100%;display:flex;align-items:flex-end}
    .astat-bar-track{width:100%;height:100%;display:flex;align-items:flex-end}
    .astat-bar-fill{width:100%;max-width:22px;margin:0 auto;border-radius:6px 6px 3px 3px;background:var(--v-orange);opacity:.5}
    .astat-bar-fill.is-now{opacity:1}

    /* Footer — refresh timestamp */
    .admin-stats-footer{
      text-align:center;
      font-size:11.5px;color:var(--text-tertiary);
      padding:8px 0;
    }

    /* Loading + error states */
    .admin-stats-loading{
      text-align:center;padding:48px 24px;
      color:var(--text-secondary);font-size:14px;
    }
    .admin-stats-error{
      background:var(--danger-soft);
      border:1px solid var(--danger);
      color:var(--danger);
      padding:14px 16px;border-radius:var(--radius-md);
      margin-bottom:14px;
      font-size:13.5px;
    }

    /* ───────── Stat-card detail sheet (Apple Health-style drill-down) ───────── */
    /* Opens when a card is tapped. Reuses .sheet-backdrop for scroll-lock +
       open/close plumbing. Generous padding throughout — this is the user's
       "focus mode" for a single metric, so it deserves the breathing room. */
    .admin-stats-detail-sheet{
      --mc:var(--accent);                 /* per-metric accent, set on open */
      background:var(--surface-elevated);
      border-radius:18px 18px 0 0;
      padding:10px 22px calc(24px + env(safe-area-inset-bottom));
      width:100%;max-width:480px;
      box-shadow:0 -10px 32px rgba(0,0,0,.10);
      transform:translateY(100%);transition:transform .26s cubic-bezier(.22,.61,.36,1);
    }
    [data-theme="dark"] .admin-stats-detail-sheet{box-shadow:0 -10px 32px rgba(0,0,0,.5)}
    .sheet-backdrop.active .admin-stats-detail-sheet{transform:translateY(0)}
    @media(min-width:600px){
      .admin-stats-detail-sheet{
        border-radius:18px;
        padding:14px 22px 22px;
        margin-bottom:24px;
      }
    }
    /* Drag handle — purely visual affordance signalling dismissibility */
    .admin-stats-detail-handle{
      width:36px;height:4px;border-radius:2px;
      background:var(--border-strong);opacity:.55;
      margin:0 auto 14px;
    }
    @media(min-width:600px){
      .admin-stats-detail-handle{display:none}
    }
    /* Header — label on top, then a big value + delta pill on one row (wraps
       for very long numbers); close button pinned top-right. */
    .admin-stats-detail-head{
      display:flex;align-items:flex-start;justify-content:space-between;
      gap:14px;margin-bottom:14px;
    }
    .admin-stats-detail-head-text{min-width:0;flex:1}
    .admin-stats-detail-close{
      flex-shrink:0;margin-top:-4px;margin-inline-end:-8px;
      color:var(--text-secondary);
    }
    .admin-stats-detail-label{
      font-size:11px;font-weight:700;
      letter-spacing:.08em;text-transform:uppercase;
      color:var(--text-secondary);margin-bottom:8px;
    }
    .admin-stats-detail-headline{
      display:flex;align-items:baseline;flex-wrap:wrap;gap:8px 12px;
    }
    .admin-stats-detail-value{
      font-size:52px;font-weight:800;         /* size stepped down in JS for 1M+ */
      letter-spacing:-.035em;line-height:1;
      color:var(--text);
    }
    /* Delta as a coloured pill — up tints with the metric colour, down uses
       the danger token, flat is neutral. */
    .admin-stats-detail-delta{
      display:inline-flex;align-items:center;gap:5px;
      font-size:13px;font-weight:700;
      padding:5px 11px;border-radius:var(--radius-pill);
      white-space:nowrap;
    }
    .admin-stats-detail-delta.admin-stats-delta-up{
      background:color-mix(in srgb,var(--mc) 14%,var(--bg));color:var(--mc);
    }
    .admin-stats-detail-delta.admin-stats-delta-down{
      background:var(--danger-soft);color:var(--danger);
    }
    .admin-stats-detail-delta.admin-stats-delta-flat{
      background:var(--bg-subtle);color:var(--text-tertiary);
    }

    /* One-line insight callout — bolt icon + bold mood lead + plain sentence,
       tinted with the metric colour. */
    .admin-stats-detail-insight{
      display:flex;gap:10px;align-items:flex-start;
      background:color-mix(in srgb,var(--mc) 13%,var(--bg));
      border-radius:14px;padding:12px 14px;margin:2px 0 6px;
    }
    .admin-stats-detail-insight svg{
      width:20px;height:20px;color:var(--mc);flex-shrink:0;margin-top:1px;
    }
    .admin-stats-detail-insight-tx{
      font-size:13px;line-height:1.45;color:var(--text);
    }
    .admin-stats-detail-insight-tx b{font-weight:700}

    /* Chart container — smooth colored area/line in the metric colour (via
       currentColor). Real-aspect viewBox + default preserveAspectRatio so the
       "now" dot stays round (no preserveAspectRatio:none stretch). */
    .admin-stats-detail-chart{
      position:relative;
      height:150px;
      margin:4px -2px 2px;
      color:var(--mc);
    }
    .admin-stats-detail-chart svg{
      width:100%;height:100%;display:block;overflow:visible;
    }

    /* X-axis labels — 3 reference points, aligned with chart left/mid/right */
    .admin-stats-detail-axis{
      display:flex;justify-content:space-between;
      padding:8px 4px 0;
      font-size:11px;font-weight:600;
      color:var(--text-tertiary);
      letter-spacing:.02em;
    }

    /* Summary row — avg / peak / low, split by thin dividers. Editorial look:
       quiet, subordinate to the number + insight above. */
    .admin-stats-detail-summary{
      display:flex;align-items:center;
      margin-top:16px;
      padding-top:14px;
      border-top:1px solid var(--border);
    }
    .admin-stats-detail-summary-cell{
      flex:1;text-align:center;min-width:0;
    }
    .admin-stats-detail-summary-cell + .admin-stats-detail-summary-cell{
      border-inline-start:1px solid var(--border);
    }
    .admin-stats-detail-summary-label{
      font-size:10.5px;font-weight:700;
      letter-spacing:.08em;text-transform:uppercase;
      color:var(--text-secondary);margin-bottom:5px;
    }
    .admin-stats-detail-summary-value{
      font-size:19px;font-weight:800;
      letter-spacing:-.02em;
      color:var(--text);
    }

    /* Login */
    .login{min-height:100vh;display:flex;flex-direction:column;padding:calc(env(safe-area-inset-top,0px) + 32px) 24px 24px;background:var(--bg);flex:1}
    /* "Warm Hero" login (design A, 2026-07-03): brand-orange hero on top (~47%),
       sign-in sheet below. Hero colors are FIXED brand values in both themes —
       same rationale as the app icon; the sheet + its text follow theme tokens.
       Compound .login.login-hero-page outranks .login's padding via specificity. */
    .login.login-hero-page{padding:0;justify-content:flex-start}
    .login-hero{
      flex:0 0 47%;display:flex;flex-direction:column;align-items:center;justify-content:center;
      gap:14px;text-align:center;
      padding:calc(env(safe-area-inset-top,0px) + 24px) 24px 38px;
      background:linear-gradient(180deg,#f0641c,#e8590c);
    }
    .login-hero-die{width:120px;height:120px;display:block}
    .login-hero-name{font-size:36px;font-weight:800;letter-spacing:-.02em;color:#fff}
    .login-hero-tagline{font-size:16px;color:rgba(255,255,255,.92);margin:0;max-width:300px;line-height:1.4}
    .login-sheet{
      flex:1;display:flex;flex-direction:column;gap:16px;align-items:stretch;
      background:var(--bg);border-radius:28px 28px 0 0;margin-top:-24px;
      padding:36px 24px calc(env(safe-area-inset-bottom,0px) + 32px);
    }
    .login-sheet .btn{width:100%}
    .login-sheet-title{font-size:20px;font-weight:700;text-align:center;color:var(--text)}
    /* Lang pill sitting on the orange hero: translucent white in BOTH themes.
       Compound selector so it outranks the later base .login-lang-btn rule. */
    .login-lang-btn.login-lang-btn--hero{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.35);color:#fff}
    .login-lang-btn.login-lang-btn--hero:hover{background:rgba(255,255,255,.26)}
    .login-fineprint{font-size:12px;color:var(--text-tertiary);text-align:center;margin:4px 0 0;line-height:1.5}
    /* Quiet by design — it must be findable without competing with the one
       thing this screen asks people to do (sign in). */
    .login-privacy-link{display:block;font-size:12px;color:var(--text-tertiary);
      text-align:center;margin:8px 0 0;text-decoration:underline;text-underline-offset:2px}
    .login-brand{display:flex;align-items:center;gap:10px;margin-bottom:48px}
    .login-logo{width:36px;height:36px;border-radius:10px;background:#e8590c;
      display:flex;align-items:center;justify-content:center;font-weight:700}
    /* Inline SVG "Mask" mark inside .login-logo (username-setup screen) — fills are
       hardcoded brand colors (black mask, white eyes on the orange tile) so it matches
       the app icon in BOTH themes; only the tile div is styled here. */
    .login-logo .rl-mark{width:64%;height:64%;display:block}

    /* Floating language picker on login — opens the existing #lang-backdrop sheet. */
    .login-lang-btn{
      position:absolute;
      top:calc(env(safe-area-inset-top, 0px) + 16px);
      inset-inline-end:16px;
      display:inline-flex;align-items:center;gap:6px;
      padding:6px 11px;
      background:var(--bg);
      border:1px solid var(--border-strong);
      border-radius:var(--radius-pill);
      font:inherit;font-size:13px;font-weight:600;color:var(--text-secondary);
      cursor:pointer;
      transition:border-color .15s ease, color .15s ease;
      z-index:5;
    }
    .login-lang-btn:hover{border-color:var(--text);color:var(--text)}
    .login-lang-icon{width:14px;height:14px;flex-shrink:0}
    .login{position:relative}
    .login-brand-name{font-weight:700;font-size:18px;letter-spacing:-.01em}
    .login h1{font-size:28px;font-weight:700;letter-spacing:-.02em;margin:0 0 8px}
    .login-sub{color:var(--text-secondary);margin:0 0 32px}
    .divider{display:flex;align-items:center;gap:12px;color:var(--text-tertiary);font-size:12px;margin:20px 0}
    .divider::before,.divider::after{content:"";flex:1;height:1px;background:var(--border)}
    .login-footer{margin-top:auto;text-align:center;color:var(--text-secondary);font-size:14px;padding-top:24px}
    .login-footer a{font-weight:600;color:var(--text)}

    /* ===== Game lobby — "Three Steps" cards (Big Play style) ===== */
    .mstep{border:1px solid var(--border);border-radius:16px;background:var(--bg);
      padding:13px 14px;display:flex;gap:11px;align-items:flex-start;margin-bottom:10px}
    .mstep-num{width:24px;height:24px;border-radius:50%;background:var(--accent);color:var(--on-accent);
      font-size:12.5px;font-weight:800;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}
    .mstep-body{flex:1;min-width:0}
    .mstep-title{font-size:14.5px;font-weight:700;letter-spacing:-.005em}
    .mstep-opt{font-weight:500;color:var(--text-secondary);font-size:12.5px}
    .mstep-sub{font-size:12px;color:var(--text-secondary);margin-top:1px;line-height:1.4}
    .mstep-title-row{display:flex;align-items:center;justify-content:space-between;gap:8px}
    .mstep-count{color:var(--text-secondary);font-weight:600;font-size:12.5px}
    .mstep-coderow{display:flex;gap:9px;margin-top:10px;align-items:stretch}
    .mstep-codebox{flex:1;min-width:0;border:1.5px dashed var(--border-strong);border-radius:12px;
      padding:9px 8px;font-size:20px;font-weight:800;letter-spacing:.1em;text-align:center;
      font-feature-settings:"tnum";min-height:44px}
    /* Loading skeleton: :empty stops matching the moment the code lands. */
    .mstep-codebox:empty::before{
      content:"———— ————";
      opacity:.22;letter-spacing:.1em;
      animation:room-skeleton-pulse 1.4s ease-in-out infinite;
    }
    @keyframes room-skeleton-pulse{0%,100%{opacity:.18}50%{opacity:.4}}
    @media(prefers-reduced-motion:reduce){
      .mstep-codebox:empty::before{animation:none;opacity:.25}
    }
    .mstep-newcode{width:44px;flex-shrink:0;border:1px solid var(--border);border-radius:12px;
      background:var(--bg-subtle);color:var(--text);cursor:pointer;
      display:flex;align-items:center;justify-content:center;transition:border-color .15s ease}
    .mstep-newcode:hover{border-color:var(--border-strong)}
    .mstep-qrbtn{flex-shrink:0;border:1px solid var(--border);border-radius:12px;
      background:var(--bg-subtle);color:var(--text);cursor:pointer;padding:0 13px;
      display:flex;align-items:center;gap:6px;font:inherit;font-size:13px;font-weight:700;
      transition:border-color .15s ease}
    .mstep-qrbtn:hover{border-color:var(--border-strong)}
    /* Room-QR sheet ("QR on Tap") — big centered QR + the code underneath. */
    .mafia-qr-sheet-body{display:flex;flex-direction:column;align-items:center;padding:4px 0 10px}
    .mafia-qr-sheet .room-qr-wrap{margin:6px auto 0}
    .mafia-qr-sheet .room-qr,
    .mafia-qr-sheet .room-qr-fallback{width:220px;height:220px}
    .mafia-qr-sheet-code{font-size:20px;font-weight:800;letter-spacing:.12em;margin-top:14px;
      font-feature-settings:"tnum"}

    /* ===== Dark-mode "Soft Layers" — LOBBY + its sheets ONLY (Saeed's pick,
       2026-07-06). Light mode untouched; geometry untouched — border widths
       and paddings are identical to the base rules, only colors/surfaces
       change. The idea: cards sit one step LIGHTER than the page (elevation
       instead of outlines), "selected" speaks accent instead of white, and
       helper text steps back a notch. Scoped token overrides do the bulk;
       --bg deliberately NOT overridden (page + sticky gradient stay #0e0e10). */
    [data-theme="dark"] #screen-mafia-lobby,
    [data-theme="dark"] #mafia-qr-backdrop,
    [data-theme="dark"] #mafia-narrator-picker-backdrop,
    [data-theme="dark"] #lobby-invite-backdrop{
      --text:#ececee;--text-secondary:#94949c;--text-tertiary:#6d6d75;
      --border:rgba(255,255,255,.055);--border-strong:rgba(255,255,255,.16);
      --bg-subtle:#1f1f25;--bg-hover:#26262c;
      /* re-anchor inherited text — without this, un-colored elements (step
         titles etc.) inherit body's brighter global --text instead of the
         softened one above */
      color:var(--text);
    }
    [data-theme="dark"] #screen-mafia-lobby .mstep,
    [data-theme="dark"] #screen-mafia-lobby .howto-trigger{background:#17171b}
    [data-theme="dark"] #mafia-qr-backdrop .sheet,
    [data-theme="dark"] #mafia-narrator-picker-backdrop .sheet,
    [data-theme="dark"] #lobby-invite-backdrop .sheet{background:#17171b}
    [data-theme="dark"] #screen-mafia-lobby .mstep-codebox{
      border-style:solid;border-color:rgba(255,255,255,.07);background:#101013;color:#fff}
    [data-theme="dark"] #screen-mafia-lobby .mstep-newcode,
    [data-theme="dark"] #screen-mafia-lobby .mstep-qrbtn{background:#1f1f25}
    [data-theme="dark"] #screen-mafia-lobby .mafia-optional-row{background:#1f1f25}
    [data-theme="dark"] #screen-mafia-lobby .mafia-optional-row[aria-pressed="true"]{
      border-color:var(--accent);background:var(--accent-soft)}
    [data-theme="dark"] #screen-mafia-lobby .mafia-rolemix-pill .count{background:#1f1f25}
    [data-theme="dark"] #screen-mafia-lobby .mafia-prototype-hint{background:transparent;border-color:transparent}
    [data-theme="dark"] #screen-mafia-lobby #mafia-start-btn:disabled,
    [data-theme="dark"] #screen-mafia-lobby #mafia-start-btn[aria-disabled="true"]{
      opacity:1;background:#232329;color:#77777e}
    [data-theme="dark"] #screen-mafia-lobby #mafia-start-btn:disabled:hover,
    [data-theme="dark"] #screen-mafia-lobby #mafia-start-btn[aria-disabled="true"]:hover{background:#232329}

    .players-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}
    /* min-width:0 — grid items refuse to shrink below their content's min-width
       by default, so one long bit of tile text used to blow both 1fr columns out
       past a 375px phone screen (page measured 407-665px wide). This lets the
       2-col tracks stay at their real width; inner text truncates instead. */
    .player-tile{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);min-width:0}
    .player-tile .avatar{width:32px;height:32px;font-size:13px}
    .player-tile-name{font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}
    .player-tile .host-badge{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-secondary)}
    
    .lobby-kick-btn{flex-shrink:0;width:26px;height:26px;border:none;border-radius:50%;background:var(--bg-subtle);color:var(--text-secondary);font-size:18px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;margin-inline-start:6px;transition:background .15s ease,color .15s ease}
    .lobby-kick-btn:hover,.lobby-kick-btn:active{background:#e5484d;color:#fff}
    .lobby-lock-btn{margin-bottom:8px}
    .lobby-lock-btn.is-locked{color:#e5484d;border-color:#e5484d}
    
    .header-leave-btn svg{stroke-width:2.25}
    .header-leave-btn{color:var(--text)}
    .header-leave-btn:hover,.header-leave-btn:active{background:var(--danger-soft);color:var(--danger)}

    .sticky-bottom{
      position:sticky;bottom:0;background:linear-gradient(180deg,rgba(255,255,255,0) 0%,var(--bg) 24px);
      padding:24px 0 calc(env(safe-area-inset-bottom,0px) + 16px);margin-top:auto;
      /* z-index needed because Twemoji emoji inside avatars (.av-symbol) carry z-index:1, and
         their parent .av doesn't create its own stacking context, so those emoji bleed UP
         through the Start game button when the player tiles scroll behind it. Setting z-index
         here (with the existing position:sticky) makes this whole strip a stacking context that
         visually covers anything below z-index 10. */
      z-index:10;
    }

    .lb-rank{width:24px;font-size:14px;font-weight:700;color:var(--text-secondary);text-align:center}
    .lb-row.winner{background:#fff8e6}
    .lb-row.winner .lb-rank{color:#b8860b}
    .lb-name{flex:1;font-weight:600}
    .lb-score{font-weight:700;font-feature-settings:"tnum"}
    

    /* Auth (login screen) status — error / loading / success */
    .login-status{
      font-size:13px;line-height:1.4;min-height:18px;margin:6px 0 12px;
      color:var(--text-secondary);
    }
    .login-status.error{color:var(--danger);font-weight:600}
    .login-status.saving{color:var(--text-secondary);font-style:italic}
    .login-status.ok{color:var(--success);font-weight:600}

    .login-forgot-link{
      font-size:13px;color:var(--text-secondary);cursor:pointer;
      text-decoration:none;
    }
    .login-forgot-link:hover{color:var(--text);text-decoration:underline}

    /* Username status hint below the Edit Profile username input */
    .ep-username-status{
      font-size:12px;line-height:1.4;margin-top:6px;min-height:16px;
      color:var(--text-secondary);
    }
    .ep-username-status.error{color:var(--danger);font-weight:600}
    .ep-username-status.saving{color:var(--text-secondary);font-style:italic}
    .ep-username-status.ok{color:var(--success);font-weight:600}

    /* Join-by-code row (lobby) — alternative to scanning the host's QR */
    /* Code-entry input + Join button — used in the global "Join with code"
       sheet (Games tab) so a player can paste a friend's room code from any
       game without first opening the wrong lobby. */
    .join-code-row{display:flex;gap:8px;align-items:center}
    .join-code-row input{
      flex:1;height:46px;padding:0 14px;
      background:var(--bg);border:1.5px solid var(--border-strong);
      border-radius:var(--radius-md);color:var(--text);font:inherit;
      font-size:17px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
      outline:none;text-align:center;
    }
    .join-code-row input:focus{border-color:var(--text);box-shadow:0 0 0 3px var(--focus-ring)}
    .join-code-row input::placeholder{color:var(--text-tertiary);font-weight:500;letter-spacing:.04em}
    .join-code-row .btn{height:46px;width:auto;padding:0 20px;flex-shrink:0}
    .join-code-status{font-size:13px;text-align:center;margin-top:10px;line-height:1.4;min-height:18px}
    .join-code-status.searching{color:var(--text-secondary)}
    .join-code-status.error{color:var(--danger)}

    /* Choice-first join sheet — "Scan their QR" hero card above an "or type
       the code" divider. The scan card must stay ABOVE the input: the phone
       keyboard (opened only when the user taps the input — no autofocus)
       would hide anything placed below it. */
    .join-scan-card{
      width:100%;display:flex;align-items:center;gap:14px;text-align:start;
      padding:14px;cursor:pointer;font:inherit;
      background:var(--accent-soft);border:1.5px solid var(--accent);
      border-radius:var(--radius-lg);color:var(--text);
      transition:transform .12s ease;
    }
    .join-scan-card:active{transform:scale(.98)}
    .join-scan-icon{
      width:46px;height:46px;border-radius:14px;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      background:var(--accent);color:var(--on-accent);
    }
    .join-scan-icon svg{width:24px;height:24px}
    .join-scan-text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
    .join-scan-title{font-size:16px;font-weight:700;letter-spacing:-.01em}
    .join-scan-sub{font-size:12.5px;color:var(--text-secondary);line-height:1.4}
    .join-scan-chev{width:18px;height:18px;flex-shrink:0;color:var(--accent)}
    /* Shown when the QR library never loaded, so the hero card can't do
       anything. Sits directly UNDER the card (not down by the code input,
       which falls below the fold at 375x760 and under the phone keyboard) —
       the failure has to be visible next to the button that failed. */
    .join-scan-error{
      margin-top:10px;font-size:12.5px;line-height:1.4;
      color:var(--danger);text-align:center;
    }
    .join-or{
      display:flex;align-items:center;gap:10px;margin:16px 0 12px;
      color:var(--text-tertiary);font-size:12px;font-weight:700;
      letter-spacing:.05em;text-transform:uppercase;white-space:nowrap;
    }
    .join-or::before,.join-or::after{content:"";flex:1;height:1px;background:var(--border)}

    /* Secondary swap button used inside the join-code and QR-scan sheets
       ("Scan QR instead" / "Enter code instead"). */
    .join-game-btn{
      display:flex;align-items:center;justify-content:center;gap:8px;height:48px;
      border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);
      color:var(--text);font:inherit;font-size:15px;font-weight:600;cursor:pointer;
      transition:all .15s ease;
    }
    .join-game-btn svg{width:19px;height:19px;flex-shrink:0}
    .join-game-btn:hover{border-color:var(--text)}
    .join-game-btn:active{transform:scale(.98)}

    /* QR scan sheet — live camera preview + scan frame. The <video> fills a
       square viewport so the host's QR is easy to line up. */
    .qr-scan-viewport{
      position:relative;width:100%;max-width:280px;margin:0 auto;aspect-ratio:1/1;
      border-radius:var(--radius-lg);overflow:hidden;background:#000;
    }
    .qr-scan-viewport video{width:100%;height:100%;object-fit:cover;display:block}
    .qr-scan-status{font-size:13px;text-align:center;margin-top:12px;line-height:1.4;min-height:18px;color:var(--text-secondary)}
    .qr-scan-status.searching{color:var(--text-secondary)}
    .qr-scan-status.error{color:var(--danger)}
    /* Floating notice shown at the top of any lobby when openX failed to load
       the cached/URL room code (e.g. host deleted the room or it expired) and
       silently created a fresh one. Fades in, auto-dismisses, click to close. */
    /* Default resting place. When a top banner is visible, huddleSyncToastShift
       (app-09) overrides `top` inline with an absolute px value so the toast is
       never hidden BEHIND the opaque invite/friend banners — it can't be done
       purely in CSS here, because the banner's own height already includes the
       safe-area inset and adding it again would double-count it on notched
       phones. z-index sits above the banners (but below the maintenance
       overlay at 100000) as belt-and-braces for a partial overlap. */
    .lobby-toast{
      position:fixed;top:calc(env(safe-area-inset-top,0px) + 14px);left:50%;transform:translate(-50%,-8px);
      z-index:10000;max-width:calc(100vw - 28px);width:max-content;
      padding:10px 16px;background:var(--surface-elevated);
      border:1px solid var(--border-strong);border-radius:var(--radius-pill);
      color:var(--text);font-size:13px;font-weight:500;line-height:1.35;
      box-shadow:var(--shadow-md);text-align:center;cursor:pointer;
      opacity:0;pointer-events:none;
      transition:opacity .25s ease,transform .25s ease;
    }
    .lobby-toast.active{opacity:1;transform:translate(-50%,0);pointer-events:auto}
    /* Usernames are one unbreakable word (max 20 chars, no spaces) — ellipsize
       instead of spilling out of the seat box. */
    /* Empty seat = invite tile. Dashed border + plus icon makes it read as
       "tap to fill" instead of a regular player slot. */

    
    .mafia-narrator-card{
      display:flex;align-items:center;gap:12px;padding:14px;margin:0 0 14px;
      background:var(--bg);border:1.5px solid var(--border-strong);
      border-radius:var(--radius-md);cursor:pointer;font:inherit;color:inherit;
      text-align:start;transition:all .15s ease;width:100%;
    }
    .mafia-narrator-card:hover:not(:disabled){border-color:var(--text);transform:translateY(-1px)}
    .mafia-narrator-card:disabled{opacity:.75;cursor:default}
    .mafia-narrator-card.claimed{border-color:var(--text);background:var(--bg-subtle)}
    .mafia-narrator-card.claimed-by-me{border-color:var(--success);background:var(--success-soft)}
    /* "needs-attention" pulse — fires when the lobby has enough players
       (5+) but the host hasn't picked a narrator yet. Without this, the
       narrator card sits silently at the top of the lobby while the user
       scrolls down to a Start button that won't work; the pulse pulls
       the eye back to the missing step. Stops the moment narrator is set. */
    @keyframes mafiaNarratorPulse {
      0%, 100% { box-shadow: 0 0 0 0 rgba(193, 53, 21, 0); border-color: var(--border-strong); }
      50%      { box-shadow: 0 0 0 6px rgba(193, 53, 21, 0.18); border-color: var(--danger); }
    }
    .mafia-narrator-card.needs-attention{
      animation: mafiaNarratorPulse 1.8s ease-in-out infinite;
    }
    .mafia-narrator-card.needs-attention .mafia-narrator-title{ color: var(--danger); }
    @media (prefers-reduced-motion: reduce) {
      .mafia-narrator-card.needs-attention{ animation: none; border-color: var(--danger); }
    }
    .mafia-narrator-icon{
      width:44px;height:44px;border-radius:50%;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;font-size:22px;
      background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%);color:#fff;
    }
    [data-theme="dark"] .mafia-narrator-icon{background:linear-gradient(135deg,#1e293b 0%,#334155 100%)}
    .mafia-narrator-content{flex:1;min-width:0}
    .mafia-narrator-title{font-weight:700;color:var(--text);font-size:15px;line-height:1.25;letter-spacing:-.01em}
    .mafia-narrator-sub{font-size:12px;color:var(--text-secondary);margin-top:3px;line-height:1.4}
    .mafia-narrator-status{font-size:10px;color:var(--text-secondary);font-weight:700;letter-spacing:.05em;text-transform:uppercase;margin-top:6px}
    .mafia-narrator-card.claimed-by-me .mafia-narrator-status{color:var(--success)}

    
    /* Seats — round avatar chips (Big Play look), wrapping rows inside the
       step-2 card. The renderer's markup is unchanged (button.mafia-seat >
       .av + .mafia-seat-info); only the presentation is restacked here. */
    .mafia-seats{display:flex;flex-wrap:wrap;gap:12px 2px;margin:12px 0 0}
    .mafia-seat{
      width:60px;display:flex;flex-direction:column;align-items:center;gap:5px;
      background:none;border:0;padding:0;font:inherit;color:var(--text);
      cursor:default;text-align:center;min-width:0;
    }
    .mafia-seat:disabled{opacity:1;cursor:default}
    .mafia-seat .av{box-shadow:0 0 0 1px var(--border)}
    .mafia-seat.claimed-by-me .av{box-shadow:0 0 0 2px var(--accent)}
    .mafia-seat.is-narrator .av{box-shadow:0 0 0 2px var(--text)}
    .mafia-seat-info{min-width:0;max-width:60px}
    .mafia-seat-name{font-weight:600;color:var(--text-secondary);font-size:10.5px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .mafia-seat.claimed-by-me .mafia-seat-name{color:var(--text);font-weight:700}
    .mafia-seat-status{font-size:8.5px;color:var(--text-tertiary);font-weight:700;letter-spacing:.05em;text-transform:uppercase;margin-top:1px}
    .mafia-seat.claimed-by-me .mafia-seat-status{color:var(--accent)}
    .mafia-seat.is-narrator .mafia-seat-status{color:var(--text)}

    .mafia-seat.mafia-seat-invite{cursor:pointer}
    .mafia-seat-invite-icon{
      width:40px;height:40px;border-radius:50%;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      border:1.5px dashed var(--border-strong);background:transparent;color:var(--text-tertiary);
      font-size:18px;font-weight:600;line-height:1;
      transition:border-color .15s ease,color .15s ease;
    }
    .mafia-seat.mafia-seat-invite:hover .mafia-seat-invite-icon{border-color:var(--accent);color:var(--accent)}
    .mafia-seat-invite .mafia-seat-name{color:var(--text-tertiary);font-weight:500}
    .mafia-seat.mafia-seat-invite:hover .mafia-seat-name{color:var(--text-secondary)}

    /* Hint lives inside .sticky-bottom now, right above the Start button. */
    .mafia-seats-hint{
      text-align:center;font-size:12px;color:var(--text-secondary);
      margin:0 0 8px;line-height:1.45;font-style:italic;min-height:17px;
    }

    /* Role-mix preview — read-only block inside the step-3 card showing what
       roles will be dealt given the current player count. Updates live. */
    .mafia-rolemix-card{margin:10px 0 0}
    .mafia-rolemix-title{
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-secondary);margin-bottom:8px;
    }
    .mafia-rolemix-row{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center;justify-content:flex-start}
    .mafia-rolemix-pill{
      display:inline-flex;align-items:center;gap:6px;
      font-size:13px;font-weight:600;color:var(--text);
    }
    .mafia-rolemix-pill .count{
      display:inline-flex;align-items:center;justify-content:center;
      min-width:20px;height:20px;padding:0 6px;border-radius:10px;
      background:var(--bg);border:1px solid var(--border-strong);
      font-size:12px;font-weight:700;
    }
    .mafia-rolemix-empty{
      font-size:13px;color:var(--text-tertiary);font-style:italic;
    }

    /* ===== Mafia optional-roles card =====================================
       Host-only card below the role-mix preview. Two tappable rows (Child
       and Mafia Leader) — toggle on/off, state persisted to localStorage.
       PURE UI for now — toggles do NOT affect role assignment. Selected
       state = derived white border via var(--text) + faint inner tint (no
       green fill, follows the established selected-state pattern). */
    .mafia-optional-card{margin:6px 0 0}
    .mafia-optional-sub{
      font-size:12px;color:var(--text-tertiary);margin-bottom:10px;line-height:1.4;
    }
    .mafia-optional-rows{display:flex;flex-direction:column;gap:8px}
    .mafia-optional-row{
      display:flex;align-items:center;gap:12px;
      padding:10px 12px;background:var(--bg);
      border:1.5px solid var(--border);border-radius:12px;
      font-family:inherit;text-align:start;cursor:pointer;width:100%;
      transition:border-color .12s ease, background-color .12s ease;
    }
    .mafia-optional-row:hover{border-color:var(--border-strong)}
    /* Selected = accent border + soft tint (matches the app-wide selected state;
       replaces the old white-outline pattern). Border width is constant (1.5px)
       in both states, so toggling never shifts the row's geometry. */
    /* Read-only twist row (guest view): shows on/off state, not tappable. */
    .mafia-optional-row.ro{cursor:default}
    .mafia-optional-row[aria-pressed="true"]{
      border-color:var(--accent);
      background:var(--accent-soft);
    }
    .mafia-optional-row-emoji{
      font-size:21px;line-height:1;flex-shrink:0;width:28px;text-align:center;
    }
    .mafia-optional-row-text{flex:1;min-width:0;display:flex;flex-direction:column}
    .mafia-optional-row-name{
      display:block;font-size:14px;font-weight:700;color:var(--text);letter-spacing:-.005em;
    }
    .mafia-optional-row-tag{
      display:block;font-size:11.5px;color:var(--text-secondary);margin-top:1px;line-height:1.3;
    }
    /* iOS-style toggle switch: grey track → accent when on, knob slides right. */
    .mafia-optional-switch{
      position:relative;width:40px;height:23px;border-radius:999px;flex-shrink:0;
      background:var(--border-strong);transition:background-color .15s ease;
    }
    .mafia-optional-switch::after{
      content:"";position:absolute;top:2.5px;inset-inline-start:2.5px;width:18px;height:18px;border-radius:50%;
      background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.28);transition:transform .15s ease;
    }
    .mafia-optional-row[aria-pressed="true"] .mafia-optional-switch{background:var(--accent)}
    .mafia-optional-row[aria-pressed="true"] .mafia-optional-switch::after{transform:translateX(17px)}
    [dir="rtl"] .mafia-optional-row[aria-pressed="true"] .mafia-optional-switch::after{transform:translateX(-17px)}

    /* ===== Role editor (host-only, 2026-07-08) ===========================
       Counter rows (Mafia/Doctor/Detective) + Villager auto row + Leader/Child
       twists + balance bar + Recommended pill + gentle hints. Reuses the
       .mafia-optional-row-* emoji/text styles above; twists reuse the toggle. */
    .mafia-role-list{display:flex;flex-direction:column;gap:8px;margin-top:6px}
    .mafia-role-row{
      display:flex;align-items:center;gap:12px;padding:9px 11px;background:var(--bg);
      border:1.5px solid var(--border);border-radius:12px;
    }
    [data-theme="dark"] #screen-mafia-lobby .mafia-role-row{background:#1f1f25}
    /* Stepper */
    .mafia-step{display:inline-flex;align-items:center;gap:2px;border:1.5px solid var(--border-strong);
      border-radius:999px;padding:2px;background:var(--bg);flex-shrink:0}
    [data-theme="dark"] #screen-mafia-lobby .mafia-step{background:#141418}
    .mafia-step-btn{width:30px;height:30px;border-radius:50%;border:0;background:transparent;color:var(--text);
      font-size:19px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;
      line-height:1;font-family:inherit;padding:0}
    .mafia-step-btn:hover:not(:disabled){background:var(--bg-hover)}
    .mafia-step-btn:disabled{color:var(--text-tertiary);cursor:default}
    .mafia-step-num{min-width:24px;text-align:center;font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}
    /* Villager auto pill */
    .mafia-auto-pill{display:inline-flex;align-items:center;gap:5px;flex-shrink:0;padding:5px 12px;border-radius:999px;
      background:var(--bg-subtle);border:1px solid var(--border);font-size:12.5px;font-weight:700;color:var(--text-secondary)}
    .mafia-auto-pill b{font-size:15px;color:var(--text);font-variant-numeric:tabular-nums}
    /* Balance summary */
    .mafia-balance{margin:12px 0 2px}
    .mafia-balance-row{display:flex;align-items:center;justify-content:space-between;font-size:13px;font-weight:700}
    .mafia-balance-maf{color:var(--danger)}
    .mafia-balance-town{color:var(--success)}
    .mafia-balance-bar{height:9px;border-radius:999px;overflow:hidden;display:flex;background:var(--bg-subtle);
      margin-top:8px;border:1px solid var(--border)}
    .mafia-balance-bar .maf{background:var(--danger);transition:width .18s ease}
    .mafia-balance-bar .town{background:var(--success);transition:width .18s ease}
    /* Recommended pill (top-right, above the balance bar) */
    .mafia-rec-row{display:flex;justify-content:flex-end;margin-top:2px}
    .mafia-rec-pill{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 14px;border-radius:999px;
      border:1px solid var(--border-strong);background:var(--bg);color:var(--text);font-size:12.5px;font-weight:700;
      cursor:pointer;font-family:inherit}
    .mafia-rec-pill:hover{background:var(--bg-subtle);border-color:var(--text)}
    /* Twists divider */
    .mafia-twists-divider{display:flex;align-items:center;gap:10px;margin:16px 2px 10px;
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary)}
    .mafia-twists-divider::before,.mafia-twists-divider::after{content:"";flex:1;height:1px;background:var(--border)}
    /* Hints */
    .mafia-hints{display:flex;flex-direction:column;gap:7px;margin-top:12px}
    .mafia-hint{display:flex;gap:9px;align-items:flex-start;font-size:12.5px;line-height:1.4;
      padding:9px 11px;border-radius:11px;border:1px solid}
    .mafia-hint-i{flex-shrink:0;font-size:14px;line-height:1.3}
    .mafia-hint.warn{background:var(--danger-soft);border-color:transparent;color:var(--danger)}
    .mafia-hint.info{background:var(--bg-subtle);border-color:var(--border);color:var(--text-secondary)}

    /* ===== Meter-led header (2026-07-09 "Meter" redesign) ================
       Host-only framed Mafia-vs-Town meter that LEADS step 3 (sits above the
       video strip). Compact by design — 18px numbers frame the steppers, they
       do not become a dashboard. Recommended (↺) lives in its top-right. The
       "TWISTS" heading is now a light label (.mafia-twlabel) instead of the
       old full-width divider. */
    .mafia-meter-card{margin:14px 0 0}
    .mafia-meter{border:1px solid var(--border);border-radius:14px;padding:11px 13px 12px;background:var(--bg-subtle)}
    .mafia-meter-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
    .mafia-meter-cap{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary)}
    /* "VS face-off" balance (Saeed's pick 2026-07-25) — Mafia vs Town as two
       coloured cards, then a plain-words verdict. Same for host and guest.
       Matches the existing win-screen team cards (.mafia-cards-win-team--*). */
    .mafia-vs{display:flex;align-items:stretch;gap:0}
    .mafia-vs-side{flex:1;min-width:0;border-radius:13px;padding:12px 8px;text-align:center;
      border:1.5px solid;display:flex;flex-direction:column;align-items:center;gap:2px}
    .mafia-vs-side.maf{background:var(--danger-soft);border-color:var(--danger)}
    .mafia-vs-side.town{background:var(--success-soft);border-color:var(--success)}
    .mafia-vs-em{font-size:19px;line-height:1}
    .mafia-vs-num{font-size:28px;font-weight:800;line-height:1.05;letter-spacing:-.02em;
      font-variant-numeric:tabular-nums;margin-top:3px}
    .mafia-vs-side.maf .mafia-vs-num,.mafia-vs-side.maf .mafia-vs-lbl{color:var(--danger)}
    .mafia-vs-side.town .mafia-vs-num,.mafia-vs-side.town .mafia-vs-lbl{color:var(--success)}
    .mafia-vs-lbl{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;
      max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .mafia-vs-mid{width:34px;flex-shrink:0;display:flex;align-items:center;justify-content:center}
    .mafia-vs-mid span{width:30px;height:30px;border-radius:50%;background:var(--bg);
      border:1.5px solid var(--border-strong);display:flex;align-items:center;justify-content:center;
      font-size:10.5px;font-weight:800;color:var(--text-secondary)}
    .mafia-vs-verdictrow{display:flex;justify-content:center;margin-top:11px}
    .mafia-verdict{display:inline-flex;align-items:center;gap:5px;border-radius:var(--radius-pill);
      padding:5px 11px;font-size:11.5px;font-weight:800}
    .mafia-verdict.ok{background:var(--success-soft);color:var(--success)}
    .mafia-verdict.warn{background:var(--danger-soft);color:var(--danger)}
    .mafia-verdict.soft{background:var(--accent-soft);color:var(--accent)}
    .mafia-vs-note{font-size:11.5px;line-height:1.45;color:var(--text-secondary);margin-top:9px;text-align:center}
    .mafia-vs-note b{color:var(--text);font-weight:800}
    .mafia-twlabel{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary);margin:8px 2px 0}
    [data-theme="dark"] #screen-mafia-lobby .mafia-meter{background:#24242b}
    [data-theme="dark"] #screen-mafia-lobby .mafia-vs-mid span{background:#141418}

    /* ============================================================
       Mafia lobby — "The Table" redesign (2026-07-11). Reuses the
       existing render logic / IDs; only presentation changes.
       ============================================================ */
    /* How-to as a header button (more visible than the old link/card) */
    .mafia-howto-btn{display:inline-flex;align-items:center;gap:5px;height:34px;padding:0 12px;
      border:1px solid var(--accent);border-radius:var(--radius-pill);background:var(--bg);
      color:var(--accent);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;white-space:nowrap;
      transition:border-color .15s ease,background-color .15s ease}
    .mafia-howto-btn:hover{background:var(--accent-soft);border-color:var(--accent-hover)}
    .mafia-howto-btn svg{width:14px;height:14px;flex-shrink:0}
    .mafia-howto-btn[hidden]{display:none}
    .mafia-howto-btn.pulse{border-color:var(--accent);color:var(--accent)}

    /* Invite code hero (+ compact variant once enough players joined) */
    .mafia-code-hero{border:1px solid var(--border);background:var(--accent-soft);border-radius:18px;
      padding:15px 16px 14px;display:flex;flex-direction:column}
    .mafia-code-hero .ceyebrow{font-size:11px;font-weight:700;color:var(--accent);letter-spacing:.02em}
    .mafia-code-hero-row{display:flex;align-items:center;gap:10px;margin-top:7px}
    .mafia-code-hero .ccode{flex:1;min-width:0;font-size:26px;font-weight:800;letter-spacing:.05em;color:var(--text);
      font-feature-settings:"tnum";white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .mafia-code-hero .ccap{font-size:11.5px;color:var(--text-secondary);margin-top:8px}
    .mafia-hero-btn{width:42px;height:42px;flex-shrink:0;border:1px solid var(--border-strong);background:var(--bg);
      border-radius:12px;display:flex;align-items:center;justify-content:center;color:var(--text);cursor:pointer;
      transition:border-color .15s ease}
    .mafia-hero-btn:hover{border-color:var(--text)}
    .mafia-hero-btn svg{width:18px;height:18px}
    .mafia-code-hero.compact{padding:8px;padding-inline-start:14px}
    .mafia-code-hero.compact .ceyebrow,.mafia-code-hero.compact .ccap{display:none}
    .mafia-code-hero.compact .mafia-code-hero-row{margin-top:0}
    .mafia-code-hero.compact .ccode{font-size:16px}
    .mafia-code-hero.compact .mafia-hero-btn{width:34px;height:34px;border-radius:9px}
    .mafia-code-hero.compact .mafia-hero-btn svg{width:15px;height:15px}
    /* Prominent Share action inside the code hero (C-combined). Bold accent fill —
       the one clear "get friends in" tap; refresh + QR stay as quiet icons above. */
    .mafia-share-btn{margin-top:12px;width:100%;height:46px;border:0;border-radius:13px;
      background:var(--accent);color:var(--on-accent);font:inherit;font-size:15px;font-weight:800;
      display:flex;align-items:center;justify-content:center;gap:8px;cursor:pointer;transition:background-color .15s ease}
    .mafia-share-btn:hover{background:var(--accent-hover)}
    .mafia-share-btn svg{width:18px;height:18px}

    /* "Join another room" — quiet escape below the share card, shown only when
       the host is alone (toggled in mafiaRenderLobby). Orange label so it reads
       as a real action; stays secondary to Start game (no solid fill). */
    .mafia-join-another{margin-top:11px;width:100%;display:flex;align-items:center;justify-content:center;
      gap:7px;border:1px solid var(--border-strong);border-radius:13px;background:var(--bg);
      padding:12px;font:inherit;font-size:13px;font-weight:800;color:var(--accent);cursor:pointer;
      transition:border-color .15s ease}
    .mafia-join-another:hover{border-color:var(--accent)}
    .mafia-join-another svg{width:15px;height:15px}
    .mafia-join-another[hidden]{display:none}

    /* The Table (player tiles) — C-combined "game board": tiles sit on a soft,
       faintly green-tinted rounded panel so it reads as a real table, not a form. */
    .mafia-table{margin-top:16px;border:1px solid var(--border);border-radius:22px;padding:18px 16px 20px;
      background:radial-gradient(circle at 50% 34%, rgba(80,190,110,.10), transparent 70%), var(--bg-subtle)}
    .mafia-table-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}
    .mafia-table-title{font-size:15px;font-weight:800}
    .mafia-table-title .cnt{color:var(--text-secondary);font-weight:600;font-size:13px;margin-inline-start:4px}
    /* Leave — a clean text link, not a boxed button */
    .mafia-leave{border:0;background:none;padding:0;margin:0;font:inherit;font-size:13px;font-weight:600;color:var(--danger);cursor:pointer;line-height:1}
    .mafia-leave:hover{opacity:.7}
    .mafia-leave[hidden]{display:none}
    /* Guest variant: the host's Leave is a small link in the "Your table" header
       row, but the guest's sits alone under the waiting bar — give it room to be
       tapped without looking like a primary action. */
    .mafia-leave--guest{display:block;width:100%;padding:12px 0 2px;text-align:center;font-size:14px}
    .mafia-table-grid{display:flex;flex-wrap:wrap;gap:16px 14px;justify-content:center}
    .mafia-tile{display:flex;flex-direction:column;align-items:center;gap:6px;width:70px;background:none;border:0;padding:0;cursor:default}
    .mafia-tile .av{border-radius:20px !important;box-shadow:0 0 0 1px var(--border)}
    .mafia-tile.me .av{box-shadow:0 0 0 2px var(--accent)}
    .mafia-tile.is-narrator .av{box-shadow:0 0 0 2px var(--text)}
    .mafia-tile-name{font-size:11px;font-weight:700;color:var(--text);max-width:70px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .mafia-tile.me .mafia-tile-name{color:var(--accent)}
    .mafia-tile-invite{cursor:pointer}
    .mafia-tile-invite .plus{width:62px;height:62px;border-radius:20px;border:2px dashed var(--accent);color:var(--accent);
      display:flex;align-items:center;justify-content:center;font-size:30px;background:transparent}
    .mafia-tile-invite .mafia-tile-name{color:var(--accent)}
    @keyframes mafia-tile-pop{0%{transform:scale(.5);opacity:0}70%{transform:scale(1.08)}100%{transform:scale(1);opacity:1}}
    .mafia-tile .av.pop{animation:mafia-tile-pop .32s cubic-bezier(.34,1.56,.64,1)}
    /* A tile "pops" the first time that player appears (set in mafiaRenderSeats). */
    .mafia-tile.just-joined .av{animation:mafia-tile-pop .34s cubic-bezier(.34,1.56,.64,1)}
    /* Faint "empty chairs" shown while the table is nearly empty — welcoming, not
       broken. Same footprint as a real tile so the row stays aligned. */
    .mafia-tile-empty{opacity:.55}
    .mafia-tile-empty .chair{width:62px;height:62px;border-radius:20px;border:2px dashed var(--border-strong);background:transparent}

    /* Roles TILE chip (icon pills) — host clickable, guest read-only (.ro).
       24px top = the app's standard section-break gap (matches .section-title),
       giving a deliberate separation from "Your table" above. */
    .mafia-roles-chip{margin-top:24px}
    .rchip{display:flex;align-items:center;gap:13px;border:1px solid var(--border);border-radius:16px;
      background:var(--bg);padding:15px;width:100%;text-align:start;cursor:pointer;transition:border-color .12s ease;font:inherit;color:var(--text)}
    .rchip.ro{cursor:default}
    .rchip:not(.ro):hover{border-color:var(--accent)}
    .rchip-ic{width:48px;height:48px;border-radius:14px;background:var(--accent-soft);display:flex;align-items:center;justify-content:center;font-size:24px;flex-shrink:0}
    .rchip-body{flex:1;min-width:0}
    .rchip-t{font-size:14.5px;font-weight:800;display:flex;align-items:center;gap:9px}
    .rchip-rec{font-size:11px;font-weight:800;color:var(--success)}
    .rchip-pills{display:flex;flex-wrap:wrap;gap:9px;margin-top:11px}
    .rpill{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:800;color:var(--text);
      background:var(--bg-subtle);border:1px solid var(--border);border-radius:var(--radius-pill);padding:5px 11px}
    .rpill .em{font-size:14px}
    .rpill.tw{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
    .rchip-meter{height:8px;border-radius:var(--radius-pill);overflow:hidden;display:flex;background:var(--bg-subtle);border:1px solid var(--border);margin-top:13px}
    .rchip-meter .maf{background:var(--danger)}
    .rchip-meter .town{background:var(--success)}
    .rchip-chev{color:var(--text-tertiary);flex-shrink:0;align-self:center}
    .rchip-chev svg{width:20px;height:20px}
    /* Calm roles line (C-combined): title + one-line note, "Change" on the right. */
    .rchip.calm{align-items:center}
    .rchip-sub{display:block;font-size:12px;color:var(--text-secondary);margin-top:3px}
    .rchip-change{flex-shrink:0;align-self:center;font-size:13px;font-weight:800;color:var(--accent)}
    /* One-line narrator explainer under the roles line. */
    .mafia-narr-note{margin-top:16px;font-size:12px;line-height:1.55;color:var(--text-secondary);text-align:center;padding:0 6px}
    [data-theme="dark"] #screen-mafia-lobby .rchip,
    [data-theme="dark"] #screen-mafia-lobby .mafia-code-hero .mafia-hero-btn,
    [data-theme="dark"] #screen-mafia-lobby .mafia-join-another,
    [data-theme="dark"] #screen-mafia-lobby .mafia-howto-btn{background:#1f1f25}
    [data-theme="dark"] #screen-mafia-lobby .rpill{background:#1f1f25}
    [data-theme="dark"] .mafia-howto-btn{background:#17171b}

    /* Roles centered popup */
    #mafia-roles-backdrop{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.45);
      opacity:0;pointer-events:none;transition:opacity .2s ease;display:flex;align-items:center;justify-content:center;padding:16px}
    #mafia-roles-backdrop.active{opacity:1;pointer-events:auto}
    .mafia-roles-dialog{width:100%;max-width:440px;max-height:86vh;overflow-y:auto;background:var(--bg);
      border-radius:20px;padding:20px 16px 16px;position:relative;transform:scale(.95);transition:transform .2s cubic-bezier(.3,.9,.4,1);
      box-shadow:0 22px 60px rgba(0,0,0,.4)}
    #mafia-roles-backdrop.active .mafia-roles-dialog{transform:scale(1)}
    .mafia-roles-dialog-x{position:absolute;top:11px;inset-inline-end:11px;width:34px;height:34px;border-radius:50%;border:0;
      background:var(--bg-subtle);color:var(--text);display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:2}
    .mafia-roles-dialog-x svg{width:16px;height:16px}
    .mafia-roles-dialog-title{font-size:18px;font-weight:800;margin-bottom:3px}
    .mafia-roles-dialog-sub{font-size:12.5px;color:var(--text-secondary);margin-bottom:6px}

    /* Guest hero */
    .mafia-guest-invite{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:46px;
      border:1.5px dashed var(--accent);border-radius:14px;background:var(--accent-soft);color:var(--accent);
      font:inherit;font-size:14px;font-weight:800;cursor:pointer;margin-bottom:14px;transition:border-color .15s ease}
    .mafia-guest-invite:hover{border-color:var(--accent-hover)}
    .mafia-guest-invite svg{width:18px;height:18px}
    .mafia-guest-invite[hidden]{display:none}
    .mafia-guest-hero{border:1px solid var(--border);border-radius:20px;background:var(--bg);padding:24px 16px 18px;text-align:center}
    .mafia-guest-avwrap{position:relative;display:inline-block;margin-bottom:12px}
    .mafia-guest-avwrap .av{border-radius:20px !important}
    .mafia-guest-badge{position:absolute;inset-inline-end:-3px;bottom:-3px;width:24px;height:24px;border-radius:50%;background:var(--success);color:#fff;
      display:flex;align-items:center;justify-content:center;border:2.5px solid var(--bg)}
    .mafia-guest-badge svg{width:13px;height:13px}
    .mafia-guest-hero h3{font-size:21px;font-weight:800;margin:0 0 3px}
    .mafia-guest-hero .gname{font-size:13.5px;color:var(--text-secondary)}
    .mafia-guest-div{height:1px;background:var(--border);margin:16px 0 14px}
    .mafia-guest-waitrow{font-size:12.5px;font-weight:700;color:var(--text-secondary);display:inline-flex;gap:7px;align-items:center;margin-bottom:13px}
    .mafia-guest-roster{display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
    .mafia-guest-roster .av{border-radius:50% !important}
    .mafia-glabel{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary);margin:22px 2px 9px}
    .mafia-glabel:first-child{margin-top:6px}

    /* narrator warm line + guest waiting bar */
    .mafia-narr-line{margin-top:16px;font-size:12px;line-height:1.55;color:var(--text-secondary);text-align:center;padding:0 6px}
    .mafia-narr-line b{color:var(--text);font-weight:700}
    .mafia-waitline{width:100%;height:54px;border-radius:16px;display:flex;align-items:center;justify-content:center;gap:8px;
      font-size:14.5px;font-weight:600;color:var(--text-secondary);background:var(--bg-subtle);border:1px solid var(--border)}
    .mafia-livedot{width:7px;height:7px;border-radius:50%;background:var(--success);display:inline-block;animation:mafia-live 1.4s ease-in-out infinite}
    @keyframes mafia-live{0%,100%{opacity:.35;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}

    /* ===== Mafia Cards — placeholder (Phase 1) =========================
       Stub screen reached by tapping the new "Mafia Cards" tile on the
       Games screen. Phase 2+ will replace this with the real lobby. */
    #screen-mafia-cards-game > main{
      padding:24px 20px 28px;
    }

    /* ===== Mafia Cards — narrator dashboard (Phase 4) ===================
       Replaces the Phase 2 placeholder. Single screen the narrator uses
       for the whole game: phase pill (Night/Day toggle), cheat sheet of
       all players + their roles (narrator-only secret), tap-to-toggle
       dead, and an End game button. Dashboard state is LOCAL — no SQL
       writes — because the narrator is the source of truth at the table.
       Other phones don't need to know who's dead; their card just stays
       face-down. */
    .mafia-cards-narrator{
      display:flex;flex-direction:column;gap:14px;padding-top:4px;min-height:100%;
    }
    #mafia-cards-live{display:flex;flex-direction:column;gap:14px}

    /* Top toolbar — three equal buttons: Who's who · Rules · Script. The
       whole screen below is the teleprompter; these are the reference taps. */
    .mafia-narr-toolbar{display:flex;gap:6px}
    /* In-game room-code chip (narrator + player role screens) — quiet, tappable;
       opens the QR share sheet so a dropped player can rejoin with their role. */
    .mafia-ingame-code{
      display:flex;align-items:center;gap:9px;width:100%;
      margin:12px 0 0;padding:9px 12px;
      background:var(--bg-subtle);border:1px solid var(--border);border-radius:12px;
      color:var(--text-secondary);cursor:pointer;-webkit-tap-highlight-color:transparent;
    }
    .mafia-ingame-code:active{background:var(--bg-hover)}
    .mafia-ingame-code--role{margin-top:16px}
    .mafia-ingame-code-key{width:16px;height:16px;flex:0 0 auto;opacity:.65}
    .mafia-ingame-code-label{text-transform:uppercase;letter-spacing:.05em;font-size:11px;font-weight:600}
    .mafia-ingame-code-val{
      flex:1 1 auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
      font-size:15px;font-weight:700;letter-spacing:.06em;color:var(--text);
    }
    .mafia-ingame-code-qr{width:18px;height:18px;flex:0 0 auto;opacity:.65}
    .mafia-narr-tool{
      flex:1;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
      padding:9px 4px;border-radius:var(--radius-md);
      background:var(--bg-subtle);border:1px solid var(--border);
      font-size:11.5px;font-weight:700;color:var(--text);
      cursor:pointer;font-family:inherit;transition:background-color .12s ease,transform .06s ease;
    }
    .mafia-narr-tool:hover{background:var(--bg-hover)}
    .mafia-narr-tool:active{transform:scale(.98)}
    .mafia-narr-tool svg{width:16px;height:16px;flex-shrink:0}
    .mafia-narr-tool span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    /* All four tools share one look (icon over label) so the 4th (room code)
       fits cleanly beside the others at 375px. */
    /* Leave-confirm sheet — the mid-game exit door asks: keep your seat or quit. */
    .mafia-leave-sub{font-size:14px;color:var(--text-secondary);margin:-2px 0 16px;line-height:1.45}
    .mafia-leave-options{display:flex;flex-direction:column;gap:10px}
    .mafia-leave-opt{
      display:flex;align-items:center;gap:14px;width:100%;text-align:start;
      padding:14px 16px;border-radius:var(--radius-md);
      background:var(--bg-subtle);border:1.5px solid var(--border);
      cursor:pointer;font:inherit;
      transition:background-color .12s ease,border-color .12s ease,transform .06s ease;
    }
    .mafia-leave-opt:hover{background:var(--bg-hover)}
    .mafia-leave-opt:active{transform:scale(.99)}
    .mafia-leave-opt--danger{border-color:var(--danger)}
    .mafia-leave-opt-icon{font-size:26px;line-height:1;flex:0 0 auto}
    .mafia-leave-opt-text{display:flex;flex-direction:column;gap:3px;min-width:0}
    .mafia-leave-opt-title{font-size:16px;font-weight:700;color:var(--text)}
    .mafia-leave-opt--danger .mafia-leave-opt-title{color:var(--danger)}
    .mafia-leave-opt-desc{font-size:13px;color:var(--text-secondary);line-height:1.4}
    .mafia-leave-cancel{
      display:block;width:100%;margin-top:14px;padding:13px;
      background:transparent;border:none;border-radius:var(--radius-pill);
      color:var(--text-secondary);font:inherit;font-size:15px;font-weight:700;cursor:pointer;
      transition:background-color .12s ease;
    }
    .mafia-leave-cancel:hover{background:var(--bg-hover)}

    /* The teleprompter card — the star of the screen. */
    .mafia-narr-stage{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:18px 18px 22px;
      display:flex;flex-direction:column;gap:16px;flex:1;
    }
    .mafia-narr-stage-head{display:flex;align-items:center;gap:10px}
    .mafia-narr-stage-emoji{font-size:22px;line-height:1;flex-shrink:0}
    .mafia-narr-stage-phase{font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.01em}
    .mafia-narr-stage-sub{
      margin-inline-start:auto;font-size:10px;font-weight:800;letter-spacing:.14em;
      text-transform:uppercase;color:var(--text-tertiary);white-space:nowrap;
    }
    .mafia-narr-lines{display:flex;flex-direction:column;gap:16px}
    .mafia-narr-lines-compact{gap:12px}
    .mafia-narr-line{display:flex;flex-direction:column;gap:5px}
    /* Spoken line — large, read verbatim. Leading quote glyph signals "say". */
    .mafia-narr-say{
      margin:0;font-size:16.5px;line-height:1.5;color:var(--text);font-weight:500;
      padding-inline-start:17px;position:relative;
    }
    .mafia-narr-say::before{
      content:"\201C";position:absolute;inset-inline-start:0;top:0;
      font-size:22px;line-height:1.1;color:var(--text-tertiary);font-weight:700;
    }
    /* Stage direction — small, muted, "do this" (NOT spoken). */
    .mafia-narr-do{
      margin:0;font-size:12.5px;line-height:1.45;color:var(--text-tertiary);
      font-style:italic;padding-inline-start:17px;display:flex;gap:6px;align-items:flex-start;
    }
    .mafia-narr-do-mark{font-style:normal;font-weight:800;opacity:.7;line-height:1.45}
    .mafia-narr-lines-compact .mafia-narr-say{font-size:15px}

    /* Primary forward action. */
    .mafia-narr-next{
      width:100%;padding:16px 18px;border:none;border-radius:var(--radius-md);
      background:var(--text);color:var(--bg);
      font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;
      display:flex;align-items:center;justify-content:center;gap:9px;
      transition:opacity .12s ease, transform .06s ease;
    }
    .mafia-narr-next:hover{opacity:.92}
    .mafia-narr-next:active{transform:scale(.99)}
    .mafia-narr-next svg{width:19px;height:19px;flex-shrink:0}

    /* End game — quiet, at the very bottom (rare, destructive). */
    .mafia-cards-narrator-end{
      margin-top:auto;width:100%;padding:13px;
      background:transparent;border:1px solid var(--border);border-radius:var(--radius-md);
      font-size:14px;font-weight:600;color:var(--text-tertiary);
      cursor:pointer;font-family:inherit;transition:background-color .12s ease,color .12s ease;
    }
    .mafia-cards-narrator-end:hover{background:var(--bg-hover);color:var(--text-secondary)}

    /* ===== Mafia Cards — narrator bottom-sheet content (redesign) =======
       Two sheets reached from the top toolbar: Who's who (cheat sheet) and
       Rules (tap-to-expand accordion). The third toolbar button (How to play)
       opens the lobby walkthrough video, not a sheet. Both sheets render into
       the app-wide .sheet shell. Calm by design — generous size + spacing,
       hierarchy via the sheet title + a one-line intro, no shouty all-caps.
       Monochrome. */
    .mafia-narr-sheet-intro{
      font-size:14px;line-height:1.55;color:var(--text-secondary);margin:-4px 0 16px;
    }
    /* Tap-to-expand row (custom div-based accordion) — used by the Rules sheet.
       Collapsed by default so the sheet opens short and calm. */
    .mafia-narr-acc{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);overflow:hidden;margin-bottom:10px;
    }
    .mafia-narr-acc-summary{
      width:100%;background:none;border:none;font-family:inherit;text-align:start;
      cursor:pointer;display:flex;align-items:center;gap:13px;
      padding:15px 16px;-webkit-tap-highlight-color:transparent;
    }
    .mafia-narr-acc-emoji{font-size:21px;line-height:1;flex-shrink:0}
    .mafia-narr-acc-title{flex:1;font-size:15.5px;font-weight:700;color:var(--text);letter-spacing:-.01em}
    .mafia-narr-acc-chev{flex-shrink:0;color:var(--text-tertiary);display:inline-flex;transition:transform .28s cubic-bezier(.4,0,.2,1)}
    .mafia-narr-acc[data-open="true"] .mafia-narr-acc-chev{transform:rotate(180deg)}
    /* Smooth height animation via the grid 0fr→1fr trick (widely supported).
       The inner wrapper clips so the body's border/padding stay hidden while
       collapsed. JS keeps only one row open per sheet. */
    .mafia-narr-acc-wrap{
      display:grid;grid-template-rows:0fr;
      transition:grid-template-rows .28s cubic-bezier(.4,0,.2,1);
    }
    .mafia-narr-acc[data-open="true"] .mafia-narr-acc-wrap{grid-template-rows:1fr}
    .mafia-narr-acc-inner{overflow:hidden;min-height:0}
    .mafia-narr-acc-body{
      padding:12px 16px 16px;border-top:1px solid var(--border);
    }
    @media (prefers-reduced-motion: reduce){
      .mafia-narr-acc-wrap,.mafia-narr-acc-chev{transition:none}
    }
    .mafia-narr-acc-p{margin:0;font-size:14px;line-height:1.65;color:var(--text-secondary)}
    .mafia-narr-acc-p strong{color:var(--text);font-weight:600}
    /* Callout — the Detective's "lie for the Mafia Leader" exception. */
    .mafia-narr-callout{
      margin-top:13px;display:flex;gap:10px;align-items:flex-start;
      padding:12px 13px;border-radius:var(--radius-sm);
      background:var(--bg-hover);border:1px solid var(--border-strong);
    }
    .mafia-narr-callout-icon{flex-shrink:0;font-size:16px;line-height:1.5}
    .mafia-narr-callout-text{font-size:13.5px;line-height:1.55;color:var(--text)}
    .mafia-narr-callout-text strong{font-weight:700}
    .mafia-narr-acc-body .mafia-narr-lines{margin-top:2px}
    /* Who's who — clean cheat-sheet list (name left, role right). */
    .mafia-narr-who{display:flex;flex-direction:column;gap:7px}
    .mafia-narr-who-row{
      display:flex;align-items:center;gap:13px;padding:13px 14px;
      background:var(--bg-subtle);border:1px solid var(--border);border-radius:var(--radius-md);
    }
    .mafia-narr-who-name{flex:0 1 auto;font-size:15px;font-weight:700;color:var(--text);white-space:nowrap}
    .mafia-narr-who-emoji{font-size:20px;line-height:1;flex-shrink:0}
    .mafia-narr-who-role{flex:1 1 auto;text-align:end;font-size:14px;font-weight:600;color:var(--text-secondary);line-height:1.35}
    .mafia-narr-loading{padding:28px 12px;text-align:center;color:var(--text-tertiary);font-style:italic;font-size:14px}

    /* ===== Mafia Cards — player role screen (redesigned 2026-07-13) =========
       Role sits DEAD-CENTRE of the screen; two circular buttons float in the
       top-right corner (out of flow): "WIN" opens the How-to-win sheet, the
       play circle opens the walkthrough video. The single deliberate accent is
       the Reveal CTA (while hidden) / the role's emoji disc (once revealed);
       everything else stays neutral. */
    #screen-mafia-cards-role > main{
      padding:0;display:flex;flex-direction:column;min-height:100%;
    }
    .mafia-cards-role-screen{
      flex:1;position:relative;display:flex;flex-direction:column;
      padding:20px 20px 24px;min-height:100%;
    }
    /* Top-right circle cluster — absolute so it never shifts the centred role. */
    .mafia-cards-role-actions{
      position:absolute;top:16px;inset-inline-end:16px;z-index:3;
      display:flex;align-items:flex-start;gap:12px;
    }
    .mafia-cards-role-circle{
      width:54px;height:54px;min-width:54px;border-radius:var(--radius-pill);
      display:inline-flex;align-items:center;justify-content:center;
      background:var(--bg-subtle);border:1.5px solid var(--border-strong);
      color:var(--text);font:inherit;padding:0;cursor:pointer;
      transition:transform .1s ease,background-color .12s ease,border-color .12s ease;
    }
    .mafia-cards-role-circle:hover{background:var(--bg-hover)}
    .mafia-cards-role-circle:active{transform:scale(.94)}
    .mafia-cards-role-circle--win{flex-direction:column;gap:1px}
    .mafia-cards-role-circle-trophy{font-size:15px;line-height:1}
    .mafia-cards-role-circle-word{
      font-size:11px;font-weight:800;letter-spacing:.06em;line-height:1;color:var(--text);
    }
    .mafia-cards-role-circle--play svg{width:20px;height:20px;margin-inline-start:2px}
    /* Role body owns the centre of the space left between the cluster + status. */
    .mafia-cards-role-body{
      flex:1;min-height:0;display:flex;flex-direction:column;
      align-items:center;justify-content:center;
      gap:14px;text-align:center;
    }
    .mafia-cards-role-hidden-state,
    .mafia-cards-role-shown-state{
      display:flex;flex-direction:column;align-items:center;gap:10px;
    }
    .mafia-cards-role-hidden-icon{
      font-size:80px;line-height:1;opacity:.32;user-select:none;
    }
    .mafia-cards-role-hidden-title{
      font-size:22px;font-weight:800;letter-spacing:-.02em;color:var(--text);
    }
    .mafia-cards-role-hidden-sub{
      font-size:14.5px;color:var(--text-secondary);line-height:1.5;
      max-width:280px;
    }
    /* Revealed role — emoji inside a soft accent disc (game-object feel). */
    .mafia-cards-role-emoji-disc{
      width:120px;height:120px;border-radius:var(--radius-pill);
      display:flex;align-items:center;justify-content:center;margin-bottom:4px;
      background:var(--accent-soft);border:2px solid var(--accent);
      box-shadow:0 0 0 6px var(--accent-soft);
    }
    .mafia-cards-role-emoji{
      font-size:60px;line-height:1;user-select:none;
    }
    .mafia-cards-role-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;
      color:var(--text);line-height:1.15;
    }
    .mafia-cards-role-desc{
      font-size:15.5px;line-height:1.55;color:var(--text-secondary);
      max-width:320px;margin:0 auto;
    }
    .mafia-cards-role-teammates{
      display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;
      justify-content:center;margin-top:8px;padding:12px 18px;
      background:var(--danger-soft);border:1.5px solid var(--danger);
      border-radius:var(--radius-md);color:var(--danger);
      font-size:14px;font-weight:700;letter-spacing:-.005em;
    }
    .mafia-cards-role-teammates-label{
      font-weight:600;letter-spacing:.04em;font-size:11px;
      text-transform:uppercase;opacity:.85;
    }
    /* Reveal CTA — filled accent (the one accent while hidden); quiets to a
       neutral ghost once the role shows so the disc is the boldest thing. */
    .mafia-cards-role-toggle{
      margin-top:6px;display:inline-flex;align-items:center;gap:8px;
      padding:12px 24px;background:var(--accent);
      border:1.5px solid var(--accent);border-radius:var(--radius-pill);
      color:var(--on-accent);font:inherit;font-size:15px;font-weight:700;
      letter-spacing:.01em;cursor:pointer;box-shadow:var(--shadow-md);
      transition:transform .1s ease,background-color .12s ease,border-color .12s ease;
    }
    .mafia-cards-role-toggle:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
    .mafia-cards-role-toggle:active{transform:scale(.97)}
    .mafia-cards-role-toggle svg{width:16px;height:16px;flex-shrink:0}
    .mafia-cards-role-toggle.is-shown{
      background:transparent;border-color:var(--border-strong);
      color:var(--text-secondary);box-shadow:none;
    }
    .mafia-cards-role-toggle.is-shown:hover{background:var(--bg-hover)}
    /* Narrator-status hint + room-code chip sit together in normal flow at the
       bottom (the role body above them is flex:1 and stays centred in the space
       that remains) — so the chip can never overlap the status text. */
    .mafia-cards-role-status{
      padding:0 20px;
      text-align:center;font-size:13px;color:var(--text-tertiary);line-height:1.4;
    }
    /* ===== How-to-win sheet (opened by the WIN circle) — bottom sheet with
       Town vs Mafia cards that teach who beats whom. ===== */
    .mafia-cards-win-sheet{
      position:fixed;inset:0;z-index:250;
      display:flex;align-items:flex-end;justify-content:center;
    }
    .mafia-cards-win-sheet[hidden]{display:none}
    .mafia-cards-win-scrim{position:absolute;inset:0;background:var(--scrim)}
    .mafia-cards-win-panel{
      position:relative;width:100%;max-width:480px;
      background:var(--surface-elevated);
      border-radius:var(--radius-xl) var(--radius-xl) 0 0;
      padding:10px 20px calc(22px + env(safe-area-inset-bottom,0px));
      box-shadow:var(--shadow-lg);
      animation:mafiaWinSlideUp .26s cubic-bezier(.22,1,.36,1) both;
    }
    @media(prefers-reduced-motion:reduce){
      .mafia-cards-win-panel{animation:none}
    }
    @keyframes mafiaWinSlideUp{from{transform:translateY(100%)}to{transform:none}}
    .mafia-cards-win-grab{
      width:40px;height:4px;border-radius:var(--radius-pill);
      background:var(--border-strong);margin:2px auto 14px;
    }
    .mafia-cards-win-head{display:flex;align-items:center;gap:9px;margin-bottom:14px}
    .mafia-cards-win-emoji{font-size:22px;line-height:1}
    .mafia-cards-win-title{flex:1;font-size:18px;font-weight:800;color:var(--text);margin:0}
    .mafia-cards-win-x{
      width:34px;height:34px;flex-shrink:0;border:none;background:transparent;
      color:var(--text-secondary);border-radius:var(--radius-pill);cursor:pointer;
      display:flex;align-items:center;justify-content:center;
    }
    .mafia-cards-win-x:hover{background:var(--bg-hover)}
    .mafia-cards-win-teams{display:flex;flex-direction:column;gap:10px}
    .mafia-cards-win-team{
      border-radius:var(--radius-lg);padding:13px 15px;border:1.5px solid transparent;
    }
    .mafia-cards-win-team--town{background:var(--success-soft);border-color:var(--success)}
    .mafia-cards-win-team--mafia{background:var(--danger-soft);border-color:var(--danger)}
    .mafia-cards-win-team-badge{display:flex;align-items:center;gap:8px;margin-bottom:5px}
    .mafia-cards-win-team-badge>span[aria-hidden]{font-size:19px;line-height:1}
    .mafia-cards-win-team-name{font-size:15px;font-weight:800}
    .mafia-cards-win-team--town .mafia-cards-win-team-name{color:var(--success)}
    .mafia-cards-win-team--mafia .mafia-cards-win-team-name{color:var(--danger)}
    .mafia-cards-win-team-line{font-size:14px;line-height:1.5;color:var(--text-secondary)}
    .mafia-cards-role-status{
      font-size:13px;color:var(--text-tertiary);font-style:italic;
      text-align:center;line-height:1.45;padding:14px 20px 0;
    }
    .mafia-cards-placeholder{
      display:flex;flex-direction:column;align-items:center;justify-content:center;
      text-align:center;padding:48px 24px;min-height:60vh;gap:14px;
    }
    .mafia-cards-placeholder-emoji{
      font-size:72px;line-height:1;user-select:none;opacity:.7;margin-bottom:4px;
    }
    .mafia-cards-placeholder-title{
      font-size:24px;font-weight:800;color:var(--text);letter-spacing:-.02em;
    }
    .mafia-cards-placeholder-body{
      font-size:14.5px;line-height:1.55;color:var(--text-secondary);
      max-width:340px;
    }

    
    .mafia-prototype-hint{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:10px 14px;margin:0 0 14px;
      font-size:12.5px;line-height:1.5;color:var(--text-secondary);
    }
    .mafia-prototype-hint strong{color:var(--text);font-weight:700}

    /* ===== Mafia — Rules screen (pre-game gate) =====
       Shown to all perspectives (players + narrator) after Start Game,
       BEFORE the first narrator beat. Each user reads the rules then
       taps Ready. Once everyone is ready, the game advances directly to
       opening-night1-open — skipping the now-redundant opening-setup
       and opening-roles beats. Reduces narrator read-aloud burden. */
    #screen-mafia-rules > main{padding:16px 16px 24px;display:flex;flex-direction:column;gap:14px}
    .mafia-rules-title{font-size:22px;font-weight:800;letter-spacing:-.02em;color:var(--text);text-align:center;margin:4px 0 2px}
    .mafia-rules-intro{font-size:14px;color:var(--text-secondary);text-align:center;line-height:1.45;margin-bottom:4px}
    .mafia-rules-section{background:var(--bg-subtle);border:1px solid var(--border);border-radius:var(--radius-md);padding:14px 16px}
    [data-theme="dark"] .mafia-rules-section{background:rgba(255,255,255,.04)}
    .mafia-rules-section h3{margin:0 0 10px;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-tertiary)}
    .mafia-rules-section p{margin:0;font-size:14.5px;line-height:1.55;color:var(--text)}
    .mafia-rules-roles{display:flex;flex-direction:column;gap:8px}
    .mafia-rules-role{display:flex;align-items:flex-start;gap:12px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm)}
    [data-theme="dark"] .mafia-rules-role{background:rgba(0,0,0,.25)}
    .mafia-rules-role-emoji{font-size:28px;line-height:1;flex-shrink:0;width:36px;text-align:center}
    .mafia-rules-role-text{flex:1;min-width:0}
    .mafia-rules-role-name{font-size:14.5px;font-weight:700;color:var(--text);margin-bottom:2px}
    .mafia-rules-role-desc{font-size:13px;color:var(--text-secondary);line-height:1.5}
    .mafia-rules-steps{display:flex;flex-direction:column;gap:10px}
    .mafia-rules-step{display:flex;gap:10px;align-items:flex-start;font-size:14px;color:var(--text);line-height:1.5}
    .mafia-rules-step-icon{font-size:18px;line-height:1.4;flex-shrink:0;width:24px;text-align:center}
    .mafia-rules-step-text{flex:1;min-width:0}
    .mafia-rules-step-text b{font-weight:700;color:var(--text)}
    .mafia-rules-tips{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:7px}
    .mafia-rules-tips li{font-size:13.5px;color:var(--text-secondary);line-height:1.5;padding-inline-start:18px;position:relative}
    .mafia-rules-tips li::before{content:"";position:absolute;inset-inline-start:6px;top:9px;width:4px;height:4px;background:var(--text-tertiary);border-radius:50%}
    .mafia-rules-ready-bar{position:sticky;bottom:0;background:var(--bg);padding-top:12px;margin-top:4px;display:flex;flex-direction:column;gap:8px;z-index:2}
    .mafia-rules-ready-count{text-align:center;font-size:13px;color:var(--text-secondary);font-weight:600}
    .mafia-rules-ready-count b{color:var(--text)}
    /* Post-tap "ready" state — explicitly overrides the default disabled-button
       opacity fade so the confirmation reads cleanly. White outline + subtle
       inner tint differentiates this from the solid "I'm Ready" CTA without
       any green/colour accent (per project palette rules). */
    .mafia-rules-ready-btn.is-ready,
    .mafia-rules-ready-btn.is-ready:disabled{
      background:rgba(0,0,0,.04);color:var(--text);
      border:2px solid var(--text);
      font-weight:700;letter-spacing:.02em;
      opacity:1;cursor:default;
      display:inline-flex;align-items:center;justify-content:center;gap:8px;
    }
    [data-theme="dark"] .mafia-rules-ready-btn.is-ready,
    [data-theme="dark"] .mafia-rules-ready-btn.is-ready:disabled{
      background:rgba(255,255,255,.06);
    }
    .mafia-rules-ready-btn.is-ready::before{
      content:"";display:inline-block;width:18px;height:18px;flex-shrink:0;
      background:var(--text);
      -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 13l4 4L19 7' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / contain no-repeat;
      mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 13l4 4L19 7' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / contain no-repeat;
    }

    /* ===== Mafia role card (Phase 4) =====
       The full-screen private role reveal that each non-narrator player
       sees once roles are dealt. Stays visible for the whole game until
       the player is eliminated or game ends. Locked — no game-action UI.
       During vote phase a sibling .mafia-vote-grid takes over (Phase 7);
       this screen returns afterward. */
    #screen-mafia-role > main{
      display:flex;flex-direction:column;justify-content:space-between;
      padding:24px 20px 28px;min-height:100%;
    }
    .mafia-role-card{
      flex:1;display:flex;flex-direction:column;justify-content:center;
      align-items:center;text-align:center;padding:32px 12px;gap:14px;
    }
    .mafia-role-emoji{
      font-size:88px;line-height:1;margin-bottom:6px;user-select:none;
      transition:opacity .25s ease,transform .25s ease;
    }
    .mafia-role-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;
      color:var(--text);line-height:1.15;
    }
    .mafia-role-desc{
      font-size:15.5px;line-height:1.55;color:var(--text-secondary);
      max-width:320px;margin:0 auto;
    }
    .mafia-role-teammates{
      display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;
      justify-content:center;margin-top:8px;padding:12px 18px;
      background:var(--danger-soft);border:1.5px solid var(--danger);
      border-radius:var(--radius-md);color:var(--danger);
      font-size:14px;font-weight:700;letter-spacing:-.005em;
    }
    .mafia-role-teammates-label{
      font-weight:600;letter-spacing:.04em;font-size:11px;
      text-transform:uppercase;opacity:.85;
    }
    .mafia-role-status{
      font-size:13px;color:var(--text-tertiary);font-style:italic;
      text-align:center;line-height:1.45;padding:0 20px;
    }
    .mafia-role-actions{
      display:flex;justify-content:center;gap:10px;margin-top:10px;
    }
    .mafia-role-hide-toggle{
      display:inline-flex;align-items:center;gap:6px;
      padding:9px 16px;background:transparent;
      border:1.5px solid var(--border-strong);border-radius:var(--radius-pill);
      color:var(--text-secondary);font:inherit;font-size:13px;
      font-weight:600;cursor:pointer;transition:all .15s ease;
    }
    .mafia-role-hide-toggle:hover{background:var(--bg-subtle);color:var(--text);border-color:var(--text)}
    .mafia-role-hide-toggle svg{width:14px;height:14px}

    /* Hidden state — replaces the role content with a "tap to peek" prompt.
       Implemented with a class on .mafia-role-card so we don't unmount nodes. */
    .mafia-role-card.is-hidden .mafia-role-emoji,
    .mafia-role-card.is-hidden .mafia-role-title,
    .mafia-role-card.is-hidden .mafia-role-desc,
    .mafia-role-card.is-hidden .mafia-role-teammates{
      display:none;
    }
    .mafia-role-hidden-block{display:none;flex-direction:column;align-items:center;gap:14px}
    .mafia-role-card.is-hidden .mafia-role-hidden-block{display:flex}
    .mafia-role-hidden-icon{font-size:72px;opacity:.35;user-select:none}
    .mafia-role-hidden-text{
      font-size:15px;color:var(--text-secondary);font-weight:600;
      letter-spacing:-.005em;
    }

    /* Role-specific accent tints (subtle — full background tint feels heavy
       on a phone screen, so we lean into the emoji + soft border). */
    .mafia-role-card[data-role="mafia"]        .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(239,68,68,.25))}
    .mafia-role-card[data-role="mafia_leader"] .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(168,85,247,.30))}
    .mafia-role-card[data-role="detective"]    .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(59,130,246,.25))}
    .mafia-role-card[data-role="doctor"]       .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(34,197,94,.25))}
    .mafia-role-card[data-role="child"]        .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(250,204,21,.30))}
    .mafia-role-card[data-role="villager"]     .mafia-role-emoji{filter:drop-shadow(0 0 18px rgba(168,168,168,.25))}

    /* ===== Mafia narrator screen (Phase 5) =====
       The script-driven UI the narrator uses to run the whole game. Each
       "beat" is one read-aloud line + optional stage direction + an action
       (Continue, or a tap-target list, or vote-tally panel later).

       Layout:
         • Phase banner pill (NIGHT 1 / DAY 2 etc.)
         • Mode badge (Opening · Round 1)
         • Read-aloud card (cinematic typography)
         • Stage direction line (italic grey)
         • Action panel (Continue button or future tile pickers)
         • Status row at the bottom (alive count / dead count). */
    #screen-mafia-narrator > main{
      display:flex;flex-direction:column;padding:18px 18px 22px;gap:14px;min-height:100%;
    }
    .mafia-narrator-banner-row{
      display:flex;align-items:center;justify-content:space-between;gap:10px;
    }
    .mafia-narrator-phase{
      display:inline-flex;align-items:center;gap:8px;
      padding:7px 14px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);border:1px solid var(--border-strong);
      font-size:11.5px;font-weight:800;letter-spacing:.08em;
      text-transform:uppercase;color:var(--text);
    }
    .mafia-narrator-phase[data-phase-kind="night"]{
      background:#0f172a;color:#cbd5e1;border-color:#1e293b;
    }
    [data-theme="dark"] .mafia-narrator-phase[data-phase-kind="night"]{
      background:#1e293b;color:#e2e8f0;border-color:#334155;
    }
    .mafia-narrator-phase[data-phase-kind="day"]{
      background:#fef3c7;color:#92400e;border-color:#fde68a;
    }
    [data-theme="dark"] .mafia-narrator-phase[data-phase-kind="day"]{
      background:#3a2810;color:#fde68a;border-color:#5a3f1c;
    }
    .mafia-narrator-mode{
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-tertiary);
    }
    .mafia-narrator-readaloud{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:22px 20px;flex:1;
      display:flex;flex-direction:column;justify-content:center;
      min-height:200px;
    }
    .mafia-narrator-readaloud-label{
      font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
      color:var(--text-tertiary);margin-bottom:12px;
    }
    .mafia-narrator-readaloud-text{
      font-size:19px;line-height:1.45;font-weight:600;letter-spacing:-.005em;
      color:var(--text);white-space:pre-wrap;
    }
    .mafia-narrator-stage-dir{
      display:flex;align-items:flex-start;gap:8px;
      padding:0 4px;font-size:13px;line-height:1.5;
      color:var(--text-secondary);font-style:italic;
    }
    .mafia-narrator-stage-dir svg{
      width:14px;height:14px;flex-shrink:0;margin-top:3px;
      stroke:var(--text-tertiary);
    }
    .mafia-narrator-action{display:flex;flex-direction:column;gap:8px}
    .mafia-narrator-action .btn{height:50px}
    .mafia-narrator-action-disabled-hint{
      font-size:12px;color:var(--text-tertiary);text-align:center;line-height:1.4;
      font-style:italic;
    }
    .mafia-narrator-status-row{
      display:flex;align-items:center;justify-content:space-between;gap:10px;
      padding:10px 14px;background:var(--bg-subtle);
      border:1px solid var(--border);border-radius:var(--radius-md);
      font-size:12px;color:var(--text-secondary);
    }
    .mafia-narrator-status-row .stat{display:inline-flex;align-items:center;gap:5px;font-weight:600}
    .mafia-narrator-status-row .stat strong{color:var(--text);font-weight:800}
    .mafia-narrator-status-row .sep{color:var(--text-tertiary)}

    /* ===== Narrator tap-target grid (Phase 6) =====
       Replaces the Continue button on night-action beats. The narrator taps
       the alive player tile that the role (Mafia / Detective / Doctor)
       silently pointed at. */
    .mafia-target-grid{
      display:grid;grid-template-columns:repeat(2,1fr);gap:8px;
    }
    .mafia-target-tile{
      display:flex;align-items:center;justify-content:center;gap:6px;
      min-height:52px;padding:10px 14px;
      background:var(--bg);color:var(--text);
      border:1.5px solid var(--border-strong);border-radius:var(--radius-md);
      font:inherit;font-size:14.5px;font-weight:700;letter-spacing:-.005em;
      cursor:pointer;text-align:center;
      transition:transform .12s ease,background .15s ease,border-color .15s ease;
    }
    .mafia-target-tile:hover{transform:translateY(-1px);border-color:var(--text);background:var(--bg-subtle)}
    .mafia-target-tile:active{transform:translateY(0)}
    .mafia-target-tile:disabled{opacity:.45;cursor:not-allowed;transform:none}
    .mafia-target-tile.is-pending{
      background:var(--primary);color:var(--on-primary);border-color:var(--primary);
    }
    .mafia-target-hint{
      font-size:12px;color:var(--text-tertiary);text-align:center;
      font-style:italic;margin-top:6px;line-height:1.4;
    }

    /* ===== Detective thumb banner (Phase 6 — SECURITY-CRITICAL) =====
       Full-overlay banner shown to the narrator ONLY when the Detective's
       investigation result comes back. The narrator gives a discreet 👍 / 👎
       hand signal to the Detective in person — the answer never appears on
       any other phone. Auto-locks for 3 seconds so the narrator can't skip
       past before delivering the signal. */
    .mafia-thumb-banner-backdrop{
      position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.78);
      display:none;flex-direction:column;align-items:center;justify-content:center;
      padding:24px;text-align:center;
    }
    .mafia-thumb-banner-backdrop.active{display:flex}
    .mafia-thumb-banner-icon{
      font-size:140px;line-height:1;margin-bottom:18px;
      animation:mafia-thumb-pop .35s ease-out;
      user-select:none;
    }
    @keyframes mafia-thumb-pop{
      from{transform:scale(0.5);opacity:0}
      to{transform:scale(1);opacity:1}
    }
    .mafia-thumb-banner-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;color:#fff;
      margin-bottom:8px;line-height:1.15;
    }
    .mafia-thumb-banner-title.is-mafia{color:#fca5a5}
    .mafia-thumb-banner-title.is-not-mafia{color:#86efac}
    .mafia-thumb-banner-sub{
      font-size:15.5px;line-height:1.5;color:#e5e7eb;
      max-width:320px;margin:0 auto 22px;
    }
    .mafia-thumb-banner-countdown{
      display:inline-flex;align-items:center;gap:8px;
      padding:8px 18px;background:rgba(255,255,255,.1);
      border-radius:var(--radius-pill);font-size:13px;color:#cbd5e1;
      font-weight:600;letter-spacing:.04em;
    }
    .mafia-thumb-banner-countdown-num{font-weight:800;color:#fff;font-size:15px;min-width:14px;text-align:center}
    @media (prefers-reduced-motion: reduce){
      .mafia-thumb-banner-icon{animation:none}
    }

    /* ===== Mafia vote screen (Phase 7) =====
       Shown to ALIVE players only when state.phase='vote' or 'vote-tie'.
       The role card is the default for non-narrator players (Phase 4);
       during vote phase the dispatcher swaps in this screen so each
       alive player can pick a target. After tapping, the screen flips
       to a confirmation card. Eliminated players never see this screen. */
    #screen-mafia-vote > main{
      display:flex;flex-direction:column;padding:24px 18px 22px;gap:18px;min-height:100%;
    }
    .mafia-vote-header{text-align:center;padding:6px 0 4px}
    .mafia-vote-title{
      font-size:22px;font-weight:800;letter-spacing:-.02em;
      color:var(--text);line-height:1.2;
    }
    .mafia-vote-sub{
      font-size:14px;color:var(--text-secondary);margin-top:6px;
      line-height:1.45;
    }
    .mafia-vote-tied-pill{
      display:inline-flex;align-items:center;gap:6px;padding:5px 12px;
      background:var(--danger-soft);border:1px solid var(--danger);
      border-radius:var(--radius-pill);color:var(--danger);
      font-size:11.5px;font-weight:800;letter-spacing:.05em;
      text-transform:uppercase;margin-top:8px;
    }
    .mafia-vote-grid{
      display:grid;grid-template-columns:repeat(2,1fr);gap:10px;
    }
    .mafia-vote-tile{
      display:flex;align-items:center;justify-content:center;
      min-height:64px;padding:12px;
      background:var(--bg);color:var(--text);
      border:1.5px solid var(--border-strong);border-radius:var(--radius-md);
      font:inherit;font-size:15.5px;font-weight:700;letter-spacing:-.005em;
      cursor:pointer;text-align:center;
      transition:transform .12s ease,background .15s ease,border-color .15s ease;
    }
    .mafia-vote-tile:hover{transform:translateY(-1px);border-color:var(--text);background:var(--bg-subtle)}
    .mafia-vote-tile:disabled{opacity:.45;cursor:not-allowed;transform:none}
    .mafia-vote-tile.is-locked-choice{
      background:var(--primary);color:var(--on-primary);border-color:var(--primary);
    }
    .mafia-vote-locked-card{
      flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
      text-align:center;gap:14px;padding:40px 20px;
    }
    .mafia-vote-locked-emoji{font-size:64px;line-height:1}
    .mafia-vote-locked-title{font-size:22px;font-weight:800;color:var(--text);letter-spacing:-.01em}
    .mafia-vote-locked-sub{font-size:14.5px;color:var(--text-secondary);max-width:300px;line-height:1.5}
    .mafia-vote-status{
      text-align:center;font-size:12.5px;color:var(--text-tertiary);
      font-style:italic;line-height:1.45;
    }

    /* ===== Mafia "you're out" lock (Phase 7) =====
       Eliminated player's permanent screen for the rest of the game. */
    #screen-mafia-out > main{
      display:flex;flex-direction:column;justify-content:center;align-items:center;
      padding:40px 24px;text-align:center;gap:16px;min-height:100%;
    }
    .mafia-out-emoji{
      font-size:96px;line-height:1;filter:grayscale(.4);opacity:.85;
    }
    .mafia-out-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;
      color:var(--text);line-height:1.15;
    }
    .mafia-out-role-pill{
      display:inline-flex;align-items:center;gap:6px;padding:7px 16px;
      background:var(--bg-subtle);border:1.5px solid var(--border-strong);
      border-radius:var(--radius-pill);font-size:13px;font-weight:700;
      color:var(--text);letter-spacing:-.005em;
    }
    .mafia-out-sub{
      font-size:15px;line-height:1.55;color:var(--text-secondary);
      max-width:320px;margin:0 auto;
    }

    /* ===== Mafia end-game result screen (Phase 8) =====
       The final reveal — everyone lands here when state.phase='end'.
       Shows outcome hero, full role reveal grid (every player), play-again
       button (host only), and back-to-games button (anyone). */
    #screen-mafia-result > main{
      display:flex;flex-direction:column;padding:24px 18px 28px;gap:18px;min-height:100%;
    }
    .mafia-result-hero{
      display:flex;flex-direction:column;align-items:center;text-align:center;
      gap:12px;padding:28px 16px 22px;border-radius:var(--radius-lg);
      background:var(--bg-subtle);border:1.5px solid var(--border);
    }
    .mafia-result-hero[data-winner="town"]{
      background:var(--success-soft);border-color:var(--success);
    }
    .mafia-result-hero[data-winner="mafia"]{
      background:var(--danger-soft);border-color:var(--danger);
    }
    .mafia-result-hero-emoji{font-size:72px;line-height:1;user-select:none}
    .mafia-result-hero-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;
      color:var(--text);line-height:1.15;
    }
    .mafia-result-hero[data-winner="town"] .mafia-result-hero-title{color:var(--success)}
    .mafia-result-hero[data-winner="mafia"] .mafia-result-hero-title{color:var(--danger)}
    .mafia-result-hero-sub{
      font-size:14.5px;line-height:1.5;color:var(--text-secondary);
      max-width:320px;margin:0 auto;
    }
    .mafia-result-section-label{
      font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
      color:var(--text-tertiary);margin:6px 4px;
    }
    .mafia-result-grid{
      display:flex;flex-direction:column;gap:6px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:8px;
    }
    .mafia-result-row{
      display:flex;align-items:center;gap:12px;padding:10px 12px;
      background:var(--bg);border-radius:var(--radius-sm);
      border:1px solid var(--border);
    }
    .mafia-result-row.is-dead{opacity:.7}
    .mafia-result-row.is-narrator{
      background:var(--bg-subtle);border-style:dashed;
    }
    .mafia-result-row-emoji{
      font-size:22px;line-height:1;width:28px;text-align:center;flex-shrink:0;
    }
    .mafia-result-row-info{flex:1;min-width:0}
    .mafia-result-row-name{
      font-size:14.5px;font-weight:700;color:var(--text);letter-spacing:-.005em;
    }
    .mafia-result-row-role{
      font-size:12.5px;color:var(--text-secondary);margin-top:1px;
    }
    .mafia-result-row-status{
      font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
      padding:3px 8px;border-radius:var(--radius-pill);flex-shrink:0;
    }
    .mafia-result-row-status.alive{background:var(--success-soft);color:var(--success)}
    .mafia-result-row-status.dead{background:var(--bg-subtle);color:var(--text-tertiary)}
    .mafia-result-row-status.narrator{background:var(--bg-subtle);color:var(--text)}
    .mafia-result-actions{
      display:flex;flex-direction:column;gap:10px;margin-top:4px;
    }
    .mafia-result-actions .btn{height:50px}
    .mafia-result-rotate-hint{
      font-size:12px;color:var(--text-tertiary);text-align:center;line-height:1.45;
      font-style:italic;margin-top:-2px;
    }

    /* ===== Narrator vote-watch panel (Phase 7) ===== */
    .mafia-vote-tally{
      display:flex;flex-direction:column;gap:6px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:12px 14px;
    }
    .mafia-vote-tally-row{
      display:flex;align-items:center;justify-content:space-between;
      padding:6px 4px;border-bottom:1px solid var(--border);
      font-size:14px;color:var(--text);
    }
    .mafia-vote-tally-row:last-child{border-bottom:none}
    .mafia-vote-tally-name{font-weight:700}
    .mafia-vote-tally-count{
      display:inline-flex;align-items:center;justify-content:center;
      min-width:24px;height:24px;padding:0 8px;border-radius:12px;
      background:var(--bg);border:1px solid var(--border-strong);
      font-size:12px;font-weight:800;color:var(--text);
    }
    .mafia-vote-tally-empty{
      padding:16px 4px;text-align:center;font-size:13px;
      color:var(--text-tertiary);font-style:italic;
    }
    .mafia-vote-progress-text{
      font-size:12px;color:var(--text-secondary);text-align:center;
      letter-spacing:.04em;font-weight:600;
    }

    /* Respect reduced motion */

    /* ===== Feedback compose popup ===== */
    .compose-textarea{
      width:100%;min-height:140px;padding:12px 14px;box-sizing:border-box;
      background:var(--bg-subtle);border:1px solid var(--border-strong);border-radius:var(--radius-md);
      font:inherit;font-size:15px;line-height:1.45;color:var(--text);resize:vertical;
      -webkit-appearance:none;outline:none;
    }
    .compose-textarea:focus{border-color:var(--text);box-shadow:0 0 0 3px var(--focus-ring)}
    .compose-textarea::placeholder{color:var(--text-tertiary)}
    .compose-actions{display:flex;gap:10px;margin-top:14px}
    .compose-actions .btn{flex:1;height:46px}
    .compose-counter{font-size:11px;color:var(--text-tertiary);text-align:end;margin-top:6px}

    /* ===== Feedback board screen ===== */
    .feedback-tabs{
      display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;
      margin:0 -4px 12px;padding:0 4px 2px;
    }
    /* Persistent per-tab description — always visible above the post list
       so users know what each category is for, not just when empty. */
    .feedback-board-desc{
      font-size:13px;line-height:1.5;
      color:var(--text-secondary);
      padding:0 2px 14px;
      margin-bottom:4px;
      border-bottom:1px solid var(--border);
    }
    .feedback-board-desc:empty{display:none}
    .feedback-tabs::-webkit-scrollbar{display:none}
    .feedback-tab{
      flex:0 0 auto;display:flex;align-items:center;gap:6px;
      padding:9px 14px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);border:1px solid transparent;color:var(--text-secondary);
      font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;
      transition:background .15s ease,border-color .15s ease,color .15s ease;
    }
    .feedback-tab svg{width:14px;height:14px;flex-shrink:0}
    .feedback-tab .count{
      background:var(--bg);color:var(--text-secondary);
      font-size:11px;padding:1px 7px;border-radius:var(--radius-pill);font-weight:700;
    }
    .feedback-tab.active{background:var(--bg);border-color:var(--text);color:var(--text)}
    .feedback-tab.active .count{background:var(--text);color:var(--bg)}
    .feedback-post{
      background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);
      padding:14px;margin-bottom:10px;transition:border-color .18s ease;
    }
    .feedback-post.is-top{border-color:var(--text-tertiary)}
    .feedback-post-text{font-size:14px;line-height:1.5;color:var(--text);white-space:pre-wrap;word-wrap:break-word;overflow-wrap:anywhere}
    .feedback-post-footer{margin-top:12px;display:flex;align-items:center;gap:8px}
    .feedback-post-meta{font-size:12px;color:var(--text-tertiary);display:flex;align-items:center;gap:8px;flex:1;min-width:0}
    .feedback-post-meta .dot{width:3px;height:3px;border-radius:50%;background:var(--text-tertiary);flex-shrink:0}
    .feedback-post-meta .lang-tag{
      padding:2px 6px;border-radius:4px;background:var(--bg-subtle);
      font-size:10px;font-weight:700;letter-spacing:.04em;color:var(--text-secondary);
    }
    .feedback-post-meta .edited-tag{font-style:italic;color:var(--text-tertiary)}
    /* Inline translation affordance under the body. Hint = passive status (loading/error),
       link = tappable toggle between translated and original views. */
    .fb-translate-row{margin-top:6px;display:flex;align-items:center;gap:6px;min-height:18px}
    .fb-translate-link{
      background:none;border:none;padding:0;margin:0;cursor:pointer;
      font-size:12.5px;font-weight:600;color:var(--text-secondary);
      display:inline-flex;align-items:center;gap:5px;
    }
    .fb-translate-link:hover{color:var(--text)}
    .fb-translate-link:disabled{opacity:.55;cursor:default}
    .fb-translate-hint{font-size:12.5px;color:var(--text-tertiary);display:inline-flex;align-items:center;gap:6px}
    .fb-translate-hint.fb-error{color:var(--danger)}
    .fb-translate-dot{width:10px;height:10px;border:2px solid var(--text-tertiary);border-top-color:transparent;border-radius:50%;animation:fbSpin .8s linear infinite}
    @keyframes fbSpin{to{transform:rotate(360deg)}}
    .feedback-post-actions{display:flex;align-items:center;gap:4px;flex-shrink:0}
    .fb-vote{
      display:inline-flex;align-items:center;gap:5px;
      height:30px;padding:0 11px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);border:1px solid transparent;
      color:var(--text-secondary);font-size:12px;font-weight:700;
      cursor:pointer;user-select:none;
      transition:background .15s ease,color .15s ease,transform .12s ease,border-color .15s ease;
    }
    .fb-vote:hover{background:var(--bg-hover)}
    .fb-vote:active{transform:scale(.94)}
    .fb-vote svg{width:14px;height:14px;transition:transform .18s ease}
    .fb-vote.voted{background:rgba(239,68,68,.12);color:#ef4444;border-color:rgba(239,68,68,.25)}
    .fb-vote.voted svg{fill:#ef4444;stroke:#ef4444;animation:fbHeartPop .32s ease-out}
    @keyframes fbHeartPop{0%{transform:scale(1)}40%{transform:scale(1.35)}100%{transform:scale(1)}}
    .fb-overflow{
      width:32px;height:32px;border-radius:var(--radius-pill);
      border:none;background:transparent;color:var(--text-secondary);
      display:inline-flex;align-items:center;justify-content:center;cursor:pointer;
      transition:background .15s ease,color .15s ease;
    }
    .fb-overflow:hover{background:var(--bg-subtle);color:var(--text)}
    .fb-overflow svg{width:18px;height:18px}
    .fb-action-sheet{
      background:var(--surface-elevated);
      border-radius:var(--radius-lg) var(--radius-lg) 0 0;
      padding:6px 10px calc(14px + env(safe-area-inset-bottom));
      width:100%;max-width:480px;
      box-shadow:0 -8px 24px rgba(0,0,0,.08);
      transform:translateY(100%);transition:transform .22s ease;
    }
    [data-theme="dark"] .fb-action-sheet{box-shadow:0 -8px 24px rgba(0,0,0,.4)}
    .sheet-backdrop.active .fb-action-sheet{transform:translateY(0)}
    .fb-action-handle{width:36px;height:4px;border-radius:2px;background:var(--border-strong);margin:8px auto 10px;opacity:.55}
    .fb-action-row{
      width:100%;display:flex;align-items:center;gap:14px;
      padding:14px 16px;border:none;background:transparent;text-align:start;
      font-size:15.5px;font-weight:500;color:var(--text);
      cursor:pointer;border-radius:var(--radius-md);
      transition:background .12s ease;
    }
    .fb-action-row + .fb-action-row{margin-top:2px}
    .fb-action-row:hover{background:var(--bg-subtle)}
    .fb-action-row:active{background:var(--bg-hover)}
    .fb-action-row svg{width:20px;height:20px;flex-shrink:0;color:var(--text-secondary)}
    .fb-action-row.is-danger{color:var(--danger)}
    .fb-action-row.is-danger svg{color:var(--danger)}
    /* On wider viewports the backdrop centers the sheet — round every corner so
       it reads as a floating card rather than a drawer stuck to the bottom. */
    @media(min-width:600px){
      .fb-action-sheet{border-radius:var(--radius-lg);padding:10px 10px 14px;margin-bottom:24px}
      .fb-action-handle{display:none}
    }
    .feedback-empty{text-align:center;padding:48px 24px;color:var(--text-secondary)}
    .feedback-empty-emoji{font-size:36px;margin-bottom:10px}
    .feedback-empty-title{font-size:15px;font-weight:600;color:var(--text);margin-bottom:6px}

    /* Empty state */
    .empty{text-align:center;padding:36px 20px;color:var(--text-secondary);border:1px dashed var(--border-strong);border-radius:var(--radius-lg);margin-top:8px}
    .empty-emoji{font-size:32px;margin-bottom:6px}

    /* Bottom sheet */
    .sheet-backdrop{
      position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:100;
      display:none;align-items:flex-end;justify-content:center;
    }
    .sheet-backdrop.active{display:flex}
    @media(min-width:600px){.sheet-backdrop{align-items:center}}
    .sheet{
      background:var(--bg);border-radius:var(--radius-xl) var(--radius-xl) 0 0;
      width:100%;max-width:480px;padding:20px 20px calc(env(safe-area-inset-bottom,0px) + 20px);
      animation:sheet-up .22s cubic-bezier(.2,.8,.2,1);
    }
    @media(min-width:600px){.sheet{border-radius:var(--radius-xl)}}
    @keyframes sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}
    .sheet-handle{
      width:36px;height:4px;background:var(--border-strong);border-radius:var(--radius-pill);
      margin:-8px auto 14px;
    }
    .sheet{max-height:88vh;overflow-y:auto}
    .sheet-title{font-size:20px;font-weight:700;letter-spacing:-.01em;margin-bottom:12px;line-height:1.25}
    .sheet-body{color:var(--text-secondary);line-height:1.55;margin-bottom:20px;font-size:14px;white-space:pre-line}
    .sheet-body strong{color:var(--text);font-weight:600}

    /* Structured "rule cards" inside info sheets */
    .info-blocks{white-space:normal}
    .info-blocks .info-intro{
      font-size:14.5px;line-height:1.55;color:var(--text-secondary);
      margin:0 0 6px;
    }
    .info-blocks .info-intro strong{color:var(--text);font-weight:700}
    .info-blocks .info-block{
      display:flex;gap:14px;padding:14px 0;
      border-top:1px solid var(--border);
    }
    .info-blocks .info-block:first-of-type{border-top:none;padding-top:18px}
    .info-blocks .info-block-emoji{
      font-size:24px;line-height:1.1;flex-shrink:0;width:30px;text-align:center;
    }
    .info-blocks .info-block-content{flex:1;min-width:0}
    .info-blocks .info-block-title{
      font-weight:700;font-size:14.5px;
      color:var(--text);margin-bottom:3px;
      letter-spacing:-.005em;
    }
    .info-blocks .info-block-text{
      font-size:13.5px;color:var(--text-secondary);line-height:1.55;
    }
    .info-blocks .info-block-text strong{color:var(--text);font-weight:700}
    .info-blocks .info-block-text .pill{
      display:inline-block;padding:1px 7px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);font-weight:700;color:var(--text);font-size:12.5px;
      border:1px solid var(--border);
    }

    /* ===== How to play trigger (in lobby) ===== */
    .howto-trigger{
      display:flex;align-items:center;gap:12px;padding:12px 14px;
      border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);
      cursor:pointer;margin-bottom:16px;transition:all .15s ease;position:relative;
      width:100%;text-align:start;font:inherit;color:inherit;
    }
    .howto-trigger:hover{border-color:var(--text);transform:translateY(-1px)}
    .howto-trigger-icon{
      width:36px;height:36px;border-radius:50%;background:var(--primary);color:var(--on-primary);
      display:flex;align-items:center;justify-content:center;flex-shrink:0;
    }
    .howto-trigger-icon svg{width:14px;height:14px;margin-inline-start:2px}
    .howto-trigger-text{flex:1;min-width:0}
    .howto-trigger-title{font-weight:600;font-size:15px;letter-spacing:-.005em}
    .howto-trigger-sub{font-size:12px;color:var(--text-secondary);margin-top:1px}
    .howto-trigger-chevron{color:var(--text-tertiary);flex-shrink:0}
    .howto-trigger.pulse::before{
      content:"";position:absolute;inset:-2px;border-radius:calc(var(--radius-lg) + 2px);
      border:2px solid var(--primary);opacity:0;pointer-events:none;
      animation:trigger-pulse 2.4s ease-out infinite;
    }
    @keyframes trigger-pulse{
      0%{opacity:0;transform:scale(.99)}
      18%{opacity:.45}
      100%{opacity:0;transform:scale(1.04)}
    }

    /* ===== Collapsible SETTINGS section (Hot Seat lobby) =====
       Closed by default each lobby entry. Tap header to reveal recommended button
       + Mode/Category/Rounds/Order rows. Mirrors .howto-trigger chrome above it. */
    .settings-collapse{margin-bottom:12px}
    .settings-collapse-header{
      display:flex;align-items:center;gap:12px;padding:14px;
      border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);
      cursor:pointer;transition:border-color .15s ease;
      width:100%;text-align:start;font:inherit;color:var(--text);
    }
    .settings-collapse-header:hover{border-color:var(--text)}
    .settings-collapse-header-label{
      flex:1;min-width:0;font-weight:600;font-size:15px;letter-spacing:-.005em;
    }
    .settings-collapse-chevron{
      color:var(--text-tertiary);flex-shrink:0;
      transition:transform .18s ease;
    }
    .settings-collapse.expanded .settings-collapse-chevron{transform:rotate(90deg)}
    .settings-collapse-body{display:none;margin-top:12px}
    .settings-collapse.expanded .settings-collapse-body{display:block}

    /* ===== How to play modal ===== */
    .howto-modal{
      position:fixed;inset:0;background:var(--bg);z-index:200;display:none;flex-direction:column;
    }
    .howto-modal.active{display:flex}
    @media(min-width:600px){
      .howto-modal{max-width:480px;left:50%;right:auto;transform:translateX(-50%);box-shadow:var(--shadow-lg)}
    }
    .howto-skip-btn{
      background:transparent;border:none;color:var(--text-secondary);font-size:14px;font-weight:500;
      padding:8px 14px;cursor:pointer;border-radius:var(--radius-pill);
    }
    .howto-skip-btn:hover{color:var(--text);background:var(--bg-subtle)}
    .howto-stage{flex:1;position:relative;overflow:hidden}
    .howto-slide{
      position:absolute;inset:0;display:flex;flex-direction:column;padding:8px 24px 8px;
      opacity:0;pointer-events:none;transition:opacity .35s ease;
    }
    .howto-slide.active{opacity:1;pointer-events:auto}
    .howto-visual{
      flex:1;display:flex;align-items:center;justify-content:center;position:relative;min-height:260px;
    }
    .howto-text{text-align:center;padding:0 8px 4px}
    .howto-text h2{font-size:22px;font-weight:700;letter-spacing:-.02em;margin:0 0 6px}
    .howto-text p{color:var(--text-secondary);margin:0;line-height:1.5;font-size:14px}
    .howto-bottom{
      padding:14px 24px calc(env(safe-area-inset-bottom,0px) + 16px);
      display:flex;flex-direction:column;align-items:center;gap:14px;
    }
    .howto-dots{display:flex;gap:6px}
    .howto-dot{
      width:8px;height:8px;border-radius:50%;background:var(--border-strong);cursor:pointer;
      transition:all .25s ease;border:none;padding:0;
    }
    .howto-dot.active{background:var(--text);width:24px;border-radius:4px}
    .howto-next-btn{width:100%;max-width:280px}

    /* Mini phone mockup */
    .mp{
      width:128px;height:248px;border:6px solid #1a1a1a;border-radius:22px;background:#fff;
      box-shadow:0 14px 28px rgba(0,0,0,.13),0 4px 8px rgba(0,0,0,.06);
      overflow:hidden;position:relative;flex-shrink:0;
    }
    .mp::before{
      content:"";position:absolute;top:0;left:50%;transform:translateX(-50%);
      width:34px;height:4px;background:#1a1a1a;border-radius:0 0 6px 6px;z-index:2;
    }
    .mp-screen{height:100%;background:#fff;display:flex;flex-direction:column;padding-top:6px}
    .mp-statusbar{
      font-size:8px;font-weight:700;color:var(--text);text-align:center;padding:6px 0 4px;
      letter-spacing:.04em;
    }
    .mp-statusbar.with-bar{border-bottom:1px solid var(--border)}
    .mp-body-mini{
      flex:1;display:flex;flex-direction:column;padding:8px;gap:6px;
      align-items:center;justify-content:center;
    }
    .mp-word-card-mini{
      width:100%;background:var(--bg);border:1px solid var(--border);border-radius:8px;
      padding:8px 6px;text-align:center;min-height:84px;
      display:flex;flex-direction:column;align-items:center;justify-content:center;
    }
    .mp-word-label-mini{
      font-size:7px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;
      color:var(--text-secondary);margin-bottom:4px;
    }
    .mp-word-shown{font-size:16px;font-weight:800;letter-spacing:-.02em;color:var(--text)}
    .mp-word-hidden{font-size:30px;text-align:center;line-height:1}
    .mp-hint-mini{font-size:7px;color:var(--text-tertiary);margin-top:4px;font-style:italic}
    .mp-actions-mini{display:flex;gap:4px;width:100%;margin-top:4px}
    .mp-btn-mini{
      flex:1;height:22px;border-radius:6px;font-size:8px;font-weight:700;
      display:flex;align-items:center;justify-content:center;
    }
    .mp-btn-mini.skip{background:#fff;border:1px solid var(--border-strong);color:var(--text)}
    .mp-btn-mini.got{background:var(--primary);color:var(--on-primary)}

    /* Slide 1 — table */
    .visual-table{display:flex;flex-direction:column;align-items:center;gap:14px}
    .table-phones{display:flex;gap:10px;justify-content:center;align-items:flex-end}
    .table-phones .mp{
      width:62px;height:108px;border-width:3.5px;border-radius:12px;
    }
    .table-phones .mp::before{width:18px;height:3px}
    .table-phones .mp-screen{padding-top:3px}
    .table-phones .mp-mini-content{
      flex:1;display:flex;align-items:center;justify-content:center;padding:4px;
    }
    .table-phones .mp-mini-avatar{
      width:34px;height:34px;border-radius:50%;
      background:linear-gradient(135deg,#e4e4e4 0%,#cfcfcf 100%);
      display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;
    }
    .howto-slide[data-slide="1"].active .table-phones .mp{animation:phone-up .55s ease both}
    .howto-slide[data-slide="1"].active .table-phones .mp:nth-child(2){animation-delay:.12s}
    .howto-slide[data-slide="1"].active .table-phones .mp:nth-child(3){animation-delay:.24s}
    .howto-slide[data-slide="1"].active .table-phones .mp:nth-child(4){animation-delay:.36s}
    .howto-slide[data-slide="1"].active .table-room-code{animation:code-pop .5s .6s ease both}
    @keyframes phone-up{from{opacity:0;transform:translateY(18px) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}
    @keyframes code-pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}
    .table-room-code{
      display:inline-flex;align-items:center;gap:8px;
      padding:9px 18px;background:var(--primary);color:var(--on-primary);
      border-radius:var(--radius-pill);font-weight:700;letter-spacing:.16em;font-size:14px;
    }

    /* Slide 2 — split */
    .visual-split{display:flex;gap:14px;justify-content:center;align-items:center}
    .phone-with-label{display:flex;flex-direction:column;align-items:center;gap:8px}
    .role-tag{
      display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:var(--radius-pill);
      font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
    }
    .howto-slide[data-slide="2"].active .phone-with-label:first-child{animation:split-left .55s ease both}
    .howto-slide[data-slide="2"].active .phone-with-label:last-child{animation:split-right .55s ease both}
    @keyframes split-left{from{opacity:0;transform:translateX(-22px) rotate(-8deg)}to{opacity:1;transform:translateX(0) rotate(-3deg)}}
    @keyframes split-right{from{opacity:0;transform:translateX(22px) rotate(8deg)}to{opacity:1;transform:translateX(0) rotate(3deg)}}
    .howto-slide[data-slide="2"].active .mp-word-shown{animation:word-reveal .5s .7s ease both}
    @keyframes word-reveal{0%{opacity:0;transform:scale(.7)}60%{opacity:1;transform:scale(1.08)}100%{opacity:1;transform:scale(1)}}
    .howto-slide[data-slide="2"].active .mp-word-hidden{animation:hide-pulse 1.4s .6s ease-out infinite}
    @keyframes hide-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.12)}}

    /* Slide 3 — race */
    .visual-race{display:flex;flex-direction:column;align-items:center;position:relative}
    .visual-race .mp{width:148px;height:278px}
    .howto-slide[data-slide="3"].active .visual-race .mp{animation:race-up .55s ease both}
    @keyframes race-up{from{opacity:0;transform:translateY(18px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}
    .mp-timer-ring{
      width:52px;height:52px;border-radius:50%;border:3px solid var(--text);
      display:flex;align-items:center;justify-content:center;
      font-size:14px;font-weight:700;font-feature-settings:"tnum";
    }
    .score-pop{
      position:absolute;top:30%;inset-inline-end:-2%;background:var(--success);color:#fff;
      font-weight:800;font-size:13px;padding:4px 10px;border-radius:var(--radius-pill);opacity:0;
    }
    .howto-slide[data-slide="3"].active .score-pop{animation:score-float 1.6s 1s ease both infinite}
    @keyframes score-float{
      0%{opacity:0;transform:translateY(10px)}
      15%{opacity:1;transform:translateY(0)}
      75%{opacity:1;transform:translateY(-30px)}
      100%{opacity:0;transform:translateY(-40px)}
    }
    .howto-slide[data-slide="3"].active .mp-btn-mini.got{animation:tap-glow 1.6s .8s ease infinite}
    @keyframes tap-glow{0%,100%{box-shadow:0 0 0 0 rgba(0,0,0,0)}50%{box-shadow:0 0 0 5px rgba(34,34,34,.18)}}

    /* Slide 4 — rotation */
    .visual-rotation{display:flex;flex-direction:column;gap:20px;align-items:center}
    .rotation-row{display:flex;align-items:center;gap:10px}
    .rotation-avatar{
      width:48px;height:48px;border-radius:50%;
      background:linear-gradient(135deg,#e4e4e4 0%,#cfcfcf 100%);
      display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px;
      color:var(--text);position:relative;flex-shrink:0;
    }
    .rotation-avatar.spotlight{box-shadow:0 0 0 3px var(--primary)}
    .rotation-avatar.spotlight::after{
      content:"🔥";position:absolute;top:-12px;inset-inline-end:-8px;font-size:16px;
    }
    .rotation-arrow{color:var(--text-tertiary);font-size:18px}
    .howto-slide[data-slide="4"].active .rotation-avatar{animation:avatar-in .4s ease both}
    .howto-slide[data-slide="4"].active .rotation-row > :nth-child(1){animation-delay:0s}
    .howto-slide[data-slide="4"].active .rotation-row > :nth-child(3){animation-delay:.12s}
    .howto-slide[data-slide="4"].active .rotation-row > :nth-child(5){animation-delay:.24s}
    .howto-slide[data-slide="4"].active .rotation-row > :nth-child(7){animation-delay:.36s}
    @keyframes avatar-in{from{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}
    .howto-slide[data-slide="4"].active .rotation-avatar.spotlight{
      animation:avatar-in .4s ease both,spotlight-cycle 2.2s 1s ease infinite;
    }
    @keyframes spotlight-cycle{
      0%,100%{box-shadow:0 0 0 3px var(--primary)}
      50%{box-shadow:0 0 0 6px var(--primary)}
    }
    .mini-leaderboard{
      width:220px;background:var(--bg);border:1px solid var(--border);
      border-radius:var(--radius-md);overflow:hidden;opacity:0;
    }
    .howto-slide[data-slide="4"].active .mini-leaderboard{animation:lb-in .55s 1s ease both}
    @keyframes lb-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
    .mini-lb-row{
      display:flex;align-items:center;justify-content:space-between;padding:8px 12px;
      font-size:13px;border-bottom:1px solid var(--border);
    }
    .mini-lb-row:last-child{border-bottom:none}
    .mini-lb-row.winner{background:#fff8e6;font-weight:700}
    .mini-lb-row .lb-left{display:flex;align-items:center;gap:8px}
    .mini-lb-row .lb-medal{font-size:14px}


    
    .role-tag.tag-truth{background:#e6f5e7;color:var(--success)}
    .role-tag.tag-bluff{background:#fde9e4;color:#c13515}
    [data-theme="dark"] .role-tag.tag-truth{background:var(--success-soft);color:var(--success)}
    [data-theme="dark"] .role-tag.tag-bluff{background:var(--danger-soft-2);color:var(--danger)}
    /* Mini playing cards */
    .mp-cards-row{display:flex;gap:3px;justify-content:center;width:100%;flex-wrap:nowrap}
    .mini-card{
      width:18px;height:26px;border-radius:3px;background:#fff;border:1px solid #1a1a1a;
      display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:800;
      color:#1a1a1a;font-family:Georgia,serif;flex-shrink:0;
    }
    .mini-card.red{color:#c13515}
    .mini-card.back{
      background:repeating-linear-gradient(45deg,#1a3a8a,#1a3a8a 3px,#2a4aac 3px,#2a4aac 6px);
      color:transparent;border-color:#0d2050;
    }
    .table-card-pill{
      display:inline-flex;flex-direction:column;align-items:center;gap:2px;
      padding:5px 14px;background:var(--primary);color:var(--on-primary);
      border-radius:var(--radius-pill);font-weight:800;font-size:13px;letter-spacing:.06em;
    }
    .table-card-pill .tcp-label{font-size:7px;font-weight:700;letter-spacing:.16em;opacity:.85}
    
    .visual-hand{display:flex;flex-direction:column;align-items:center;gap:12px}
    .howto-slide[data-slide="2"].active .visual-hand .table-card-pill{animation:code-pop .5s ease both}
    .howto-slide[data-slide="2"].active .visual-hand .mp{animation:race-up .55s .15s ease both;opacity:0;animation-fill-mode:both}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card{animation:card-deal .4s ease both;opacity:0}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card:nth-child(1){animation-delay:.7s}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card:nth-child(2){animation-delay:.82s}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card:nth-child(3){animation-delay:.94s}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card:nth-child(4){animation-delay:1.06s}
    .howto-slide[data-slide="2"].active .visual-hand .mini-card:nth-child(5){animation-delay:1.18s}
    @keyframes card-deal{from{opacity:0;transform:translateY(-12px) rotate(-12deg)}to{opacity:1;transform:translateY(0) rotate(0)}}
    
    .mp-opps-row{display:flex;justify-content:center;gap:5px;width:100%;margin-bottom:2px}
    .mp-opp{
      display:inline-flex;align-items:center;gap:2px;
      padding:2px;padding-inline:3px 5px;background:var(--bg);border:1px solid var(--border);
      border-radius:8px;font-size:7px;font-weight:700;color:var(--text);line-height:1;
    }
    .mp-opp-init{
      display:inline-flex;align-items:center;justify-content:center;
      width:11px;height:11px;border-radius:50%;background:var(--bg-subtle);
      font-size:6px;font-weight:800;color:var(--text);
    }
    .mp-opp-count{font-size:6.5px;color:var(--text-secondary);font-weight:700}
    .mp-opps-label{font-size:5.5px;color:var(--text-tertiary);text-align:center;
      letter-spacing:.04em;text-transform:uppercase;margin-bottom:2px}

    
    .mp-btn-mini.danger{background:var(--danger);color:#fff}
    .howto-slide[data-slide="3"].active .mp-btn-mini.danger{animation:tap-glow 1.6s .8s ease infinite}
    /* "Watching" phone: Maria's seat with face-down stack + verbal claim badge */
    .mp-played-row{
      display:flex;align-items:center;justify-content:space-between;gap:4px;
      width:100%;padding:4px;background:var(--bg);border:1px solid var(--border);
      border-radius:6px;margin-bottom:4px;
    }
    .mp-played-seat{display:flex;flex-direction:column;align-items:center;gap:2px}
    .mp-played-avatar{
      width:18px;height:18px;border-radius:50%;
      background:linear-gradient(135deg,#e4e4e4 0%,#cfcfcf 100%);
      display:flex;align-items:center;justify-content:center;
      font-size:9px;font-weight:800;color:#1a1a1a;
    }
    [data-theme="dark"] .mp-played-avatar{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%);color:var(--text)}
    .mp-played-name{font-size:6px;font-weight:700;color:var(--text);letter-spacing:.02em}
    .mp-played-badge{
      display:inline-flex;align-items:center;gap:3px;
      padding:3px;padding-inline:4px 6px;background:var(--bg-subtle);
      border:1.5px solid var(--text);border-radius:10px;
      font-size:7px;font-weight:700;color:var(--text);
    }
    .mp-played-badge strong{font-weight:800;font-size:8px}
    .mp-played-cards{position:relative;display:inline-flex;width:14px;height:11px}
    .mp-played-cards span{
      position:absolute;width:7px;height:10px;border-radius:1.5px;
      background:linear-gradient(135deg,#7c2d12 0%,#b91c1c 100%);
      border:.5px solid #9a3412;
    }
    .mp-played-cards span:nth-child(1){inset-inline-start:0;transform:rotate(-10deg)}
    .mp-played-cards span:nth-child(2){inset-inline-start:5px;transform:rotate(8deg)}
    .howto-slide[data-slide="3"].active .mp-played-badge{animation:tap-glow 1.6s 1.1s ease infinite}
    
    .visual-cup{display:flex;flex-direction:column;align-items:center;gap:16px}
    .cup-mock{
      width:74px;height:90px;
      background:linear-gradient(180deg,#8b5a3a 0%,#5a3520 100%);
      border-radius:6px 6px 28px 28px;position:relative;
      box-shadow:0 6px 14px rgba(0,0,0,.18);
    }
    .cup-mock::before{
      content:"";position:absolute;top:5px;left:5px;right:5px;height:14px;
      background:linear-gradient(180deg,#a06a44 0%,#7a4a2e 100%);border-radius:5px 5px 3px 3px;
    }
    .cup-chambers{
      display:grid;grid-template-columns:repeat(3,1fr);gap:7px;width:150px;
    }
    .cup-chamber{
      width:100%;aspect-ratio:1;border-radius:50%;background:var(--bg);
      border:2px solid var(--border-strong);display:flex;align-items:center;justify-content:center;
      font-size:14px;color:transparent;
    }
    .cup-chamber.spill{background:var(--danger);border-color:var(--danger);color:#fff}
    [data-theme="dark"] .cup-chamber{background:var(--surface)}
    .howto-slide[data-slide="4"].active .cup-mock{animation:cup-bob 2s ease-in-out infinite}
    @keyframes cup-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
    .howto-slide[data-slide="4"].active .cup-chamber{animation:avatar-in .35s ease both}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(1){animation-delay:.1s}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(2){animation-delay:.18s}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(3){animation-delay:.26s}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(4){animation-delay:.34s}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(5){animation-delay:.42s}
    .howto-slide[data-slide="4"].active .cup-chambers > :nth-child(6){animation-delay:.5s}
    .howto-slide[data-slide="4"].active .cup-chamber.spill{
      animation:avatar-in .35s ease both,spill-flash 1.6s 1s ease infinite;
    }
    @keyframes spill-flash{0%,100%{box-shadow:0 0 0 0 rgba(193,53,21,0)}50%{box-shadow:0 0 0 6px rgba(193,53,21,.28)}}

    /* ===== Room QR code ===== */
    .room-qr-wrap{
      background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);padding:10px;
      display:inline-block;margin:12px auto 0;
    }
    .room-qr{width:120px;height:120px;display:block;background:#f0f0f0;border-radius:4px}
    /* Loading state: while openX hasn't set the real QR src yet, the img
       defaults to a transparent SVG data URI in the HTML (so the browser
       never renders a broken-image icon). The CSS background:#f0f0f0 above
       fills the 120×120 area with a subtle pulsing gray so the user sees a
       clear "loading" indicator instead of an empty broken slot. */
    .room-qr[data-loading="1"]{
      animation:qr-skeleton-pulse 1.4s ease-in-out infinite;
    }
    @keyframes qr-skeleton-pulse{
      0%,100%{background:#f0f0f0}
      50%{background:#e4e4e4}
    }
    @media(prefers-reduced-motion:reduce){
      .room-qr[data-loading="1"]{animation:none}
    }
    /* Fallback shown when the QR image fails to load (offline / external service down).
       Sits in the same 120×120 slot so layout doesn't jump. */
    .room-qr-fallback{
      width:120px;height:120px;display:none;flex-direction:column;align-items:center;justify-content:center;
      gap:6px;padding:10px;box-sizing:border-box;background:#f0f0f0;border-radius:4px;
      color:#555;font-size:11px;line-height:1.35;text-align:center;font-weight:600;
      white-space:pre-line; /* Honor the \n in the i18n fallback string so it breaks cleanly between sentences. */
    }
    .room-qr-fallback.show{display:flex}
    .room-qr-fallback svg{width:24px;height:24px;color:#888}
    .room-qr-caption{
      font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-secondary);margin-top:8px;
    }

    /* ============================================================
       Dark theme — overrides for hardcoded colors in the styles above.
       Pure-additive: light theme behaviour is unchanged.
       ============================================================ */
    [data-theme="dark"] .btn-primary{color:var(--on-primary)}
    [data-theme="dark"] .btn-accent{color:var(--on-accent)}
    [data-theme="dark"] .btn-outline{background:var(--surface)}
    [data-theme="dark"] .chip.active{color:var(--on-accent)}
    [data-theme="dark"] .avatar{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    [data-theme="dark"] .sticky-bottom{background:linear-gradient(180deg,rgba(14,14,16,0) 0%,var(--bg) 24px)}
    [data-theme="dark"] .lb-row.winner{background:var(--winner-bg)}
    [data-theme="dark"] .lb-row.winner .lb-rank{color:var(--winner-text)}
    [data-theme="dark"] .mini-lb-row.winner{background:var(--winner-bg)}
    [data-theme="dark"] .sheet-backdrop{background:var(--scrim)}
    [data-theme="dark"] .rotation-avatar{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    /* QR — keep the wrapper white in dark mode too so the standard
       black-on-white QR stays scannable. */
    [data-theme="dark"] .room-qr-wrap{background:#fff}
    [data-theme="dark"] .room-qr{background:#fff}
    /* Mini-phone mockups in How-to-play modal — give them visible frames
       and a light inner screen so the illustration reads at a glance. */
    [data-theme="dark"] .mp{
      background:#f5f5f5;border-color:#3a3a3e;
      box-shadow:0 14px 28px rgba(0,0,0,.55),0 4px 8px rgba(0,0,0,.3);
    }
    [data-theme="dark"] .mp::before{background:#3a3a3e}
    [data-theme="dark"] .mp-screen{background:#f5f5f5;color:#222}
    [data-theme="dark"] .mp-statusbar{color:#222}
    [data-theme="dark"] .mp-statusbar.with-bar{border-bottom-color:#e5e5e5}
    [data-theme="dark"] .mp-word-card-mini{background:#fff;border-color:#e5e5e5}
    [data-theme="dark"] .mp-word-label-mini{color:#717171}
    [data-theme="dark"] .mp-word-shown{color:#222}
    [data-theme="dark"] .mp-hint-mini{color:#9c9c9c}
    [data-theme="dark"] .mp-btn-mini.skip{background:#fff;color:#222;border-color:#ddd}
    [data-theme="dark"] .mp-btn-mini.got{background:#222;color:#fff}
    [data-theme="dark"] .mp-mini-avatar{color:#222}
    [data-theme="dark"] .mp-timer-ring{border-color:#222;color:#222}
    /* ===== Avatar component (player identity) =====
       Renders at any size 24–96px. Uses inline CSS vars for size and color so
       the same component scales cleanly. Pattern styles are layered as
       background-image overlays. Symbol is an emoji; falls back to initial. */
    .av{
      --size:44px;
      width:var(--size);height:var(--size);border-radius:50%;
      display:inline-flex;align-items:center;justify-content:center;
      flex-shrink:0;position:relative;overflow:hidden;
      background:var(--av-bg, var(--bg-subtle));color:#fff;
      font-family:"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol",-apple-system,sans-serif;
      font-weight:700;letter-spacing:0;
      line-height:1;user-select:none;
    }
    /* Symbol container fills the avatar exactly so glyph-width variance
       between emoji never shifts the centering. Flex + text-align both
       enforce centering on the rendered character. Any residual offset is
       purely from the emoji font's internal glyph metrics (e.g. grape
       cluster sitting lower than leaf within its glyph box), not the box. */
    .av-symbol, .av-initial{
      position:absolute;inset:0;
      display:flex;align-items:center;justify-content:center;
      line-height:1;text-align:center;
      z-index:1;
    }
    .av-symbol{font-size:calc(var(--size) * 0.55)}
    .av-initial{font-size:calc(var(--size) * 0.42);font-weight:700;color:#fff}
    /* Twemoji replaces emoji text with <img class="emoji">. Reset its default
       inline styles (margin / vertical-align) and size it explicitly. */
    img.emoji{margin:0;vertical-align:middle;display:inline-block;height:1em;width:1em}
    .av-symbol img.emoji{
      width:calc(var(--size) * 0.62);
      height:calc(var(--size) * 0.62);
      display:block;
    }
    /* Bigger emoji in the symbol picker so every glyph fills its cell
       substantially — minor visual offsets in some emoji (which exist on
       every emoji vendor, not just Twemoji) become proportionally invisible. */
    .ep-symbol-cell img.emoji{width:40px;height:40px;display:block;margin:auto}

    /* Per-emoji visual-centering corrections. Some emoji are drawn at an
       angle or with the ink biased to one side as a universal emoji-art
       convention (🚀 rocket angled, 🎸 guitar angled, 🌈 rainbow as a
       bottom-arched arc, etc.). The IMG element is centered correctly; these
       transforms re-center the *drawing* within the IMG so the visual mass
       sits at the geometric center of the avatar / picker cell. */
    img.emoji[alt="🚀"]{transform:translate(3%,-3%)}
    img.emoji[alt="🎸"]{transform:translate(4%,-4%)}
    img.emoji[alt="🌈"]{transform:translateY(-5%)}
    img.emoji[alt="🍇"]{transform:translateY(-4%)}
    img.emoji[alt="🍦"]{transform:translateY(-3%)}
    img.emoji[alt="🐢"]{transform:translateY(-3%)}
    img.emoji[alt="🦄"]{transform:translateY(2%)}
    img.emoji[alt="🐙"]{transform:translateY(-2%)}
    img.emoji[alt="🥑"]{transform:translate(2%,0)}
    img.emoji[alt="🌮"]{transform:translateY(-2%)}
    img.emoji[alt="🎯"]{transform:translate(-2%,2%)}
    img.emoji[alt="🎬"]{transform:translateY(-2%)}
    .av[data-style="gradient"]{
      background:linear-gradient(135deg,
        color-mix(in srgb, var(--av-bg) 70%, white) 0%,
        var(--av-bg) 100%);
    }
    .av[data-style="dots"]{
      background-color:var(--av-bg);
      background-image:radial-gradient(rgba(255,255,255,.32) calc(var(--size) * .018), transparent calc(var(--size) * .028));
      background-size:calc(var(--size) * .12) calc(var(--size) * .12);
    }
    .av[data-style="stripes"]{
      background-color:var(--av-bg);
      background-image:repeating-linear-gradient(45deg,
        rgba(255,255,255,.22) 0 calc(var(--size) * .04),
        transparent calc(var(--size) * .04) calc(var(--size) * .1));
    }
    .av[data-style="glow"]{
      background:var(--av-bg);
      box-shadow:inset 0 0 0 calc(var(--size) * .04) rgba(255,255,255,.38);
    }
    /* Soft — single light-source highlight in upper-left (glossy bubble) */
    .av[data-style="soft"]{
      background-color:var(--av-bg);
      background-image:radial-gradient(circle at 30% 28%, rgba(255,255,255,.36) 0%, transparent 55%);
    }
    /* Half — top lighter, bottom slightly darker. Soft middle so the
       symbol doesn't sit on a hard line. */
    .av[data-style="half"]{
      background-color:var(--av-bg);
      background-image:linear-gradient(180deg,
        rgba(255,255,255,.22) 0%,
        rgba(255,255,255,0)   45%,
        rgba(0,0,0,0)         55%,
        rgba(0,0,0,.18)       100%);
    }
    /* Ring — thin concentric ring inset from the edge (layered medal feel) */
    .av[data-style="ring"]{
      background:var(--av-bg);
    }
    .av[data-style="ring"]::before{
      content:"";position:absolute;
      inset:calc(var(--size) * .12);
      border-radius:50%;
      border:calc(var(--size) * .025) solid rgba(255,255,255,.46);
      pointer-events:none;
    }
    /* Pulse — subtle heartbeat scale (transform-only = GPU-friendly) */
    .av[data-style="pulse"]{
      background:var(--av-bg);
      animation:av-pulse 2.4s ease-in-out infinite;
    }
    @keyframes av-pulse{
      0%, 100% { transform:scale(1) }
      50%      { transform:scale(1.04) }
    }
    /* Shimmer — diagonal light sweep over the surface */
    .av[data-style="shimmer"]{
      background:var(--av-bg);
    }
    .av[data-style="shimmer"]::before{
      content:"";position:absolute;inset:0;
      background:linear-gradient(115deg,
        transparent 30%,
        rgba(255,255,255,.42) 50%,
        transparent 70%);
      transform:translateX(-110%);
      animation:av-shimmer 4s ease-in-out infinite;
      pointer-events:none;
    }
    @keyframes av-shimmer{
      0%, 35%   { transform:translateX(-110%) }
      65%, 100% { transform:translateX(110%) }
    }
    /* Halo — outer glow breathing in the avatar's own colour */
    .av[data-style="halo"]{
      background:var(--av-bg);
      animation:av-halo 2.8s ease-in-out infinite;
    }
    @keyframes av-halo{
      0%, 100% { box-shadow:0 0 0 0 transparent }
      50%      { box-shadow:0 0 0 calc(var(--size) * .07) color-mix(in srgb, var(--av-bg) 55%, transparent) }
    }
    /* Float — gentle vertical bobbing */
    .av[data-style="float"]{
      background:var(--av-bg);
      animation:av-float 2.6s ease-in-out infinite;
    }
    @keyframes av-float{
      0%, 100% { transform:translateY(0) }
      50%      { transform:translateY(calc(var(--size) * -.05)) }
    }
    /* Ripple — expanding inner ring fading outward (sonar) */
    .av[data-style="ripple"]{
      background:var(--av-bg);
    }
    .av[data-style="ripple"]::before{
      content:"";position:absolute;
      top:50%;left:50%;
      width:calc(var(--size) * .3);height:calc(var(--size) * .3);
      /* Physical margin-left ON PURPOSE: this is the left:50% + negative-margin
         centring pair. As margin-inline-start it becomes margin-right in RTL,
         which has no effect next to left:50%/right:auto and knocks the ring
         off-centre. Centring is direction-neutral, so keep it physical. */
      margin-left:calc(var(--size) * -.15);margin-top:calc(var(--size) * -.15);
      border-radius:50%;
      border:calc(var(--size) * .025) solid rgba(255,255,255,.55);
      animation:av-ripple 2.4s ease-out infinite;
      pointer-events:none;
    }
    @keyframes av-ripple{
      0%   { transform:scale(.5); opacity:.75 }
      100% { transform:scale(2.6); opacity:0 }
    }
    /* Accessibility — respect OS "Reduce motion" preference. Each animated
       style falls back to a calm static state, never an empty/broken avatar. */
    @media (prefers-reduced-motion: reduce){
      .av[data-style="pulse"]{ animation:none }
      .av[data-style="shimmer"]::before{ animation:none; transform:translateX(0); opacity:.5 }
      .av[data-style="halo"]{ animation:none; box-shadow:0 0 0 calc(var(--size) * .035) color-mix(in srgb, var(--av-bg) 35%, transparent) }
      .av[data-style="float"]{ animation:none }
      .av[data-style="ripple"]::before{ animation:none; transform:scale(1.2); opacity:.4 }
    }
    /* Presence dot — Discord / Instagram / Slack pattern.
       The dot lives on a sibling wrapper (.av-shell), NOT inside .av, because .av
       has overflow:hidden to clip pattern backgrounds to its circle — putting the
       dot inside meant the outer half was being chopped off at the avatar's edge.
       Sibling positioning lets the dot poke cleanly past the corner. The thick
       bg-coloured ring "carves" a notch out of the avatar so the dot reads as a
       deliberate add-on, not an overlap. */
    .av-shell{
      position:relative;
      display:inline-flex;
      width:var(--size);height:var(--size);
      flex-shrink:0;
    }
    .av-shell > .av{width:100%;height:100%}
    .av-presence{
      position:absolute;
      inset-inline-end:calc(var(--size) * -0.02);
      bottom:calc(var(--size) * -0.02);
      width:calc(var(--size) * .32);
      height:calc(var(--size) * .32);
      background:#22c55e;
      border:calc(var(--size) * .085) solid var(--bg);
      border-radius:50%;
      box-shadow:
        0 0 0 1px rgba(0,0,0,.05),
        0 calc(var(--size) * .015) calc(var(--size) * .08) rgba(34,197,94,.35);
      pointer-events:none;
    }
    [data-theme="dark"] .av-presence{
      background:#2ecc71;
      box-shadow:
        0 0 0 1px rgba(0,0,0,.4),
        0 calc(var(--size) * .015) calc(var(--size) * .1) rgba(46,204,113,.45);
    }

    /* ===== Edit Profile screen ===== */
    .edit-profile-page{
      padding:16px 16px 0;
      display:flex;flex-direction:column;
    }
    .edit-profile-preview{
      display:flex;flex-direction:column;align-items:center;gap:12px;
      padding:16px 0 22px;
    }
    .edit-profile-preview .ep-hint{
      font-size:13px;color:var(--text-secondary);
    }
    /* "Surprise me" — labeled pill button that randomises the avatar combo.
       Replaces the unrecognisable shuffle icon that used to be in the header. */
    .ep-shuffle-btn{
      display:inline-flex;align-items:center;gap:8px;
      padding:10px 18px;border-radius:var(--radius-pill);
      border:1px solid var(--border-strong);
      background:var(--surface);color:var(--text);
      font:inherit;font-size:14px;font-weight:600;
      cursor:pointer;transition:all .15s ease;
      margin-top:-2px;
    }
    .ep-shuffle-btn:hover{
      border-color:var(--text);background:var(--bg-subtle);
    }
    .ep-shuffle-btn:active{transform:scale(.97)}
    .ep-shuffle-btn svg{width:16px;height:16px;flex-shrink:0;color:var(--text-secondary)}
    .ep-shuffle-btn:hover svg{color:var(--text)}
    .edit-profile-fields{margin-bottom:8px}
    .edit-profile-tabs{
      display:flex;gap:6px;border-bottom:1px solid var(--border);margin:18px 0 14px;
    }
    .edit-profile-tabs .tab{padding:12px 4px;margin-inline-end:18px}
    .ep-grid{
      display:grid;grid-template-columns:repeat(4,1fr);gap:10px;
    }
    .ep-grid-5{grid-template-columns:repeat(5,1fr)}
    .ep-cell{
      aspect-ratio:1;
      display:flex;align-items:center;justify-content:center;
      border:1.5px solid var(--border);border-radius:var(--radius-md);
      background:var(--surface);cursor:pointer;
      font:inherit;color:inherit;padding:0;
      transition:border-color .15s ease, transform .15s ease;
    }
    .ep-cell:hover{border-color:var(--text-secondary)}
    .ep-cell.active{
      border-color:var(--text);border-width:2px;
      transform:scale(0.96);
    }
    .ep-cell .av{--size:44px}
    .ep-symbol-cell{font-size:36px;line-height:1}
    .ep-style-cell{flex-direction:column;gap:6px;padding:8px 6px}
    .ep-style-cell .av{--size:36px}
    .ep-style-cell-label{font-size:11px;color:var(--text-secondary);font-weight:500;text-align:center}
    .ep-section-label{
      font-size:12px;font-weight:600;text-transform:uppercase;
      letter-spacing:.08em;color:var(--text-secondary);
      margin:0 0 10px;
    }
    .ep-symbol-tabs{
      display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;margin-bottom:14px;
    }
    .ep-symbol-tabs::-webkit-scrollbar{display:none}
    .ep-symbol-tabs .chip{flex:0 0 auto}
    .ep-save-bar{
      position:sticky;bottom:0;margin-top:auto;
      padding:24px 0 calc(env(safe-area-inset-bottom,0px) + 16px);
      background:linear-gradient(180deg, transparent 0%, var(--bg) 24px, var(--bg) 100%);
      z-index:5;
    }

    /* Theme menu — chips for the picker sheet */
    .theme-options{display:flex;flex-direction:column;gap:8px;margin-top:4px}
    .theme-option{
      display:flex;align-items:center;gap:12px;width:100%;text-align:start;
      padding:14px 16px;border:1px solid var(--border);border-radius:var(--radius-md);
      background:var(--surface);color:var(--text);font:inherit;cursor:pointer;
      transition:border-color .15s ease, background .15s ease;
    }
    .theme-option:hover{border-color:var(--text)}
    .theme-option.active{border-color:var(--accent);background:var(--bg-subtle)}
    .theme-option-icon{
      width:36px;height:36px;border-radius:var(--radius-pill);
      display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
      background:var(--bg-subtle);color:var(--text);
    }
    .theme-option-text{flex:1;min-width:0}
    .theme-option-title{font-weight:600;font-size:15px;line-height:1.2}
    .theme-option-sub{font-size:12.5px;color:var(--text-secondary);margin-top:2px}
    .theme-option-check{color:var(--text);opacity:0}
    .theme-option.active .theme-option-check{opacity:1;color:var(--accent)}

    
    .test-reveal-card{
      display:flex;align-items:center;gap:14px;padding:14px;
      background:var(--surface-elevated);border:1px solid var(--border);
      border-radius:var(--radius-lg);cursor:pointer;text-align:start;
      transition:border-color .15s ease, background .15s ease;width:100%;font:inherit;
    }
    .test-reveal-card:hover{border-color:var(--text)}
    .test-reveal-thumb{
      width:48px;height:48px;border-radius:12px;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;font-size:24px;
    }
    .test-reveal-thumb.verdict{background:linear-gradient(135deg,#6b4818,#fbbf24);color:#3a2410}
    .test-reveal-title{font-size:15px;font-weight:700;color:var(--text);line-height:1.2}
    .test-reveal-sub  {font-size:12.5px;color:var(--text-secondary);margin-top:3px;line-height:1.3}

    /* ===== Mafia — How To Play video player (mh-*) ======================
       Fullscreen, animation-driven walkthrough with synced ElevenLabs
       voiceover. 6 scenes + an end card. Audio drives the timeline:
       JS adds .is-active to the matching .mh-scene based on currentTime,
       which triggers the scene's CSS keyframe animations. */
    #screen-mafia-howto{background:#0a0a0d}
    .mh-player{
      position:fixed;inset:0;display:flex;flex-direction:column;
      background:radial-gradient(120% 80% at 50% 0%, #1a1a22 0%, #0a0a0d 60%);
      color:#fff;overflow:hidden;
    }
    .mh-close{
      position:absolute;top:calc(env(safe-area-inset-top,0) + 14px);inset-inline-end:16px;
      width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.08);
      color:#fff;border:none;cursor:pointer;z-index:10;
      display:flex;align-items:center;justify-content:center;
      transition:background .15s ease;-webkit-tap-highlight-color:transparent;
    }
    .mh-close:hover{background:rgba(255,255,255,.16)}

    .mh-stage{
      flex:1;position:relative;overflow:hidden;
      display:flex;align-items:center;justify-content:center;
      padding-top:calc(env(safe-area-inset-top,0) + 20px);
    }
    .mh-scene{
      position:absolute;inset:0;
      display:flex;flex-direction:column;align-items:center;justify-content:center;
      gap:36px;padding:20px;
      opacity:0;visibility:hidden;
      transition:opacity .5s ease;
    }
    .mh-scene.is-active{opacity:1;visibility:visible}
    .mh-scene-visual{
      flex:1;display:flex;align-items:center;justify-content:center;
      max-width:480px;width:100%;position:relative;
    }
    .mh-caption{text-align:center;max-width:360px}
    .mh-caption-eyebrow{
      font-size:11px;font-weight:800;letter-spacing:.22em;
      color:#fbbf24;text-transform:uppercase;margin-bottom:8px;
      opacity:0;transform:translateY(8px);
      transition:opacity .5s ease .3s, transform .5s ease .3s;
    }
    .mh-caption-line{
      font-size:22px;font-weight:700;letter-spacing:-.01em;line-height:1.3;
      color:#fff;
      opacity:0;transform:translateY(8px);
      transition:opacity .5s ease .5s, transform .5s ease .5s;
    }
    .mh-scene.is-active .mh-caption-eyebrow,
    .mh-scene.is-active .mh-caption-line{opacity:1;transform:none}

    /* ===== How-to tableau v2 (2026-07-07 storyboard rebuild) =====
       One persistent "game table" across all 8 scenes: same six seats, same
       ring colors, gold narrator post. Conventions (never violated):
       dead = grayscale + 15deg tilt + red X that stays; night = navy sky +
       dimmed seats + eyelids; red glow = Mafia; shield = Doctor; gold = narrator.
       All animation is CSS, gated on .mh-scene.is-active so scenes replay
       cleanly on scrub/replay. Stage is 335x430 inside the player. */
    .mht{flex:none;width:335px;max-width:100%;height:430px;position:relative;margin:0 auto}
    .mht::after{content:"";position:absolute;inset:-12px;border-radius:24px;pointer-events:none;z-index:9;
      background:radial-gradient(ellipse at center, transparent 58%, rgba(0,0,0,.5) 100%)}
    .mht-sky{position:absolute;left:0;right:0;top:0;height:96px;border-radius:14px;overflow:hidden;
      background-color:rgba(251,191,36,.10)}
    .mht-orb{position:absolute;right:18px;top:12px;font-size:26px;line-height:1}
    .mht-star{position:absolute;top:34%;left:var(--stx);width:2px;height:2px;border-radius:50%;background:#fff;opacity:0}
    .mht-table{position:absolute;left:50%;top:235px;transform:translate(-50%,-50%);
      width:250px;height:168px;border-radius:50%;
      background:radial-gradient(ellipse at 50% 38%, #24242e, #15151b 78%);
      border:1px solid rgba(255,255,255,.07);
      box-shadow:inset 0 10px 26px rgba(0,0,0,.5)}
    .mht-seat{position:absolute;left:var(--x);top:var(--y);transform:translate(-50%,-50%);
      width:46px;height:46px;border-radius:50%;background:#1d1d24;border:3px solid var(--ring);
      display:flex;align-items:center;justify-content:center;z-index:2}
    .mht-face{font-size:23px;line-height:1}
    .mht-seat--p1{--x:224px;--y:157px;--ring:#ef4444}
    .mht-seat--p2{--x:282px;--y:235px;--ring:#3b82f6}
    .mht-seat--p3{--x:224px;--y:313px;--ring:#22c55e}
    .mht-seat--p4{--x:110px;--y:313px;--ring:#06b6d4}
    .mht-seat--p5{--x:52px;--y:235px;--ring:#a855f7}
    .mht-seat--p6{--x:110px;--y:157px;--ring:#f97316}
    .mht-npost{position:absolute;left:167px;top:60px;transform:translate(-50%,-50%);
      width:46px;height:46px;border-radius:50%;background:#1d1d24;border:3px solid #fbbf24;
      display:flex;align-items:center;justify-content:center;z-index:3;
      box-shadow:0 0 14px rgba(251,191,36,.35)}
    .mht-seat--dead{filter:grayscale(1) brightness(.6);transform:translate(-50%,-50%) rotate(15deg)}
    .mht-seat--dead .mht-x{opacity:1}
    .mht-x{position:absolute;right:-5px;top:-7px;font-size:13px;font-style:normal;font-weight:800;color:#ef4444;opacity:0;
      text-shadow:0 0 6px rgba(0,0,0,.8)}
    .mht-lid{position:absolute;inset:3px;border-radius:50%;background:#14141a;transform:scaleY(0);transform-origin:center top}
    .mht-alt{position:absolute;inset:0;border-radius:50%;background:#1d1d24;display:flex;align-items:center;justify-content:center;
      font-size:23px;opacity:0;filter:drop-shadow(0 0 10px rgba(239,68,68,.8))}
    .mht-chip{position:absolute;font-size:15px;line-height:1;opacity:0;z-index:4}
    .mht-badge{position:absolute;left:50%;top:-22px;transform:translateX(-50%);font-size:17px;opacity:0;z-index:5}
    @keyframes mhtPopIn{0%{opacity:0;transform:scale(.4)}100%{opacity:1;transform:scale(1)}}
    @keyframes mhtFadeIn{to{opacity:1}}
    @keyframes mhtDeath{to{filter:grayscale(1) brightness(.6);transform:translate(-50%,-50%) rotate(15deg)}}
    @keyframes mhtTwinkle{0%,100%{opacity:0}50%{opacity:1}}
    @keyframes mhtMaskFlick{0%,100%{opacity:0}25%,75%{opacity:1}}

    /* ---------- Scene 1: the hook ---------- */
    .mht--s1 .mht-seat{opacity:0;transform:translate(-50%,-50%) scale(.5)}
    .mh-scene.is-active .mht--s1{animation:mht1Push 1.6s ease-out both}
    @keyframes mht1Push{from{transform:scale(1.06)}to{transform:scale(1)}}
    .mh-scene.is-active .mht--s1 .mht-seat{animation:mht1Pop .5s cubic-bezier(.34,1.56,.64,1) var(--d,.2s) both, mht1Sway 2.4s ease-in-out 4.8s 2}
    @keyframes mht1Pop{to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
    @keyframes mht1Sway{0%,100%{transform:translate(-50%,-50%) rotate(0)}25%{transform:translate(-50%,-50%) rotate(6deg)}75%{transform:translate(-50%,-50%) rotate(-6deg)}}
    .mht--s1 .mht-seat--p1{--d:.20s}.mht--s1 .mht-seat--p2{--d:.35s}.mht--s1 .mht-seat--p3{--d:.50s}
    .mht--s1 .mht-seat--p4{--d:.65s}.mht--s1 .mht-seat--p5{--d:.80s}.mht--s1 .mht-seat--p6{--d:.95s}
    .mht-spot{position:absolute;left:224px;top:157px;width:74px;height:74px;border-radius:50%;z-index:1;opacity:0;
      transform:translate(-50%,-50%);filter:blur(2px);
      background:radial-gradient(circle, rgba(239,68,68,.5), transparent 70%)}
    /* the spotlight prowls exactly through "secretly Mafia... before it's too late" */
    .mh-scene.is-active .mht--s1 .mht-spot{animation:mht1Hop 4.2s 1s both}
    @keyframes mht1Hop{
      0%{opacity:0;left:224px;top:157px}5%,15%{opacity:1;left:224px;top:157px}
      20%,32%{left:282px;top:235px}37%,49%{left:224px;top:313px}54%,66%{left:110px;top:313px}
      71%,83%{left:52px;top:235px}88%,96%{opacity:1;left:110px;top:157px}100%{opacity:0;left:110px;top:157px}}
    .mht-bigq{position:absolute;left:167px;top:225px;transform:translate(-50%,-50%);font-size:44px;opacity:0;z-index:4;
      filter:drop-shadow(0 0 14px rgba(239,68,68,.6))}
    .mh-scene.is-active .mht--s1 .mht-bigq{animation:mht1BigQ 3.2s 2.6s both}
    @keyframes mht1BigQ{
      0%{opacity:0;transform:translate(-50%,-50%) scale(.4)}
      8%{opacity:1;transform:translate(-50%,-50%) scale(1)}
      30%{transform:translate(-50%,-50%) scale(1.12)}50%{transform:translate(-50%,-50%) scale(1)}
      70%{transform:translate(-50%,-50%) scale(1.12)}90%{opacity:1;transform:translate(-50%,-50%) scale(1)}
      100%{opacity:0;transform:translate(-50%,-50%) scale(.8)}}
    .mh-scene.is-active .mht--s1 .mht-seat--p1 .mht-alt{animation:mhtMaskFlick 1s 7.2s both}
    /* "five to twenty players": ghost seats bloom around the ring — the table
       visibly grows, then the extras fade and the count pill lands */
    .mht-ghost{position:absolute;left:var(--gx);top:var(--gy);width:32px;height:32px;border-radius:50%;
      transform:translate(-50%,-50%) scale(.6);opacity:0;z-index:1;
      border:2px dashed rgba(255,255,255,.35)}
    .mht-ghost--1{--gx:167px;--gy:117px}.mht-ghost--2{--gx:297px;--gy:176px}
    .mht-ghost--3{--gx:297px;--gy:294px}.mht-ghost--4{--gx:167px;--gy:353px}
    .mht-ghost--5{--gx:37px;--gy:294px}.mht-ghost--6{--gx:37px;--gy:176px}
    .mh-scene.is-active .mht--s1 .mht-ghost{animation:mht1Ghost 2.4s calc(var(--gd,8.7s) + var(--gshift,0s)) both}
    .mht--s1 .mht-ghost--1{--gd:8.7s}.mht--s1 .mht-ghost--2{--gd:8.88s}.mht--s1 .mht-ghost--3{--gd:9.06s}
    .mht--s1 .mht-ghost--4{--gd:9.24s}.mht--s1 .mht-ghost--5{--gd:9.42s}.mht--s1 .mht-ghost--6{--gd:9.6s}
    @keyframes mht1Ghost{0%{opacity:0;transform:translate(-50%,-50%) scale(.6)}
      14%{opacity:.9;transform:translate(-50%,-50%) scale(1.05)}22%{transform:translate(-50%,-50%) scale(1)}
      72%{opacity:.9}100%{opacity:0;transform:translate(-50%,-50%) scale(.7)}}
    .mht-pill{position:absolute;left:50%;top:398px;transform:translate(-50%,0) scale(.4);opacity:0;
      padding:8px 16px;border-radius:999px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.2);
      font-size:15px;font-weight:800;color:#fff;letter-spacing:.04em;z-index:5}
    .mh-scene.is-active .mht--s1 .mht-pill--count{animation:mht1Pill .5s cubic-bezier(.34,1.56,.64,1) var(--s1pill,9s) both}
    @keyframes mht1Pill{to{opacity:1;transform:translate(-50%,0) scale(1)}}
    .mht--s1 .mht-npost{opacity:0;transform:translate(-50%,-50%) translateY(-36px)}
    /* "plus one narrator" EN 10.6s / TR 11.6s; "doesn't play" EN 12.1s / TR 13s */
    .mh-scene.is-active .mht--s1 .mht-npost{animation:mht1NDrop .6s cubic-bezier(.34,1.56,.64,1) var(--s1n,10.6s) both}
    @keyframes mht1NDrop{to{opacity:1;transform:translate(-50%,-50%) translateY(0)}}
    .mht-nchip{position:absolute;right:-10px;top:-8px;font-size:15px;opacity:0}
    .mh-scene.is-active .mht--s1 .mht-nchip{animation:mhtPopIn .4s var(--s1nc,12.1s) both}

    /* Scene 1 punch-up: red threat glow on P1 while the mask flashes.
       Beat times are word-accurate ("a game of lying" EN 6.6s / TR 7.1s);
       the TR values live in the [data-mh-lang="tr"] var block below. */
    .mh-scene.is-active .mht--s1 .mht-seat--p1{
      animation:mht1Pop .5s cubic-bezier(.34,1.56,.64,1) var(--d,.2s) both, mht1Sway 2.4s ease-in-out 4.8s 2, mht1Sus 1.6s var(--s1mask,6.6s) both}
    @keyframes mht1Sus{0%,100%{box-shadow:0 0 0 rgba(239,68,68,0)}30%,70%{box-shadow:0 0 22px rgba(239,68,68,.85)}}
    .mh-scene.is-active .mht--s1 .mht-seat--p1 .mht-alt{animation:mhtMaskFlick 1.6s var(--s1mask,6.6s) both}

    /* ---------- Scene 2: our real lobby in a phone frame ---------- */
    .mht-phoneframe{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) translateY(24px) scale(.92);opacity:0;
      width:210px;height:360px;border-radius:28px;background:#0e0e12;
      border:3px solid #2c2c36;box-shadow:0 18px 44px rgba(0,0,0,.6);padding:16px 14px;z-index:2}
    .mh-scene.is-active .mht--s2 .mht-phoneframe{animation:mht2Frame .7s .2s cubic-bezier(.3,1.2,.5,1) both}
    @keyframes mht2Frame{to{opacity:1;transform:translate(-50%,-50%) translateY(0) scale(1)}}
    .mht-app{display:flex;flex-direction:column;gap:14px;height:100%}
    .mht-app-title{text-align:center;font-size:15px;font-weight:800;color:#fff;letter-spacing:-.01em}
    .mht-app-coderow{display:flex;gap:8px;align-items:stretch}
    .mht-app-code{flex:1;display:flex;align-items:center;justify-content:center;
      font-size:16px;font-weight:800;letter-spacing:.18em;color:#fff;
      border:1.5px dashed rgba(255,255,255,.3);border-radius:10px;padding:8px 0}
    .mht-app-qrbtn{display:flex;align-items:center;justify-content:center;width:38px;border-radius:10px;
      background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);color:#fff}
    .mh-scene.is-active .mht--s2 .mht-app-qrbtn{animation:mht2QrPulse 1.4s 1.4s ease-in-out 2}
    @keyframes mht2QrPulse{0%,100%{box-shadow:0 0 0 rgba(251,146,60,0);color:#fff}50%{box-shadow:0 0 16px rgba(251,146,60,.7);color:#fb923c}}
    .mht-app-seats{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;justify-items:center;padding-top:4px}
    .mht-app-chip{position:relative;width:34px;height:34px;border-radius:50%;background:#1d1d24;
      border:2.5px solid var(--ring);display:flex;align-items:center;justify-content:center;
      font-size:16px;line-height:1;opacity:0;transform:scale(.4)}
    .mh-scene.is-active .mht--s2 .mht-app-chip{animation:mht2Chip .45s var(--cd,.6s) cubic-bezier(.34,1.56,.64,1) both}
    @keyframes mht2Chip{to{opacity:1;transform:scale(1)}}
    .mht--s2 .mht-app-chip--1{--cd:.6s}.mht--s2 .mht-app-chip--2{--cd:2.4s}
    .mht--s2 .mht-app-chip--3{--cd:3.0s}.mht--s2 .mht-app-chip--4{--cd:3.6s}
    .mht--s2 .mht-app-chip--5{--cd:4.2s}.mht--s2 .mht-app-chip--6{--cd:4.8s}
    .mht--s2 .mht-app-chip--7{--cd:5.4s}
    .mht-app-star{position:absolute;right:-9px;top:-9px;font-size:12px;font-style:normal}
    /* the 7th chip is made NARRATOR at ~7s: ring turns gold + glow (host picks) */
    .mh-scene.is-active .mht--s2 .mht-app-chip--narr{
      animation:mht2Chip .45s var(--cd,5.4s) cubic-bezier(.34,1.56,.64,1) both, mht2Gold 1.2s var(--s2gold,7.2s) both}
    @keyframes mht2Gold{
      0%{border-color:#6d6d75;box-shadow:0 0 0 rgba(251,191,36,0)}
      45%{border-color:#fbbf24;box-shadow:0 0 20px rgba(251,191,36,.9)}
      100%{border-color:#fbbf24;box-shadow:0 0 10px rgba(251,191,36,.4)}}
    .mht-app-start{margin-top:auto;display:flex;align-items:center;justify-content:center;
      height:40px;border-radius:12px;background:#232329;color:#77777e}
    /* Start goes live once the narrator is set — gray to accent, then a proud pulse */
    /* "the game begins" EN 8.6s / TR 8.95s */
    .mh-scene.is-active .mht--s2 .mht-app-start{animation:mht2Start .9s var(--s2start,8.6s) both, mht2StartPulse 1.8s var(--s2pulse,9.6s) ease-in-out infinite}
    @keyframes mht2Start{to{background:#e8590c;color:#fff}}
    @keyframes mht2StartPulse{0%,100%{box-shadow:0 0 0 rgba(232,89,12,0)}50%{box-shadow:0 0 18px rgba(232,89,12,.6)}}

    /* ---------- Scene 3: secret roles ---------- */
    .mht--s3 .mht-seat{z-index:1}
    .mht--s3 .mht-s3-mafia{z-index:3}
    .mh-scene.is-active .mht--s3 .mht-seat,
    .mh-scene.is-active .mht--s3 .mht-npost{animation:mhtFadeIn .4s both}
    .mht--s3 .mht-seat,.mht--s3 .mht-npost{opacity:0}
    .mht-dim{position:absolute;inset:0;border-radius:14px;background:rgba(0,0,0,.5);opacity:0;z-index:2;pointer-events:none}
    .mh-scene.is-active .mht--s3 .mht-dim{animation:mht3Dim 4s 3.3s both}
    @keyframes mht3Dim{0%{opacity:0}12%,86%{opacity:1}100%{opacity:0}}
    .mht-scard{position:absolute;left:50%;top:27px;width:26px;height:36px;z-index:4;opacity:0;
      transform-style:preserve-3d;
      transform:translate(-50%,0) translate(var(--dx),var(--dy)) scale(.2)}
    .mht-scard-back,.mht-scard-role{position:absolute;inset:0;border-radius:5px;backface-visibility:hidden;
      display:flex;align-items:center;justify-content:center}
    .mht-scard-back{background:linear-gradient(135deg,#2b2b3a,#1b1b26);border:1.5px solid rgba(255,255,255,.25)}
    .mht-scard-role{background:#f5f0e8;font-size:15px;transform:rotateY(180deg)}
    .mht-seat--p1 .mht-scard{--dx:-57px;--dy:60px}
    .mht-seat--p2 .mht-scard{--dx:-115px;--dy:-18px}
    .mht-seat--p3 .mht-scard{--dx:-57px;--dy:-96px}
    .mht-seat--p4 .mht-scard{--dx:57px;--dy:-96px}
    .mht-seat--p5 .mht-scard{--dx:115px;--dy:-18px}
    .mht-seat--p6 .mht-scard{--dx:57px;--dy:60px}
    .mh-scene.is-active .mht--s3 .mht-scard{animation:mht3Deal .5s var(--dealD,.2s) cubic-bezier(.3,1.1,.5,1) both, var(--flip) , mht3Hide .5s var(--s3hide,9.6s) both}
    .mht--s3 .mht-seat--p1 .mht-scard{--dealD:.2s}.mht--s3 .mht-seat--p2 .mht-scard{--dealD:.4s}
    .mht--s3 .mht-seat--p3 .mht-scard{--dealD:.6s}.mht--s3 .mht-seat--p4 .mht-scard{--dealD:.8s}
    .mht--s3 .mht-seat--p5 .mht-scard{--dealD:1.0s}.mht--s3 .mht-seat--p6 .mht-scard{--dealD:1.2s}
    /* word-accurate: Villagers ~2.1s, Mafia ~3.5s, Doctor ~6.7s (EN≈TR) */
    .mht--s3 .mht-s3-vill .mht-scard{--flip:mht3Flip 2.4s 2.1s both}
    .mht--s3 .mht-s3-mafia .mht-scard{--flip:mht3Flip 3.5s 3.5s both}
    .mht--s3 .mht-s3-doc .mht-scard{--flip:mht3Flip 2.6s 6.7s both}
    @keyframes mht3Deal{to{opacity:1;transform:translate(-50%,0) translate(0,0) scale(1)}}
    @keyframes mht3Flip{0%{transform:translate(-50%,0) rotateY(0)}18%,82%{transform:translate(-50%,0) rotateY(180deg)}100%{transform:translate(-50%,0) rotateY(0)}}
    @keyframes mht3Hide{to{opacity:0;transform:translate(-50%,0) scale(0)}}
    .mh-scene.is-active .mht--s3 .mht-s3-mafia{animation:mhtFadeIn .4s both, mht3MafiaBeat 3.5s 3.5s both}
    @keyframes mht3MafiaBeat{
      0%{box-shadow:0 0 0 rgba(239,68,68,0);transform:translate(-50%,-50%) rotate(0)}
      20%{box-shadow:0 0 18px rgba(239,68,68,.6)}
      40%{transform:translate(-50%,-50%) rotate(6deg)}
      60%{transform:translate(-50%,-50%) rotate(-6deg)}
      80%{box-shadow:0 0 18px rgba(239,68,68,.6);transform:translate(-50%,-50%) rotate(0)}
      100%{box-shadow:0 0 0 rgba(239,68,68,0);transform:translate(-50%,-50%) rotate(0)}}
    .mht-thread{position:absolute;inset:0;width:100%;height:100%;z-index:3;pointer-events:none}
    .mht-thread line{stroke:#ef4444;stroke-width:2;stroke-dasharray:6 6;opacity:0}
    .mh-scene.is-active .mht--s3 .mht-thread line{animation:mht3Thread 2.9s 4s both}
    @keyframes mht3Thread{0%{opacity:0;stroke-dashoffset:120}12%{opacity:1}80%{opacity:1;stroke-dashoffset:0}100%{opacity:0;stroke-dashoffset:0}}
    .mht-chip--shield{left:-14px;top:-12px;font-size:17px}
    .mh-scene.is-active .mht--s3 .mht-chip--shield{animation:mht3Shield 2.4s 7.3s both}
    @keyframes mht3Shield{0%{opacity:0;transform:scale(.4)}15%{opacity:1;transform:scale(1.15)}30%{transform:scale(1)}80%{opacity:1}100%{opacity:0}}
    /* Extra roles row — chips pop as Eric names them (Detective, Child, Mafia
       Leader), then the ▶ video pointer. TR scene-3 window is 17.9s. */
    .mht-xroles{position:absolute;left:50%;top:396px;transform:translateX(-50%);z-index:5;
      display:flex;align-items:center;gap:10px}
    .mht-xrole{width:38px;height:38px;border-radius:50%;background:rgba(255,255,255,.06);
      border:2px solid rgba(59,130,246,.55);display:flex;align-items:center;justify-content:center;
      font-size:18px;line-height:1;opacity:0;transform:scale(.4)}
    .mht-xrole--2{border-color:rgba(251,191,36,.55)}
    .mht-xrole--3{border-color:rgba(239,68,68,.55)}
    /* "the Detective, the Child, and the Mafia Leader" — chip per name (EN base, TR shifts +1.1s) */
    .mh-scene.is-active .mht--s3 .mht-xrole{animation:mhtPopIn .45s calc(var(--xd,12.6s) + var(--s3shift,0s)) cubic-bezier(.34,1.56,.64,1) both}
    .mht--s3 .mht-xrole--1{--xd:12.6s}.mht--s3 .mht-xrole--2{--xd:13.3s}.mht--s3 .mht-xrole--3{--xd:14s}
    .mht-xplay{display:flex;align-items:center;justify-content:center;
      padding:7px 13px;border-radius:999px;background:rgba(59,130,246,.16);border:1px solid rgba(59,130,246,.55);
      font-size:13px;font-weight:800;color:#fff;opacity:0;transform:translateY(12px)}
    .mh-scene.is-active .mht--s3 .mht-xplay{animation:mht3Play .55s calc(15.5s + var(--s3shift,0s)) cubic-bezier(.34,1.56,.64,1) both}
    @keyframes mht3Play{60%{opacity:1;transform:translateY(-4px)}100%{opacity:1;transform:translateY(0)}}

    /* ---------- Scene 4: night one ---------- */
    .mh-scene.is-active .mht--s4 .mht-sky--tonight{animation:mht4Sky 2s both}
    @keyframes mht4Sky{to{background-color:rgba(30,41,90,.55)}}
    .mht--s4 .mht-orb--moon{opacity:0;transform:translateY(16px)}
    .mh-scene.is-active .mht--s4 .mht-orb--sun{animation:mht4SunSet 1.6s both}
    .mh-scene.is-active .mht--s4 .mht-orb--moon{animation:mht4MoonRise 1.6s .6s both}
    @keyframes mht4SunSet{to{opacity:0;transform:translateY(16px)}}
    @keyframes mht4MoonRise{to{opacity:1;transform:translateY(0)}}
    .mh-scene.is-active .mht--s4 .mht-star{animation:mhtTwinkle 2.4s var(--std) 2s infinite}
    .mht--s4 .mht-seat{opacity:1}
    .mh-scene.is-active .mht--s4 .mht-seat{animation:mht4SeatDim 1s 1.1s both}
    @keyframes mht4SeatDim{to{filter:brightness(.5) saturate(.55)}}
    .mh-scene.is-active .mht--s4 .mht-seat .mht-lid{animation:mht4LidClose .45s var(--lidD,1.2s) both}
    .mht--s4 .mht-seat--p1 .mht-lid{--lidD:1.15s}.mht--s4 .mht-seat--p2 .mht-lid{--lidD:1.30s}
    .mht--s4 .mht-seat--p3 .mht-lid{--lidD:1.45s}.mht--s4 .mht-seat--p4 .mht-lid{--lidD:1.60s}
    .mht--s4 .mht-seat--p5 .mht-lid{--lidD:1.75s}.mht--s4 .mht-seat--p6 .mht-lid{--lidD:1.90s}
    @keyframes mht4LidClose{to{transform:scaleY(1)}}
    .mht-beam{position:absolute;left:167px;top:80px;width:130px;height:220px;z-index:1;opacity:0;
      transform:translate(-50%,0) rotate(-30deg);transform-origin:50% 0;
      background:linear-gradient(180deg, rgba(251,191,36,.30), transparent 82%);
      clip-path:polygon(50% 0, 100% 100%, 0 100%)}
    /* beam sweeps during "the narrator wakes each role in turn" (EN 3.3-6.2s) */
    .mh-scene.is-active .mht--s4 .mht-beam{animation:mht4Beam 12s 3.2s linear both}
    @keyframes mht4Beam{
      0%{opacity:0;transform:translate(-50%,0) rotate(-30deg)}
      2%{opacity:1;transform:translate(-50%,0) rotate(-30deg)}
      8%{transform:translate(-50%,0) rotate(30deg)}
      42%{transform:translate(-50%,0) rotate(30deg)}
      50%{transform:translate(-50%,0) rotate(-13deg)}
      90%{opacity:1;transform:translate(-50%,0) rotate(-13deg)}
      100%{opacity:0;transform:translate(-50%,0) rotate(-13deg)}}
    /* Mafia act on "choose their victim" (EN 7.1-8.6s); Doctor stays awake
       through the whole save sequence (TR runs longer via --s4dwDur) */
    .mh-scene.is-active .mht--s4 .mht-s4-mafia{animation:mht4SeatDim 1s 1.1s both, mht4Wake 2.4s 6.8s both}
    .mh-scene.is-active .mht--s4 .mht-s4-mafia .mht-lid{animation:mht4LidClose .45s var(--lidD,1.2s) both, mht4Peek 2.4s 6.8s both}
    .mh-scene.is-active .mht--s4 .mht-s4-doc{animation:mht4SeatDim 1s 1.1s both, mht4Wake var(--s4dwDur,7.4s) 8.55s both}
    .mh-scene.is-active .mht--s4 .mht-s4-doc .mht-lid{animation:mht4LidClose .45s var(--lidD,1.2s) both, mht4Peek var(--s4dwDur,7.4s) 8.55s both}
    @keyframes mht4Wake{0%{filter:brightness(.5) saturate(.55)}12%,86%{filter:brightness(1.05) saturate(1)}100%{filter:brightness(.5) saturate(.55)}}
    @keyframes mht4Peek{0%{transform:scaleY(1)}12%,86%{transform:scaleY(0)}100%{transform:scaleY(1)}}
    .mht-skull{position:absolute;left:110px;top:290px;font-size:20px;z-index:5;opacity:0;
      transform:translate(-50%,-50%) translate(57px,-125px)}
    /* BOTH doctor outcomes, in narration order: shield hovers the target →
       ✓ + the skull FADES ("guess right — nobody dies") → shield drifts to the
       wrong player → the skull RETURNS with a red pulse ("one player won't
       wake up"). Skull runs 5.7–15.7s, shield 9.2–15.6s. */
    .mh-scene.is-active .mht--s4 .mht-skull{animation:mht4Skull var(--s4skDur,8.5s) var(--s4skD,7.9s) linear both}
    @keyframes mht4Skull{
      0%{opacity:0;transform:translate(-50%,-50%) translate(57px,-125px) scale(.6);filter:none}
      5%{opacity:1;transform:translate(-50%,-50%) translate(57px,-125px) scale(1);filter:none}
      12%{transform:translate(-50%,-50%) translate(0,0) scale(1)}
      17%{transform:translate(-50%,-50%) translate(0,0) scale(1.25)}
      22%,44%{opacity:1;transform:translate(-50%,-50%) translate(0,0) scale(1);filter:none}
      50%,62%{opacity:.12;transform:translate(-50%,-50%) translate(0,0) scale(.9);filter:none}
      68%{opacity:1;transform:translate(-50%,-50%) translate(0,0) scale(1.3);filter:drop-shadow(0 0 10px rgba(239,68,68,.9))}
      76%{transform:translate(-50%,-50%) translate(0,0) scale(1);filter:drop-shadow(0 0 6px rgba(239,68,68,.6))}
      90%{transform:translate(-50%,-50%) translate(0,0) scale(1.15);filter:drop-shadow(0 0 12px rgba(239,68,68,.9))}
      100%{opacity:1;transform:translate(-50%,-50%) translate(0,0) scale(1);filter:drop-shadow(0 0 8px rgba(239,68,68,.7))}}
    .mht-shield{position:absolute;left:110px;top:290px;font-size:20px;z-index:6;opacity:0;
      transform:translate(-50%,-50%) translate(114px,23px)}
    .mh-scene.is-active .mht--s4 .mht-shield{animation:mht4Shield var(--s4shDur,6.8s) 9s linear both}
    @keyframes mht4Shield{
      0%{opacity:0;transform:translate(-50%,-50%) translate(114px,23px) scale(.6)}
      6%{opacity:1;transform:translate(-50%,-50%) translate(114px,23px) scale(1)}
      20%{transform:translate(-50%,-50%) translate(-14px,0) scale(1)}
      26%{transform:translate(-50%,-50%) translate(-14px,0) scale(1.15)}
      62%{transform:translate(-50%,-50%) translate(-14px,0) scale(1)}
      75%{transform:translate(-50%,-50%) translate(172px,-55px) scale(1)}
      82%{transform:translate(-50%,-50%) translate(172px,-55px) scale(1.2)}
      100%{opacity:1;transform:translate(-50%,-50%) translate(172px,-55px) scale(1)}}
    .mht-check{position:absolute;left:50%;top:-20px;transform:translateX(-50%) scale(.5);font-size:16px;font-weight:800;
      color:#22c55e;opacity:0;z-index:6;text-shadow:0 0 8px rgba(34,197,94,.8)}
    .mh-scene.is-active .mht--s4 .mht-check{animation:mht4Check 2.2s var(--s4ck,11.9s) both}
    @keyframes mht4Check{0%{opacity:0;transform:translateX(-50%) scale(.5)}14%{opacity:1;transform:translateX(-50%) scale(1.2)}80%{opacity:1;transform:translateX(-50%) scale(1)}100%{opacity:0;transform:translateX(-50%) scale(.8)}}

    /* ---------- Scene 5: day discussion — talk, lie, no-phone, dead-silent ----------
       All beat delays are word-accurate CSS vars (EN defaults; TR overrides in
       the [data-mh-lang="tr"] block). Continuity: P4 dies here and stays dead;
       P3 (the real Doctor) only gets a knife WARNING, not a real death — it wins
       later in scene 7, so it must survive this scene. */
    .mht--s5 .mht-sky--today{background-color:rgba(30,41,90,.55)}
    .mh-scene.is-active .mht--s5 .mht-sky--today{animation:mht5Sky 1.6s both}
    @keyframes mht5Sky{to{background-color:rgba(251,191,36,.14)}}
    .mht--s5 .mht-orb--sun{opacity:0;transform:translateY(16px)}
    .mh-scene.is-active .mht--s5 .mht-orb--moon{animation:mht4SunSet 1s both}
    .mh-scene.is-active .mht--s5 .mht-orb--sun{animation:mht4MoonRise 1s .4s both}

    /* P4 died in the night — the death lands at scene start, then stays */
    .mh-scene.is-active .mht--s5 .mht-s5-dead{animation:mhtDeath .9s .4s both}
    .mh-scene.is-active .mht--s5 .mht-s5-dead .mht-x{animation:mhtPopIn .4s 1.2s both}

    /* speech bubbles above the seats — accuse / claims / question marks */
    .mht-say{position:absolute;left:50%;top:-26px;transform:translateX(-50%);font-size:15px;line-height:1;
      opacity:0;z-index:5;padding:4px 6px;border-radius:11px 11px 11px 3px;
      background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.22)}
    @keyframes mht5Say{0%{opacity:0;transform:translateX(-50%) scale(.4)}12%{opacity:1;transform:translateX(-50%) scale(1.12)}22%{transform:translateX(-50%) scale(1)}82%{opacity:1;transform:translateX(-50%) scale(1)}100%{opacity:0;transform:translateX(-50%) scale(.9)}}
    /* "Accuse, defend, bluff" ~1.2s */
    .mh-scene.is-active .mht--s5 .mht-say--accuse{animation:mht5Say 3s var(--s5accuse,1.2s) both}
    /* "say you're the Doctor" — an innocent claims ~4.6s */
    .mh-scene.is-active .mht--s5 .mht-say--claim{animation:mht5Say 3.4s var(--s5claim,4.6s) both}
    /* "the Mafia can lie too" — the liar P1 ALSO claims Doctor + mask flick ~8.2s */
    .mh-scene.is-active .mht--s5 .mht-say--liar{animation:mht5Say 3.6s var(--s5liar,8.2s) both}
    .mh-scene.is-active .mht--s5 .mht-s5-liar .mht-alt{animation:mhtMaskFlick 1s calc(var(--s5liar,8.2s) + .2s) both}
    /* "no one knows who to trust" ~9.8s */
    .mh-scene.is-active .mht--s5 .mht-say--q{animation:mht5Say 2.6s var(--s5q,9.8s) both}
    .mh-scene.is-active .mht--s5 .mht-say--q2{animation:mht5Say 2.6s calc(var(--s5q,9.8s) + .3s) both}

    /* the real Doctor P3 reveals — a knife THREATENS, then passes (warning, not
       a real death: P3 must survive to win in scene 7) */
    .mht-say--doc{border-color:rgba(34,197,94,.6)}
    .mh-scene.is-active .mht--s5 .mht-say--doc{animation:mht5Say 4s var(--s5doc,14.8s) both}
    .mht-kill{position:absolute;left:50%;top:-4px;transform:translate(-50%,-50%) scale(.4);font-size:22px;opacity:0;z-index:7;
      filter:drop-shadow(0 0 8px rgba(239,68,68,.8))}
    .mh-scene.is-active .mht--s5 .mht-kill{animation:mht5Kill 2.4s var(--s5kill,17.9s) both}
    @keyframes mht5Kill{0%{opacity:0;transform:translate(-50%,-50%) scale(.4) rotate(-20deg)}18%{opacity:1;transform:translate(-50%,-50%) scale(1.2) rotate(0)}35%{transform:translate(-50%,-50%) scale(1) rotate(0)}70%{opacity:1}100%{opacity:0;transform:translate(-50%,-50%) scale(.85)}}
    .mh-scene.is-active .mht--s5 .mht-s5-doc{animation:mht5DocWarn 2.4s var(--s5kill,17.9s) both}
    @keyframes mht5DocWarn{0%,100%{filter:none;box-shadow:0 0 0 rgba(239,68,68,0)}30%,55%{filter:brightness(1.05);box-shadow:0 0 18px rgba(239,68,68,.85)}}

    /* the one hard rule: 💬 talk = OK, 📱 phone = banned */
    .mht-rule2{position:absolute;left:50%;top:384px;transform:translate(-50%,0) translateY(22px);opacity:0;z-index:6;
      display:flex;gap:24px;align-items:center}
    .mh-scene.is-active .mht--s5 .mht-rule2{animation:mht5Rule .6s var(--s5rule,19.5s) both}
    @keyframes mht5Rule{to{opacity:1;transform:translate(-50%,0) translateY(0)}}
    .mht-rule2-opt{position:relative;display:flex;align-items:center;justify-content:center;font-size:26px;
      width:56px;height:52px;border-radius:14px;border:2px solid rgba(255,255,255,.14);background:rgba(255,255,255,.05)}
    .mht-rule2-tick{position:absolute;right:-8px;top:-10px;font-size:15px;font-style:normal;font-weight:800;color:#22c55e;opacity:0;
      text-shadow:0 0 8px rgba(34,197,94,.7)}
    .mht-rule2-slash{position:absolute;left:8%;top:50%;width:84%;height:3px;border-radius:2px;
      background:#ef4444;box-shadow:0 0 8px rgba(239,68,68,.8);transform:rotate(-18deg) scaleX(0);transform-origin:left center}
    /* "say anything" → talk gets the green ✓ ~20.7s */
    .mh-scene.is-active .mht--s5 .mht-rule2-talk{animation:mht5Pick .5s var(--s5talk,20.7s) both}
    @keyframes mht5Pick{to{border-color:#22c55e;box-shadow:0 0 14px rgba(34,197,94,.3)}}
    .mh-scene.is-active .mht--s5 .mht-rule2-tick{animation:mhtPopIn .4s var(--s5talk,20.7s) both}
    /* "never show your phone" → phone gets the red slash ~22.0s */
    .mh-scene.is-active .mht--s5 .mht-rule2-phone{animation:mht5NopeShake .5s var(--s5phone,22s) both, mht5Nope .6s calc(var(--s5phone,22s) + .5s) both}
    .mh-scene.is-active .mht--s5 .mht-rule2-slash{animation:mht5Slash .45s calc(var(--s5phone,22s) + .1s) both}
    @keyframes mht5Slash{0%{transform:rotate(-18deg) scaleX(0)}100%{transform:rotate(-18deg) scaleX(1)}}
    @keyframes mht5NopeShake{0%,100%{transform:translateX(0)}25%{transform:translateX(-3px)}50%{transform:translateX(3px)}75%{transform:translateX(-2px)}}
    @keyframes mht5Nope{to{border-color:rgba(239,68,68,.55)}}

    /* dead stay silent — the muted P4 ~26.3s */
    .mht-mute{position:absolute;left:50%;top:-26px;transform:translate(-50%,0) scale(.4);font-size:18px;opacity:0;z-index:7}
    .mh-scene.is-active .mht--s5 .mht-mute{animation:mhtPopIn .5s var(--s5mute,26.3s) both}

    /* ---------- Scene 6: the vote ---------- */
    .mht--s6 .mht-sky--day{background-color:rgba(251,191,36,.14)}
    .mht-banner{position:absolute;left:50%;top:18px;transform:translate(-50%,-40px);font-size:26px;opacity:0;z-index:5}
    .mh-scene.is-active .mht--s6 .mht-banner{animation:mht6Banner .6s .1s cubic-bezier(.34,1.56,.64,1) both}
    @keyframes mht6Banner{to{opacity:1;transform:translate(-50%,0)}}
    .mht-chip--hand{left:50%;top:-24px;transform:translateX(-50%);font-size:16px}
    .mh-scene.is-active .mht--s6 .mht-chip--hand{animation:mht6Hand 1.8s var(--hd,1s) both}
    .mht--s6 .mht-seat--p1 .mht-chip--hand{--hd:1.0s}.mht--s6 .mht-seat--p2 .mht-chip--hand{--hd:1.15s}
    .mht--s6 .mht-seat--p3 .mht-chip--hand{--hd:1.3s}.mht--s6 .mht-seat--p5 .mht-chip--hand{--hd:1.45s}
    .mht--s6 .mht-seat--p6 .mht-chip--hand{--hd:1.6s}
    @keyframes mht6Hand{0%{opacity:0;transform:translateX(-50%) translateY(8px)}15%{opacity:1;transform:translateX(-50%) translateY(0)}80%{opacity:1}100%{opacity:0}}
    .mht-dot{position:absolute;width:12px;height:12px;border-radius:50%;opacity:0;z-index:6;background:var(--c);
      left:var(--sx);top:var(--sy);box-shadow:0 0 8px var(--c)}
    .mh-scene.is-active .mht-dot{animation:mht6Dot .9s var(--dd) linear both}
    @keyframes mht6Dot{0%{opacity:0;transform:translate(-50%,-50%)}14%{opacity:1}86%{opacity:1;transform:translate(-50%,-50%) translate(var(--tx),var(--ty))}100%{opacity:0;transform:translate(-50%,-50%) translate(var(--tx),var(--ty))}}
    /* TR scene-6 window is 10.13s with Eric — the whole sequence is compressed */
    .mht--s6 .mht-dot--1{--sx:282px;--sy:235px;--tx:-230px;--ty:0px;--c:#3b82f6;--dd:1.8s}
    .mht--s6 .mht-dot--2{--sx:224px;--sy:313px;--tx:0px;--ty:-156px;--c:#22c55e;--dd:2.3s}
    .mht--s6 .mht-dot--3{--sx:52px;--sy:235px;--tx:172px;--ty:-78px;--c:#a855f7;--dd:2.8s}
    .mht--s6 .mht-dot--4{--sx:224px;--sy:157px;--tx:-172px;--ty:78px;--c:#ef4444;--dd:3.3s}
    .mht--s6 .mht-dot--5{--sx:110px;--sy:157px;--tx:-58px;--ty:78px;--c:#f97316;--dd:3.8s}
    .mht-tally{position:absolute;left:50%;top:-30px;transform:translateX(-50%);z-index:7;width:22px;height:22px}
    .mht-tally b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
      font-size:14px;font-weight:800;color:#fff;background:rgba(239,68,68,.85);border-radius:50%;opacity:0}
    .mh-scene.is-active .mht--s6 .mht-tally-1{animation:mht6T 1.5s 2.6s both}
    .mh-scene.is-active .mht--s6 .mht-tally-2{animation:mht6T 0.5s 4.1s both}
    .mh-scene.is-active .mht--s6 .mht-tally-3{animation:mht6T3 2.8s 4.6s both}
    @keyframes mht6T{0%{opacity:0;transform:scale(.4)}12%{opacity:1;transform:scale(1.15)}22%{transform:scale(1)}88%{opacity:1}100%{opacity:0}}
    @keyframes mht6T3{0%{opacity:0;transform:scale(.4)}6%{opacity:1;transform:scale(1.15)}12%{transform:scale(1)}
      20%,30%{background:rgba(239,68,68,1);box-shadow:0 0 14px rgba(239,68,68,.9)}
      86%{opacity:1}100%{opacity:0}}
    .mh-scene.is-active .mht--s6 .mht-s6-dies{animation:mhtDeath 1s 4.9s both}
    .mh-scene.is-active .mht--s6 .mht-s6-dies .mht-x{animation:mhtPopIn .4s 5.7s both}
    .mh-scene.is-active .mht--s6 .mht-seat:not(.mht-s6-liar){animation:mht6Dim 2s var(--s6dim,5.6s) both}
    .mh-scene.is-active .mht--s6 .mht-s6-dies{animation:mhtDeath 1s 4.9s both, mht6Dim 2s var(--s6dim,5.6s) both}
    /* Dim via opacity, NOT filter — a filter keyframe would momentarily strip
       the grayscale off dead seats (P4/P5) and break the death convention. */
    @keyframes mht6Dim{0%,100%{opacity:1}25%,75%{opacity:.45}}
    .mh-scene.is-active .mht--s6 .mht-s6-liar .mht-alt{animation:mhtMaskFlick .8s var(--s6fl,6s) both}
    .mht-qcard{position:absolute;left:50%;top:-52px;transform:translateX(-50%) translateY(10px);z-index:7;opacity:0;
      width:22px;height:30px;border-radius:4px;background:#f5f0e8;color:#1b1b26;
      display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:800}
    .mh-scene.is-active .mht--s6 .mht-qcard{animation:mht6Q .6s var(--s6q,9s) cubic-bezier(.34,1.56,.64,1) both}
    @keyframes mht6Q{to{opacity:1;transform:translateX(-50%) translateY(0)}}

    /* ---------- Scene 7: time-lapse + endings ---------- */
    .mht-shrink{position:absolute;inset:0;transform:scale(.86);transform-origin:50% 46%}
    .mht--s7 .mht-sky--lapse{background-color:rgba(30,41,90,.55)}
    .mht--s7 .mht-orb--sun{opacity:0}
    .mh-scene.is-active .mht--s7 .mht-sky--lapse{animation:mht7Sky 2.6s both}
    @keyframes mht7Sky{0%,18%{background-color:rgba(30,41,90,.55)}30%,42%{background-color:rgba(251,191,36,.14)}
      54%,66%{background-color:rgba(30,41,90,.55)}78%,100%{background-color:rgba(251,191,36,.14)}}
    .mh-scene.is-active .mht--s7 .mht-orb--moon{animation:mht7Moon 2.6s both}
    .mh-scene.is-active .mht--s7 .mht-orb--sun{animation:mht7Sun 2.6s both}
    @keyframes mht7Moon{0%,18%{opacity:1}30%,42%{opacity:0}54%,66%{opacity:1}78%,100%{opacity:0}}
    @keyframes mht7Sun{0%,18%{opacity:0}30%,42%{opacity:1}54%,66%{opacity:0}78%,100%{opacity:1}}
    .mht-ringarrow{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
    .mht-ringarrow ellipse{fill:none;stroke:rgba(251,191,36,.45);stroke-width:2;
      stroke-dasharray:850;stroke-dashoffset:850}
    /* scene-7 window with Eric is ~7.6s in both languages — tight timeline */
    .mh-scene.is-active .mht--s7 .mht-ringarrow ellipse{animation:mht7Ring 2.2s .2s linear both}
    @keyframes mht7Ring{to{stroke-dashoffset:0}}
    .mht--s7 .mht-dot--a{--sx:282px;--sy:235px;--tx:-172px;--ty:-78px;--c:#3b82f6;--dd:1.5s}
    .mht--s7 .mht-dot--b{--sx:224px;--sy:313px;--tx:-114px;--ty:-156px;--c:#22c55e;--dd:1.75s}
    .mht--s7 .mht-dot--c{--sx:282px;--sy:235px;--tx:-58px;--ty:-78px;--c:#3b82f6;--dd:3.0s}
    .mht--s7 .mht-dot--d{--sx:224px;--sy:313px;--tx:0px;--ty:-156px;--c:#22c55e;--dd:3.25s}
    .mh-scene.is-active .mht--s7 .mht-dot{animation:mht6Dot .6s var(--dd) linear both}
    .mh-scene.is-active .mht--s7 .mht-s7-caught1{animation:mhtDeath .7s 2.2s both}
    .mh-scene.is-active .mht--s7 .mht-s7-caught1 .mht-x{animation:mhtPopIn .35s 2.7s both}
    .mh-scene.is-active .mht--s7 .mht-s7-caught2{animation:mhtDeath .7s 3.7s both}
    .mh-scene.is-active .mht--s7 .mht-s7-caught2 .mht-x{animation:mhtPopIn .35s 4.2s both}
    .mh-scene.is-active .mht--s7 .mht-badge{animation:mht7Badge .5s var(--bd,4.4s) cubic-bezier(.34,1.56,.64,1) both}
    .mht--s7 .mht-s7-caught1 .mht-badge{--bd:4.55s}
    .mht--s7 .mht-s7-caught2 .mht-badge{--bd:4.4s}
    @keyframes mht7Badge{to{opacity:1;transform:translateX(-50%) scale(1)}}
    .mht-badge{transform:translateX(-50%) scale(.4)}
    .mh-scene.is-active .mht--s7 .mht-s7-winner{animation:mht7Win .9s 4.7s both}
    @keyframes mht7Win{to{box-shadow:0 0 18px rgba(34,197,94,.75);transform:translate(-50%,-50%) scale(1.08)}}
    .mht-trophy{position:absolute;left:50%;top:118px;transform:translate(-50%,-50%) scale(.3);font-size:34px;opacity:0;z-index:8;
      filter:drop-shadow(0 0 16px rgba(251,191,36,.6))}
    .mh-scene.is-active .mht--s7 .mht-trophy{animation:mht7Trophy .5s 4.9s cubic-bezier(.34,1.56,.64,1) both}
    @keyframes mht7Trophy{to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
    .mht-conf{position:absolute;top:96px;left:var(--cx);width:7px;height:7px;border-radius:2px;background:var(--c);opacity:0;z-index:8}
    .mht-conf--1{--cx:26%;--c:#ef4444}.mht-conf--2{--cx:38%;--c:#3b82f6}.mht-conf--3{--cx:50%;--c:#fbbf24}
    .mht-conf--4{--cx:62%;--c:#22c55e}.mht-conf--5{--cx:74%;--c:#a855f7}.mht-conf--6{--cx:86%;--c:#f97316}
    .mh-scene.is-active .mht--s7 .mht-conf{animation:mht7Conf 1.4s var(--cd,5s) linear both}
    .mht--s7 .mht-conf--1{--cd:5.0s}.mht--s7 .mht-conf--2{--cd:5.15s}.mht--s7 .mht-conf--3{--cd:5.05s}
    .mht--s7 .mht-conf--4{--cd:5.2s}.mht--s7 .mht-conf--5{--cd:5.1s}.mht--s7 .mht-conf--6{--cd:5.25s}
    @keyframes mht7Conf{0%{opacity:0;transform:translateY(0) rotate(0)}10%{opacity:1}100%{opacity:0;transform:translateY(150px) rotate(300deg)}}
    .mht-altend{position:absolute;inset:0;z-index:8;border-radius:14px;background:rgba(10,10,13,.9);opacity:0;
      display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px}
    .mh-scene.is-active .mht--s7 .mht-altend{animation:mht7Alt 1.8s var(--s7alt,5.6s) both}
    @keyframes mht7Alt{0%{opacity:0}18%,80%{opacity:1}100%{opacity:0}}
    .mht-altend-scale{font-size:36px;animation:mht7Tip 1.2s ease-in-out infinite alternate}
    @keyframes mht7Tip{from{transform:rotate(-7deg)}to{transform:rotate(7deg)}}
    .mht-altend-dots{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;color:rgba(255,255,255,.6)}
    .mht-altend-dots i{width:12px;height:12px;border-radius:50%}
    .mht-altend-dots i.red{background:#ef4444;box-shadow:0 0 8px rgba(239,68,68,.7)}
    .mht-altend-dots i.blu{background:#3b82f6}

    /* ---------- Scene 8: outro ---------- */
    .mht--s8{display:flex;flex-direction:column;align-items:center;justify-content:center}
    .mht-s8-cast{position:absolute;left:50%;top:120px;transform:translateX(-50%);display:flex;gap:8px}
    .mht-mini{width:34px;height:34px;border-radius:50%;background:#1d1d24;border:2.5px solid var(--ring);
      display:flex;align-items:center;justify-content:center;font-size:16px;
      filter:blur(2.5px) brightness(.45)}
    /* EN scene-8 window is only 4.15s with Eric — the outro sprints */
    .mh-scene.is-active .mht--s8 .mht-mini{animation:mht8Cast .4s calc(var(--md,3s) + var(--s8shift,0s)) cubic-bezier(.34,1.56,.64,1) both}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(1){--md:3.00s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(2){--md:3.06s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(3){--md:3.12s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(4){--md:3.18s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(5){--md:3.24s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(6){--md:3.30s}
    .mh-scene.is-active .mht--s8 .mht-mini:nth-child(7){--md:3.36s}
    @keyframes mht8Cast{to{filter:blur(0) brightness(1);transform:scale(1.1)}}
    .mh-outro-words{position:absolute;left:0;right:0;top:200px;display:flex;gap:12px;flex-wrap:wrap;justify-content:center;padding:0 14px}
    .mh-outro-word{font-size:21px;font-weight:800;color:#fff;letter-spacing:.01em;opacity:0}
    /* stamps land on Eric's words: Lie 0 / Bluff .88 / Accuse 1.47 / Survive 2.34 (EN≈TR) */
    .mh-scene.is-active .mht--s8 .mh-outro-word{animation:mht8Stamp .35s var(--wd) both, mht8WordDim .25s var(--wdim,2.4s) both, mht8Out .3s calc(2.95s + var(--s8shift,0s)) both}
    .mht--s8 .mh-outro-word--1{--wd:.1s;--wdim:.85s}
    .mht--s8 .mh-outro-word--2{--wd:.85s;--wdim:1.5s}
    .mht--s8 .mh-outro-word--3{--wd:1.5s;--wdim:2.3s}
    .mht--s8 .mh-outro-word--4{--wd:2.3s;--wdim:2.75s}
    @keyframes mht8Stamp{0%{opacity:0;transform:scale(1.7);filter:blur(6px)}100%{opacity:1;transform:scale(1);filter:blur(0)}}
    @keyframes mht8WordDim{to{opacity:.4}}
    @keyframes mht8Out{to{opacity:0;transform:scale(.9)}}
    .mh-outro-mask{position:absolute;left:50%;top:238px;transform:translate(-50%,0) scale(.4) rotate(-8deg);font-size:52px;opacity:0;
      filter:drop-shadow(0 0 18px rgba(239,68,68,.4))}
    .mh-scene.is-active .mht--s8 .mh-outro-mask{animation:mht8Mask .5s calc(3.15s + var(--s8shift,0s)) cubic-bezier(.34,1.56,.64,1) both, mht8Glow 2s calc(3.65s + var(--s8shift,0s)) ease-in-out infinite}
    @keyframes mht8Mask{to{opacity:1;transform:translate(-50%,0) scale(1) rotate(0)}}
    @keyframes mht8Glow{0%,100%{filter:drop-shadow(0 0 12px rgba(239,68,68,.35))}50%{filter:drop-shadow(0 0 26px rgba(239,68,68,.7))}}
    .mh-outro-title{position:absolute;left:0;right:0;top:312px;text-align:center;
      font-size:23px;font-weight:800;color:#fff;letter-spacing:-.01em;opacity:0;transform:translateY(10px)}
    .mh-scene.is-active .mht--s8 .mh-outro-title{animation:mht8Title .4s calc(3.45s + var(--s8shift,0s)) both}
    @keyframes mht8Title{to{opacity:1;transform:translateY(0)}}

    /* ---- Turkish beat overrides (word-accurate; Eric's TR pacing differs) ----
       Set once at the player root — openMafiaHowTo writes data-mh-lang. */
    #screen-mafia-howto[data-mh-lang="tr"] .mh-scene{
      --s1mask:7.1s;--gshift:1.1s;--s1pill:10s;--s1n:11.6s;--s1nc:13s;
      --s2gold:7.8s;--s2start:8.95s;--s2pulse:9.95s;
      --s3hide:10.5s;--s3shift:1.1s;
      --s4dwDur:9.8s;--s4skDur:11s;--s4skD:7.3s;--s4shDur:8.4s;--s4ck:13.1s;
      --s5accuse:1.6s;--s5liar:8.6s;--s5q:10.5s;--s5doc:17.1s;--s5kill:20.4s;
      --s5rule:21.5s;--s5talk:22.5s;--s5phone:24.3s;--s5mute:29.9s;
      --s6dim:5s;--s6fl:5.4s;--s6q:8.3s;
      --s7alt:5.9s;
      --s8shift:-.3s;
    }

    /* ---- Arabic beat overrides (word-accurate; Mustafa's MSA pacing) ----
       Derived from mafia-ar.alignment.json word times. Beats not listed fall
       through to the EN inline defaults (which already fit Arabic's pacing). */
    #screen-mafia-howto[data-mh-lang="ar"] .mh-scene{
      --s1mask:6.9s;--gshift:.7s;--s1pill:10.8s;--s1n:11.6s;--s1nc:13s;
      --s2gold:7.4s;--s2start:8.6s;--s2pulse:9.5s;
      --s3hide:10.8s;--s3shift:1.7s;
      --s4skD:7s;--s4skDur:9.5s;--s4ck:11.2s;
      --s5accuse:1.7s;--s5claim:6s;--s5liar:9s;--s5q:11.2s;--s5doc:16s;--s5kill:18.4s;
      --s5rule:19.6s;--s5talk:21s;--s5phone:23s;--s5mute:27.1s;
      --s6dim:5.2s;--s6fl:6.2s;--s6q:8.3s;
      --s7alt:5s;
    }

    /* Paused = frozen frame, like a real video. The seek machinery re-syncs
       the frame on every scrub, so paused scrubbing previews correctly. */
    #screen-mafia-howto.mh-freeze .mh-scene,
    #screen-mafia-howto.mh-freeze .mh-scene *{animation-play-state:paused !important}

    /* Accessibility: collapse the show to final frames for reduced-motion users */
    @media (prefers-reduced-motion: reduce){
      .mht *, .mht{animation-duration:.01s !important;animation-delay:0s !important}
    }
    /* ----- End card ----- */
    .mh-scene-end{gap:18px}
    .mh-end-icon{font-size:64px;
      opacity:0;transform:scale(.5);
      transition:opacity .5s ease, transform .5s cubic-bezier(.34,1.56,.64,1);
    }
    .mh-end-title{
      font-size:28px;font-weight:800;letter-spacing:-.02em;
      opacity:0;transform:translateY(8px);
      transition:opacity .5s ease .2s, transform .5s ease .2s;
    }
    .mh-end-sub{
      font-size:15px;color:rgba(255,255,255,.65);text-align:center;max-width:300px;
      opacity:0;transform:translateY(8px);
      transition:opacity .5s ease .4s, transform .5s ease .4s;
    }
    .mh-end-actions{
      display:flex;gap:10px;margin-top:14px;
      opacity:0;transform:translateY(8px);
      transition:opacity .5s ease .6s, transform .5s ease .6s;
    }
    .mh-scene-end.is-active .mh-end-icon,
    .mh-scene-end.is-active .mh-end-title,
    .mh-scene-end.is-active .mh-end-sub,
    .mh-scene-end.is-active .mh-end-actions{opacity:1;transform:none}
    .mh-end-btn{
      padding:12px 22px;border-radius:24px;font-size:14px;font-weight:700;
      border:none;cursor:pointer;font-family:inherit;
      transition:transform .15s ease, background .15s ease;
      -webkit-tap-highlight-color:transparent;
    }
    .mh-end-btn:active{transform:scale(.97)}
    .mh-end-btn--ghost{background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,.25)}
    .mh-end-btn--ghost:hover{background:rgba(255,255,255,.06)}
    .mh-end-btn--primary{background:#fff;color:#0a0a0d}

    /* ----- Controls bar ----- */
    .mh-controls{
      display:flex;align-items:center;gap:14px;
      padding:14px 18px calc(env(safe-area-inset-bottom,0) + 18px);
      background:linear-gradient(180deg, transparent, rgba(0,0,0,.6) 60%);
      /* Video timeline stays left→right in every language (like YouTube/Netflix):
         keeps the fill + knob on the same side and the play/time layout normal. */
      direction:ltr;
    }
    .mh-play-pause{
      width:40px;height:40px;border-radius:50%;
      background:rgba(255,255,255,.12);color:#fff;border:none;cursor:pointer;
      display:flex;align-items:center;justify-content:center;flex-shrink:0;
      transition:background .15s ease;-webkit-tap-highlight-color:transparent;
    }
    .mh-play-pause:hover{background:rgba(255,255,255,.2)}
    .mh-play-pause.is-paused .mh-icon-pause{display:none}
    .mh-play-pause:not(.is-paused) .mh-icon-play{display:none}
    /* Progress bar is a 24px-tall hit target (mobile-friendly tap area) with
       a centered 3px visual track inside. The knob sits at the fill edge and
       grows on hover/drag for clear scrubbing affordance. */
    .mh-progress{
      flex:1;position:relative;height:24px;
      display:flex;align-items:center;
      cursor:pointer;-webkit-tap-highlight-color:transparent;
      touch-action:none;            /* keep drag horizontal, no scroll hijack */
      user-select:none;-webkit-user-select:none;
    }
    .mh-progress-track{
      position:relative;width:100%;height:3px;
      background:rgba(255,255,255,.15);border-radius:2px;
      transition:height .12s ease;
    }
    .mh-progress:hover  .mh-progress-track,
    .mh-progress.is-scrubbing .mh-progress-track{height:5px}
    .mh-progress-fill{
      height:100%;background:#fbbf24;width:0;border-radius:2px;
      transition:width .1s linear;will-change:width;
    }
    .mh-progress.is-scrubbing .mh-progress-fill{transition:none}
    .mh-progress-knob{
      /* physical `left` — app-08 sets knob.style.left = pct+'%' at runtime;
         a logical inset here would resolve to `right` in RTL and fight it */
      position:absolute;top:50%;left:0;
      width:0;height:0;border-radius:50%;background:#fbbf24;
      transform:translate(-50%,-50%);
      box-shadow:0 0 0 0 rgba(251,191,36,.25);
      transition:width .12s ease, height .12s ease, box-shadow .12s ease;
      pointer-events:none;
    }
    .mh-progress:hover  .mh-progress-knob,
    .mh-progress.is-scrubbing .mh-progress-knob{
      width:14px;height:14px;
      box-shadow:0 0 0 6px rgba(251,191,36,.18);
    }
    .mh-progress:focus{outline:none}
    .mh-progress:focus-visible .mh-progress-knob{
      width:14px;height:14px;
      box-shadow:0 0 0 4px rgba(251,191,36,.35);
    }
    .mh-time{
      font-size:12px;color:rgba(255,255,255,.65);min-width:36px;text-align:end;
      font-variant-numeric:tabular-nums;
    }

    /* ===== Mafia — VIDEO 2 "Extra Powers" (mhx-*) ========================
       Second explainer (Detective / Child / Mafia Leader). Shares the how-to
       player shell + engine (same #screen-mafia-howto, .mh-scene sync, scrubber,
       freeze); only the reel (scenes + audio) differs. Scenes reuse Video 1's
       persistent tableau look (.mht-seat--p* ring + gold narrator + dead=
       grayscale/tilt/✕) so both videos feel like one app. Beats are word-synced:
       EN defaults inline as var() fallbacks, TR overrides in the block at the end.
       Scene ids: x1 intro / x2 detective / x3 child / x4 leader. */

    /* Stage — same 335x430 tableau box + edge vignette as .mht */
    .mhx{flex:none;width:335px;max-width:100%;height:430px;position:relative;margin:0 auto}
    .mhx::after{content:"";position:absolute;inset:-12px;border-radius:24px;pointer-events:none;z-index:9;
      background:radial-gradient(ellipse at center, transparent 58%, rgba(0,0,0,.5) 100%)}

    /* Night overlay + detective spotlight + pointing beams (shared elements) */
    .mhx-dim{position:absolute;inset:-12px;border-radius:24px;background:rgba(10,14,44,.7);opacity:0;z-index:1;pointer-events:none}
    .mhx-spot{position:absolute;left:52px;top:235px;width:82px;height:82px;border-radius:50%;transform:translate(-50%,-50%);
      background:radial-gradient(circle, rgba(168,85,247,.55), transparent 70%);opacity:0;z-index:1;filter:blur(3px)}
    .mhx-beam{position:absolute;inset:0;width:100%;height:100%;z-index:3;pointer-events:none;overflow:visible}
    .mhx-beam line{stroke:#fbbf24;stroke-width:2.5;stroke-linecap:round;
      stroke-dasharray:var(--len,190);stroke-dashoffset:var(--len,190);opacity:0;
      filter:drop-shadow(0 0 4px rgba(251,191,36,.6))}
    @keyframes mhxBeamDraw{0%{opacity:.2;stroke-dashoffset:var(--len,190)}20%{opacity:1}100%{opacity:1;stroke-dashoffset:0}}
    @keyframes mhxBeamOut{to{opacity:0}}

    /* Narrator thumb bubble (👍/👎), reused by scenes x2 + x4 */
    .mhx-thumb{position:absolute;left:206px;top:44px;width:32px;height:32px;z-index:6}
    .mhx-thumb>span{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
      font-size:24px;line-height:1;opacity:0;filter:drop-shadow(0 2px 5px rgba(0,0,0,.55))}
    @keyframes mhxThumbUp{0%{opacity:0;transform:translateY(8px) scale(.5)}60%{transform:translateY(-3px) scale(1.15)}100%{opacity:1;transform:translateY(0) scale(1)}}
    @keyframes mhxThumbDown{0%{opacity:0;transform:translateY(-8px) scale(.5)}60%{transform:translateY(3px) scale(1.15)}100%{opacity:1;transform:translateY(0) scale(1)}}
    @keyframes mhxThumbClear{to{opacity:0}}

    /* Verdict / role chips positioned on their seats (opacity 0 → pop via mhtPopIn) */
    .mhx-chip-role,.mhx-chip-ok,.mhx-chip-kill{top:-8px;right:-8px}
    .mhx-chip-vote{top:-8px;left:-8px}
    /* margin-left kept physical — left:50% centring pair, see .av ripple note */
    .mhx-chip-vill{bottom:-9px;left:50%;margin-left:-8px}
    .mhx-chip-spark{top:-10px;left:50%;margin-left:-8px}
    .mhx-chip-shield{bottom:-9px;left:50%;margin-left:-8px}
    .mhx-chip-shush{top:-8px;right:-9px}

    /* Shared "hold" glows: red = Mafia, green = innocent */
    @keyframes mhxRedHold{0%{box-shadow:0 0 0 rgba(239,68,68,0)}50%{box-shadow:0 0 18px rgba(239,68,68,.85)}100%{box-shadow:0 0 12px rgba(239,68,68,.6)}}
    @keyframes mhxGreenHold{0%{box-shadow:0 0 0 rgba(34,197,94,0)}50%{box-shadow:0 0 18px rgba(34,197,94,.8)}100%{box-shadow:0 0 12px rgba(34,197,94,.5)}}
    @keyframes mhxSuspense{0%,100%{box-shadow:0 0 0 rgba(245,115,31,0)}50%{box-shadow:0 0 16px rgba(245,115,31,.7)}}
    @keyframes mhxNight{to{opacity:.9}}

    /* ---------- Scene X1: the "Spice it up" panel ---------- */
    .mhx-panel{position:absolute;left:50%;top:50%;opacity:0;
      transform:translate(-50%,-50%) translateY(16px) scale(.94);
      width:252px;padding:18px 16px;border-radius:20px;background:#15151b;
      border:1px solid rgba(255,255,255,.10);box-shadow:0 18px 44px rgba(0,0,0,.6);z-index:2}
    .mh-scene.is-active .mhx--s1 .mhx-panel{animation:mhxPanelIn .6s .2s cubic-bezier(.3,1.2,.5,1) both}
    @keyframes mhxPanelIn{to{opacity:1;transform:translate(-50%,-50%) translateY(0) scale(1)}}
    .mhx-panel-title{display:flex;align-items:center;gap:7px;justify-content:center;
      font-size:15px;font-weight:800;color:#fff;margin-bottom:14px}
    .mhx-toggle{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:12px;
      background:#1d1d24;border:1.5px solid transparent;margin-bottom:8px}
    .mhx-toggle:last-child{margin-bottom:0}
    .mhx-toggle-emoji{font-size:20px;line-height:1}
    .mhx-toggle-name{flex:1;font-size:13px;font-weight:700;color:#e8e8ea;text-align:start}
    .mhx-switch{position:relative;width:34px;height:20px;border-radius:999px;background:#3a3a44;flex-shrink:0}
    .mhx-switch::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff}
    /* rows flip ON (track+knob+border), then all glow, then the emoji preview */
    .mh-scene.is-active .mhx--s1 .mhx-toggle{animation:mhxRowOn .4s var(--d,3.8s) both, mhxRowGlow 1s var(--x1glow,5.6s) both}
    @keyframes mhxRowOn{to{border-color:#f5731f;background:rgba(245,115,31,.14)}}
    @keyframes mhxRowGlow{0%,100%{box-shadow:0 0 0 rgba(245,115,31,0)}45%{box-shadow:0 0 16px rgba(245,115,31,.55)}}
    .mh-scene.is-active .mhx--s1 .mhx-switch{animation:mhxSwitchOn .4s var(--d,3.8s) both}
    @keyframes mhxSwitchOn{to{background:#f5731f}}
    .mh-scene.is-active .mhx--s1 .mhx-switch::after{animation:mhxKnob .4s var(--d,3.8s) both}
    @keyframes mhxKnob{to{transform:translateX(14px)}}
    .mhx--s1 .mhx-toggle--1{--d:var(--x1t1,3.8s)}
    .mhx--s1 .mhx-toggle--2{--d:var(--x1t2,4.2s)}
    .mhx--s1 .mhx-toggle--3{--d:var(--x1t3,4.6s)}
    .mh-scene.is-active .mhx--s1 .mhx-toggle-emoji{animation:mhxEmojiPop .6s var(--pd,7.6s) both}
    @keyframes mhxEmojiPop{0%{transform:scale(1)}40%{transform:scale(1.4)}100%{transform:scale(1)}}
    .mhx--s1 .mhx-toggle--1 .mhx-toggle-emoji{--pd:var(--x1prev,7.6s)}
    .mhx--s1 .mhx-toggle--2 .mhx-toggle-emoji{--pd:calc(var(--x1prev,7.6s) + .15s)}
    .mhx--s1 .mhx-toggle--3 .mhx-toggle-emoji{--pd:calc(var(--x1prev,7.6s) + .3s)}

    /* ---------- Scene X2: Detective ---------- */
    .mh-scene.is-active .mhx--s2 .mhx-dim{animation:mhxNight .8s .15s both}
    .mh-scene.is-active .mhx--s2 .mhx-spot{animation:mhtFadeIn .5s var(--x2wake,.3s) both}
    .mh-scene.is-active .mhx--s2 .mht-seat--p5 .mht-badge{animation:mhtPopIn .4s var(--x2wake,.3s) both}
    /* beam A → P1 (draws at "points"), then fades as beam B → P3 draws */
    .mh-scene.is-active .mhx--s2 .mhx-beam--a{animation:mhxBeamDraw .5s var(--x2point,1.6s) both, mhxBeamOut .3s var(--x2move,7s) both}
    .mh-scene.is-active .mhx--s2 .mhx-beam--b{animation:mhxBeamDraw .5s var(--x2move,7s) both}
    /* narrator thumb — only ONE visible at a time (no stacked/peeking emoji):
       👍 rises when the narrator answers, then fades out exactly as 👎 rises. */
    .mh-scene.is-active .mhx--s2 .mhx-thumb-up{animation:mhxThumbUp .4s var(--x2raise,3.3s) both, mhxThumbClear .25s var(--x2down,7.5s) both}
    .mh-scene.is-active .mhx--s2 .mhx-thumb-down{animation:mhxThumbDown .4s var(--x2down,7.5s) both}
    /* P1 = Mafia (red glow + 🎭); P3 = innocent (green glow + ✅) */
    .mh-scene.is-active .mhx--s2 .mht-seat--p1{animation:mhxRedHold 1.2s var(--x2up,5.4s) both}
    .mh-scene.is-active .mhx--s2 .mhx-chip-role{animation:mhtPopIn .4s var(--x2up,5.4s) both}
    .mh-scene.is-active .mhx--s2 .mht-seat--p3{animation:mhxGreenHold 1.2s var(--x2down,7.5s) both}
    .mh-scene.is-active .mhx--s2 .mhx-chip-ok{animation:mhtPopIn .4s var(--x2down,7.5s) both}

    /* ---------- Scene X3: Child ---------- */
    .mh-scene.is-active .mhx--s3 .mht-seat--p4 .mht-badge{animation:mhtPopIn .4s var(--x3vill,.3s) both}
    .mh-scene.is-active .mhx--s3 .mhx-chip-vill{animation:mhtPopIn .4s var(--x3vill,.3s) both}
    /* P4 pulses (elimination looms), then a cause chip (✋ vote / 🔪 mafia), then dies */
    .mh-scene.is-active .mhx--s3 .mht-seat--p4{animation:mhxSuspense 1s var(--x3elim,3.5s) both, mhtDeath .6s var(--x3dead,8.5s) both}
    .mh-scene.is-active .mhx--s3 .mhx-chip-vote{animation:mhtPopIn .35s var(--x3vote,5.6s) both}
    .mh-scene.is-active .mhx--s3 .mhx-chip-kill{animation:mhtPopIn .35s var(--x3kill,7s) both}
    .mh-scene.is-active .mhx--s3 .mht-seat--p4 .mht-x{animation:mhtPopIn .35s calc(var(--x3dead,8.5s) + .5s) both}
    /* dead Child points at P2 → P2 leaves too → ✕2 */
    .mh-scene.is-active .mhx--s3 .mhx-beam--a{animation:mhxBeamDraw .6s var(--x3point,11s) both}
    .mh-scene.is-active .mhx--s3 .mht-seat--p2{animation:mhtDeath .6s var(--x3target,13.6s) both}
    .mh-scene.is-active .mhx--s3 .mht-seat--p2 .mht-x{animation:mhtPopIn .35s calc(var(--x3target,13.6s) + .5s) both}
    .mhx-two{position:absolute;left:167px;top:235px;transform:translate(-50%,-50%) scale(.4);opacity:0;z-index:6;
      font-size:30px;font-weight:900;color:#ef4444;text-shadow:0 2px 10px rgba(0,0,0,.7)}
    .mh-scene.is-active .mhx--s3 .mhx-two{animation:mhxTwoPop .5s var(--x3two,15.8s) both}
    @keyframes mhxTwoPop{0%{opacity:0;transform:translate(-50%,-50%) scale(.4)}60%{opacity:1;transform:translate(-50%,-50%) scale(1.25)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}}

    /* ---------- Scene X4: Mafia Leader ---------- */
    /* Mafia team glows red; P6 swaps 😏→🎩 (replaces a regular Mafia) */
    .mh-scene.is-active .mhx--s4 .mht-seat--p1{animation:mhxRedHold 1s var(--x4team,.3s) both}
    .mh-scene.is-active .mhx--s4 .mht-seat--p6{animation:mhxRedHold 1s var(--x4team,.3s) both}
    .mhx-swapb{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:23px;opacity:0}
    .mh-scene.is-active .mhx--s4 .mhx-swapa{animation:mhxSwapOut .4s var(--x4replace,2.5s) both}
    .mh-scene.is-active .mhx--s4 .mhx-swapb{animation:mhxSwapIn .4s var(--x4replace,2.5s) both}
    @keyframes mhxSwapOut{to{opacity:0;transform:rotateY(90deg)}}
    @keyframes mhxSwapIn{0%{opacity:0;transform:rotateY(-90deg)}100%{opacity:1;transform:rotateY(0)}}
    /* night + team kill: two beams → P3 dies */
    .mh-scene.is-active .mhx--s4 .mhx-dim{animation:mhxNight .8s var(--x4kill,4.6s) both}
    .mh-scene.is-active .mhx--s4 .mhx-beam--k1{animation:mhxBeamDraw .5s var(--x4kill,4.6s) both, mhxBeamOut .4s var(--x4power,8s) both}
    .mh-scene.is-active .mhx--s4 .mhx-beam--k2{animation:mhxBeamDraw .5s var(--x4kill,4.6s) both, mhxBeamOut .4s var(--x4power,8s) both}
    .mh-scene.is-active .mhx--s4 .mht-seat--p3{animation:mhtDeath .6s var(--x4victim,6s) both}
    .mh-scene.is-active .mhx--s4 .mht-seat--p3 .mht-x{animation:mhtPopIn .35s calc(var(--x4victim,6s) + .5s) both}
    /* special power ✨; Detective can't catch → 🕵️ wakes + 🛡️ shield on the leader */
    .mh-scene.is-active .mhx--s4 .mhx-chip-spark{animation:mhtPopIn .4s var(--x4power,8s) both}
    .mh-scene.is-active .mhx--s4 .mhx-badge-det{animation:mhtPopIn .4s var(--x4shield,9.7s) both}
    .mh-scene.is-active .mhx--s4 .mhx-chip-shield{animation:mhtPopIn .4s var(--x4shield,9.7s) both}
    /* Detective points at the leader; narrator lies (bounce) → false 👎 + ✅ */
    .mh-scene.is-active .mhx--s4 .mhx-beam--d{animation:mhxBeamDraw .5s var(--x4point,11.8s) both}
    .mh-scene.is-active .mhx--s4 .mht-npost{animation:mhxNBounce .5s var(--x4lie,13.9s) both}
    @keyframes mhxNBounce{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.18)}}
    .mh-scene.is-active .mhx--s4 .mhx-thumb-down{animation:mhxThumbDown .4s var(--x4down,15.4s) both}
    .mh-scene.is-active .mhx--s4 .mhx-chip-ok{animation:mhtPopIn .4s var(--x4down,15.4s) both}
    /* only the narrator knows: 🤫 + P6's hidden 🎭 flickers to the viewer */
    .mh-scene.is-active .mhx--s4 .mhx-chip-shush{animation:mhtPopIn .4s var(--x4truth,17.9s) both}
    .mh-scene.is-active .mhx--s4 .mht-seat--p6 .mht-alt{animation:mhtMaskFlick 1.6s var(--x4truth,17.9s) both}

    /* ---- Turkish beat overrides (word-accurate; Eric's TR pacing differs) ----
       Same mechanism as Video 1: openMafiaHowTo writes data-mh-lang on the root. */
    #screen-mafia-howto[data-mh-lang="tr"] .mhx--s1{--x1t1:3.6s;--x1t2:4.0s;--x1t3:4.4s;--x1glow:5.0s;--x1prev:6.5s}
    #screen-mafia-howto[data-mh-lang="tr"] .mhx--s2{--x2wake:.2s;--x2point:2.0s;--x2raise:3.7s;--x2up:6.1s;--x2move:7.2s;--x2down:7.4s}
    #screen-mafia-howto[data-mh-lang="tr"] .mhx--s3{--x3vill:.2s;--x3elim:3.3s;--x3vote:5.5s;--x3kill:7.0s;--x3dead:9.1s;--x3point:11.4s;--x3target:14.6s;--x3two:16.5s}
    #screen-mafia-howto[data-mh-lang="tr"] .mhx--s4{--x4team:.2s;--x4replace:2.9s;--x4kill:4.9s;--x4victim:6.0s;--x4power:7.1s;--x4shield:8.5s;--x4point:10.9s;--x4lie:14.1s;--x4down:16.5s;--x4truth:20.5s}

    /* ---- Arabic beat overrides (word-accurate; Mustafa's MSA pacing) ---- */
    #screen-mafia-howto[data-mh-lang="ar"] .mhx--s1{--x1t1:4.4s;--x1t2:4.8s;--x1t3:5.2s;--x1glow:6.4s;--x1prev:7.8s}
    #screen-mafia-howto[data-mh-lang="ar"] .mhx--s2{--x2wake:.2s;--x2point:1.5s;--x2raise:3.4s;--x2up:5.8s;--x2move:6.9s;--x2down:7.6s}
    #screen-mafia-howto[data-mh-lang="ar"] .mhx--s3{--x3vill:.3s;--x3elim:3.9s;--x3vote:5.6s;--x3kill:6.9s;--x3dead:8.1s;--x3point:10.8s;--x3target:13s;--x3two:15.3s}
    #screen-mafia-howto[data-mh-lang="ar"] .mhx--s4{--x4team:.3s;--x4replace:2.3s;--x4kill:4.9s;--x4victim:6s;--x4power:8s;--x4shield:9.7s;--x4point:12.5s;--x4lie:14.9s;--x4down:16.6s;--x4truth:19.9s}

    /* Reduced-motion: collapse Video 2 animations to final frames (matches .mht rule) */
    @media (prefers-reduced-motion: reduce){
      .mhx *, .mhx{animation-duration:.01s !important;animation-delay:0s !important}
    }

    /* Lobby "How the powers work" video button (step 3) — hero style: a filled
       accent play-circle, title + sub, and a chevron. Themes via tokens. */
    /* Quiet neutral strip (2026-07-09 "Meter" redesign — the loud accent card
       was demoted so the balance meter can lead step 3). Accent survives only
       on the small play glyph. */
    .mafia-xtra-trigger{
      display:flex;align-items:center;gap:11px;width:100%;margin:14px 0 12px;min-height:44px;
      padding:11px 12px;border-radius:12px;cursor:pointer;
      background:var(--bg-subtle);border:1px solid var(--border-strong);
      font-family:inherit;-webkit-tap-highlight-color:transparent;transition:background .15s ease;
    }
    .mafia-xtra-trigger:hover{background:var(--bg-hover)}
    .mafia-xtra-trigger:active{transform:scale(.99)}
    .mafia-xtra-trigger-play{
      flex-shrink:0;width:30px;height:30px;border-radius:50%;
      background:var(--accent-soft);color:var(--accent);
      display:flex;align-items:center;justify-content:center;
    }
    .mafia-xtra-trigger-text{flex:1;min-width:0;text-align:start;display:flex;flex-direction:column}
    .mafia-xtra-trigger-title{font-size:13.5px;font-weight:700;color:var(--text);letter-spacing:-.005em}
    .mafia-xtra-trigger-sub{font-size:11px;color:var(--text-secondary);margin-top:1px}
    .mafia-xtra-trigger-chev{flex-shrink:0;color:var(--text-tertiary)}

    /* ===== Social safety — block / report / blocked list (2026-07-27) =====
       Colours come only from theme variables, so light and dark both work
       without a second ruleset (and without the dark-mode inversion trap of
       hard-coded greys). Selected states use an accent BORDER, not a fill,
       matching the pattern used everywhere else in the app. */

    /* The quiet "Block or report" link at the foot of the add-friend popup.
       Deliberately understated — it must be findable, not shouty, mid-party. */
    .friend-add-safety{
      display:block;width:100%;margin-top:14px;padding:6px 0;
      background:none;border:0;cursor:pointer;
      font-size:13px;font-weight:600;color:var(--text-tertiary);
      text-decoration:underline;text-underline-offset:3px;
    }
    .friend-add-safety:hover{color:var(--danger)}

    /* Report form */
    .safety-report-sub{
      padding:0 20px 10px;font-size:13px;color:var(--text-secondary);text-align:start;
    }
    .safety-reason.is-selected,
    .safety-also.is-selected{
      border:1.5px solid var(--accent);border-radius:12px;color:var(--accent);
    }
    .safety-details-label{
      display:block;padding:12px 20px 6px;
      font-size:13px;font-weight:600;color:var(--text-secondary);text-align:start;
    }
    .safety-details-input{
      display:block;width:calc(100% - 40px);margin:0 20px;padding:10px 12px;
      border:1px solid var(--border-strong);border-radius:12px;
      background:var(--bg);color:var(--text);
      font:inherit;font-size:14px;resize:vertical;
    }
    .safety-details-input:focus{outline:none;border-color:var(--accent)}

    /* Blocked people list */
    .blocked-sub{
      padding:4px 4px 14px;font-size:13px;color:var(--text-secondary);text-align:start;
    }

    /* ---- Delete account (db/fix/25) ----
       Logical properties throughout (padding-inline, border-inline-start,
       text-align:start) so the screen mirrors correctly in Arabic without a
       separate RTL block. */
    .del-lead{
      padding:4px 4px 16px;font-size:14px;line-height:1.5;
      color:var(--text-secondary);text-align:start;
    }
    .del-card{
      border-radius:var(--radius-md);padding:14px 16px;margin-bottom:12px;
      border:1px solid var(--border);background:var(--surface);text-align:start;
    }
    .del-card-gone{border-inline-start:3px solid var(--danger)}
    .del-card-kept{border-inline-start:3px solid var(--border-strong)}
    .del-card-title{font-weight:600;font-size:14px;margin-bottom:8px}
    .del-list{margin:0;padding-inline-start:20px}
    .del-list li{font-size:13.5px;line-height:1.7;color:var(--text-secondary)}
    .del-kept-body{margin:0;font-size:13.5px;line-height:1.6;color:var(--text-secondary)}
    .del-ack{
      display:flex;align-items:flex-start;gap:10px;
      padding:14px 4px 18px;font-size:14px;line-height:1.45;
      cursor:pointer;text-align:start;
    }
    .del-ack input{
      width:20px;height:20px;flex:0 0 20px;margin:0;
      accent-color:var(--danger);cursor:pointer;
    }
    .del-button{margin-bottom:24px}
    .blocked-row{
      display:flex;align-items:center;gap:12px;
      padding:10px 4px;border-bottom:1px solid var(--border);
    }
    .blocked-row-text{flex:1;min-width:0}
    .blocked-row-name{
      font-size:15px;font-weight:600;color:var(--text);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    }
    .blocked-row-kind{font-size:12px;color:var(--text-tertiary);margin-top:1px}
    /* .btn is width:100%;height:48px by default — both wrong for a button
       sitting inline at the end of a row (it pushed the page 44px wider than
       a 375px phone). Override explicitly. */
    .blocked-unblock{flex:none;width:auto;height:auto;padding:7px 14px;font-size:13px}

    /* Admin reports queue */
    .admin-report-card{
      border:1px solid var(--border);border-radius:14px;
      /* --bg-subtle, NOT --card: this stylesheet has no --card variable, and
         var() on an undefined name silently falls back to transparent. On dark
         this also reads as elevation against the page, which is the pattern
         used elsewhere in the app. */
      padding:14px;margin-bottom:10px;background:var(--bg-subtle);
    }
    .admin-report-card.is-done{opacity:.6}
    .admin-report-top{display:flex;align-items:center;gap:8px;margin-bottom:6px}
    .admin-report-who{flex:1;min-width:0;font-size:16px;font-weight:700;color:var(--text);
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .admin-report-chip{
      flex:none;padding:2px 9px;border-radius:999px;font-size:11px;font-weight:700;
      background:var(--danger-soft);color:var(--danger);
    }
    .admin-report-chip.is-done{background:var(--accent-soft);color:var(--accent)}
    .admin-report-reason{font-size:14px;font-weight:600;color:var(--text);margin-bottom:4px}
    /* Free text one player typed about another — wrap hard so a long
       unbroken string cannot blow out the card or scroll the page sideways. */
    .admin-report-details{
      font-size:14px;color:var(--text-secondary);margin:6px 0 8px;
      overflow-wrap:anywhere;white-space:pre-wrap;
    }
    .admin-report-meta{font-size:12px;color:var(--text-tertiary);margin-top:2px}
    /* Same .btn width:100%/height:48px override as .blocked-unblock above. */
    .admin-report-btn{width:auto;height:auto;margin-top:10px;padding:7px 14px;font-size:13px}

    /* Toast action button — "Undo" after blocking (2026-07-28). The toast is a
       pill with centred text; the action sits inline after it. */
    .lobby-toast-action{
      margin-inline-start:12px;padding:3px 10px;
      background:none;border:1px solid var(--border-strong);border-radius:var(--radius-pill);
      color:var(--accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer;
      vertical-align:middle;
    }
    .lobby-toast-action:hover{border-color:var(--accent)}

    /* "Blocked people · N" at the foot of the Friends list. Only rendered when
       the count is > 0, so it never clutters an ordinary user's screen. */
    .friends-blocked-link{
      display:flex;align-items:center;gap:10px;width:100%;
      margin-top:22px;padding:12px 14px;
      background:none;border:1px solid var(--border);border-radius:var(--radius-md);
      color:var(--text-secondary);font:inherit;font-size:14px;font-weight:600;
      cursor:pointer;text-align:start;
    }
    .friends-blocked-link:hover{border-color:var(--border-strong);color:var(--text)}
    .friends-blocked-link svg{width:18px;height:18px;flex:none}
    .friends-blocked-link span:first-of-type{flex:1;min-width:0}
    .friends-blocked-count{
      flex:none;min-width:22px;padding:1px 7px;border-radius:999px;
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:12px;font-weight:700;text-align:center;
    }
