    :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;
      --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;
      --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}
    a{color:var(--text);text-decoration:none;cursor:pointer}

    .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="lobby"] #screen-login{display:none}
    html[data-boot-screen="lobby"] #screen-lobby{display:flex}
    html[data-boot-screen="cham-lobby"] #screen-login{display:none}
    html[data-boot-screen="cham-lobby"] #screen-cham-lobby{display:flex}
    html[data-boot-screen="liar-lobby"] #screen-login{display:none}
    html[data-boot-screen="liar-lobby"] #screen-liar-lobby{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:var(--header-h);background:var(--bg);
      border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;padding:0 8px 0 8px;gap:8px}
    .header-title{font-size:17px;font-weight:600;letter-spacing:-.01em;flex:1;text-align:left;padding-left: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}
    .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(--text)}
    .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)}
    .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)}
    /* Enforce the HTML `hidden` attribute even on elements with explicit display rules
       (e.g. .btn uses display:inline-flex which otherwise overrides the UA hidden style).
       Required so hot/cham/liar Reset/Leave buttons actually hide when not eligible. */
    [hidden]{display:none !important}
    .btn-danger{background:var(--danger);color:#fff}
    .btn-success{background:var(--success);color:#fff}
    /* 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-left:44px}
    .search-icon{position:absolute;top:50%;left: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(--primary);color:var(--on-primary);border-color:var(--primary)}

    /* Player count picker (Games — step 1) */
    /* Player-count filter chip row. Horizontally scrollable on narrow viewports so 7+ chips
       never wrap to a second line. Active chip = filled primary (text on inverted bg),
       inactive = subtle outline. Real-time: tapping a chip immediately re-renders the games
       list below. Replaces the old two-step "How many players?" landing flow. */
    /* Hot Seat game cards (full width row) */
    .hotseat-card{
      display:flex;gap:14px;padding:14px;border:1px solid var(--border);border-radius:var(--radius-lg);
      background:var(--bg);cursor:pointer;transition:box-shadow .15s ease,transform .15s ease;margin-bottom:10px;
      align-items:center;
    }
    .hotseat-card:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}
    .hotseat-thumb{
      width:72px;height:72px;border-radius:var(--radius-md);flex-shrink:0;
      display:flex;align-items:center;justify-content:center;color:#fff;position:relative;overflow:hidden;
    }
    .hotseat-thumb.classic{background:linear-gradient(135deg,#2c2c2c 0%,#444 100%)}
    .hotseat-thumb svg{width:38px;height:38px;color:#fff;opacity:.95}
    .hotseat-info{flex:1;min-width:0}
    .hotseat-title-row{display:flex;align-items:center;gap:8px;margin-bottom:4px}
    .hotseat-title{font-weight:700;font-size:16px;letter-spacing:-.01em}
    .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}
    .hotseat-desc{font-size:13px;color:var(--text-secondary);margin-bottom:4px}
    .hotseat-meta{font-size:12px;color:var(--text-tertiary)}

    /* 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-right: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}}
    /* 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)}
    /* Kebab (⋯) button on every accepted-friend row. Destructive "Remove" now
       lives behind this menu so the friends list reads social, not admin-y. */
    .friend-overflow{
      width:36px;height:36px;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;
    }
    .friend-overflow:hover{background:var(--bg-subtle);color:var(--text)}
    .friend-overflow:active{background:var(--bg-hover)}
    .friend-overflow svg{width:18px;height:18px}
    /* 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}
    .friends-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;margin-left:6px;border-radius:var(--radius-pill);background:var(--primary);color:var(--on-primary);font-size:11px;font-weight:700;line-height:1}
    .friends-tab-badge[hidden]{display:none}
    #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;right: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:0;background:transparent}
    .lobby-invite-tile{display:flex;align-items:center;gap:10px;padding:7px 4px;border-bottom:1px solid var(--border)}
    .lobby-invite-tile:last-child{border-bottom:none}
    /* 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;
    }
    .lobby-invite-section + .lobby-invite-tile{border-top:none}
    /* 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;left:10px;top:50%;transform:translateY(-50%);color:var(--text-secondary);pointer-events:none}
    .lobby-invite-search{
      width:100%;
      padding:9px 12px 9px 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}
    /* Primary CTA — filled pill. The Invite action is the whole point of the sheet, so it
       should read as the dominant control. "Invited" and "Joined" states downgrade visually
       to communicate that no action is needed there anymore. */
    .lobby-invite-btn{border:1px solid var(--primary);background:var(--primary);color:var(--on-primary);
      font-weight:600;font-size:13px;padding:6px 14px;border-radius:var(--radius-pill);cursor:pointer;
      display:inline-flex;align-items:center;gap:5px;transition:background .15s ease,opacity .15s ease}
    .lobby-invite-btn:hover{background:color-mix(in srgb, var(--primary) 88%, black)}
    .lobby-invite-btn:active{background:color-mix(in srgb, var(--primary) 78%, black)}
    .lobby-invite-btn.invited{border-color:var(--border);color:var(--text-secondary);background:var(--bg-subtle);cursor:default}
    .lobby-invite-btn.invited:hover{background:var(--bg-subtle)}
    /* Joined state — passive confirmation, must read quieter than the Invite CTA.
       Just text + checkmark, no chip fill. The bright --success text alone
       already communicates "done"; a chip background only adds visual weight
       without adding meaning. Matches Discord/Linear/Slack done-state patterns. */
    .lobby-invite-btn.joined{border-color:transparent;color:var(--success);background:transparent;cursor:default;font-weight:600;padding:8px 6px}
    .lobby-invite-btn.joined:hover{background:transparent}
    .lobby-invite-btn.joined svg{opacity:.85}
    .lobby-invite-btn.declined{border-color:var(--border);color:var(--text-secondary);background:var(--bg-subtle);cursor:default;opacity:.7}
    .lobby-invite-btn[disabled]{cursor:default}
    .lobby-invite-cancel{background:none;border:none;color:var(--text-secondary);font-size:12px;padding:4px 6px;cursor:pointer;text-decoration:underline}
    .lobby-invite-cancel:hover{color:var(--text)}
    .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)}

    /* Profile */
    .profile-head{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 0 16px}
    .avatar-lg{width:96px;height:96px;border-radius:var(--radius-pill);
      background:linear-gradient(135deg,#e4e4e4 0%,#c0c0c0 100%);
      display:flex;align-items:center;justify-content:center;font-size:36px;font-weight:600;color:var(--text)}
    .profile-name{font-size:22px;font-weight:700;letter-spacing:-.01em}
    .profile-username{color:var(--text-secondary);font-size:14px}
    .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:20px 0 8px}
    .stat{background:var(--bg-subtle);border-radius:var(--radius-md);padding:14px 8px;text-align:center}
    .stat-value{font-size:20px;font-weight:700}
    .stat-label{font-size:12px;color:var(--text-secondary);margin-top:2px}
    .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 4px 20px}
    .admin-hero-badge{
      display:inline-flex;align-items:center;gap:6px;
      padding:5px 10px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);border:1px solid var(--border);
      color:var(--text-secondary);font-size:11px;font-weight:600;
      letter-spacing:.06em;text-transform:uppercase;margin-bottom:14px
    }
    .admin-hero-badge svg{width:12px;height:12px}
    .admin-hero-title{font-size:28px;font-weight:700;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;gap:12px}
    @media(min-width:520px){.admin-grid{grid-template-columns:1fr 1fr}}
    .admin-tile{
      position:relative;text-align:left;
      display:flex;align-items:flex-start;gap:14px;
      padding:16px 16px 18px;
      background:var(--surface);
      border:1px solid var(--border);
      border-radius:var(--radius-lg);
      color:var(--text);font:inherit;cursor:not-allowed;
      transition:transform .15s ease, box-shadow .15s ease, border-color .15s ease;
      min-height:96px
    }
    .admin-tile:disabled{opacity:.78}
    .admin-tile.is-next{
      border-color:var(--text);
      box-shadow:var(--shadow-md);
      opacity:1
    }
    .admin-tile.is-live{
      cursor:pointer;
      border-color:var(--text);
      box-shadow:var(--shadow-md)
    }
    .admin-tile.is-live:hover{
      transform:translateY(-1px);
      box-shadow:var(--shadow-lg)
    }
    .admin-tile.is-live .admin-tile-icon{color:var(--text)}
    .admin-tile-chevron{
      position:absolute;bottom:14px;right:14px;
      color:var(--text-tertiary)
    }
    .admin-tile-icon{
      width:40px;height:40px;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      border-radius:var(--radius-md);
      background:var(--bg-subtle);
      color:var(--text-secondary)
    }
    .admin-tile.is-next .admin-tile-icon{color:var(--text)}
    .admin-tile-icon svg{width:20px;height:20px}
    .admin-tile-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;padding-right:60px}
    .admin-tile-title{font-size:15px;font-weight:600;line-height:1.2;letter-spacing:-.01em}
    .admin-tile-desc{font-size:13px;line-height:1.4;color:var(--text-secondary)}
    .admin-tile-badge{
      position:absolute;top:12px;right:12px;
      display:inline-flex;align-items:center;height:22px;padding:0 9px;
      border-radius:var(--radius-pill);
      background:var(--bg-subtle);
      border:1px solid var(--border);
      color:var(--text-tertiary);
      font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase
    }
    .admin-tile-badge-next{
      background:var(--text);color:var(--bg);border-color:var(--text)
    }
    .admin-footnote{
      margin:22px 4px 0;color:var(--text-tertiary);
      font-size:12px;line-height:1.5;text-align:center
    }

    /* ===== Admin → Feedback moderation ===== */
    .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:var(--bg);
      border-color:var(--text);
      color:var(--text)
    }
    .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(--text);color:var(--bg);border-color:var(--text)
    }
    .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:var(--radius-lg);
      padding:14px 14px 12px;
      margin-bottom:10px
    }
    .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(--bg-subtle);
      display:flex;align-items:center;justify-content:center;
      color:var(--text-secondary);
      font-size:13px;font-weight:600
    }
    .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;
      padding:3px 8px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);
      color:var(--text-secondary);
      font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase
    }
    .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
    }
    .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:var(--text);color:var(--bg)}
    .admin-fb-status-done{
      background:var(--bg-subtle);
      color:var(--text-tertiary);
      border:1px solid var(--border)
    }
    .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);
    }

    /* Hero card — one big number leading the page.
       Layout: text on top (label + value + delta), sparkline as its own
       full-width strip pinned to the bottom. No overlap. */
    .admin-stats-hero{
      background:var(--surface);
      border:1px solid var(--text);
      border-radius:var(--radius-lg);
      padding:18px 18px 0;
      margin-bottom:14px;
      display:flex;flex-direction:column;
      overflow:hidden;
    }
    .admin-stats-hero-body{padding-bottom:14px}
    .admin-stats-hero-label{
      font-size:11px;font-weight:700;
      letter-spacing:.08em;text-transform:uppercase;
      color:var(--text-secondary);
      margin-bottom:10px;
    }
    .admin-stats-hero-value{
      font-size:48px;font-weight:700;
      letter-spacing:-.03em;line-height:1;
      color:var(--text);
      margin-bottom:10px;
    }
    .admin-stats-hero-delta{
      font-size:13px;font-weight:600;
      color:var(--text-secondary);
      display:inline-flex;align-items:center;gap:6px;
    }
    .admin-stats-hero-sparkline{
      height:48px;width:auto;
      margin:0 -18px;          /* extend to card edges */
      color:var(--text);
      opacity:.85;
      display:block;
      line-height:0;
    }
    .admin-stats-hero-sparkline svg{
      width:100%;height:100%;display:block;
    }

    /* 2×2 secondary grid */
    .admin-stats-grid{
      display:grid;grid-template-columns:1fr 1fr;gap:10px;
      margin-bottom:14px;
    }
    .admin-stats-card{
      background:var(--surface);
      border:1px solid var(--border);
      border-radius:var(--radius-lg);
      padding:14px 14px 0;
      min-height:130px;
      display:flex;flex-direction:column;
      overflow:hidden;
    }
    .admin-stats-card-body{padding-bottom:10px}
    .admin-stats-card-top{
      display:flex;align-items:center;gap:8px;
      color:var(--text-secondary);
      font-size:11px;font-weight:700;
      letter-spacing:.06em;text-transform:uppercase;
      margin-bottom:8px;
    }
    .admin-stats-card-top svg{width:14px;height:14px;flex-shrink:0}
    .admin-stats-card-value{
      font-size:28px;font-weight:700;
      letter-spacing:-.02em;line-height:1;
      color:var(--text);
      margin-bottom:8px;
    }
    .admin-stats-card-delta{
      font-size:11.5px;font-weight:600;
      color:var(--text-secondary);
      display:inline-flex;align-items:center;gap:4px;
    }
    .admin-stats-card-spark{
      height:28px;
      margin:0 -14px;          /* extend to card edges */
      color:var(--text);
      opacity:.75;
      display:block;
      line-height:0;
    }
    .admin-stats-card-spark svg{
      width:100%;height:100%;display:block;
    }

    /* Delta arrows — single accent, no green/red fills */
    .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 }   /* → */

    /* Per-game breakdown */
    .admin-stats-breakdown{
      background:var(--surface);
      border:1px solid var(--border);
      border-radius:var(--radius-lg);
      padding:14px 14px 12px;
      margin-bottom:14px;
    }
    .admin-stats-breakdown-title{
      font-size:11px;font-weight:700;
      letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-secondary);
      margin-bottom:12px;
    }
    .admin-stats-bd-row{
      display:flex;align-items:center;gap:10px;
      padding:6px 0;
    }
    .admin-stats-bd-name{
      flex:0 0 88px;
      font-size:13px;font-weight:600;color:var(--text);
    }
    .admin-stats-bd-bar{
      flex:1;height:6px;
      background:var(--bg-subtle);
      border-radius:var(--radius-pill);
      overflow:hidden;
    }
    .admin-stats-bd-bar-fill{
      height:100%;background:var(--text);
      border-radius:var(--radius-pill);
      transition:width .25s ease;
    }
    .admin-stats-bd-count{
      flex:0 0 auto;
      font-size:13px;font-weight:700;color:var(--text);
      min-width:24px;text-align:right;
    }

    /* 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;
    }

    /* Tap affordance — every stat card is clickable */
    .admin-stats-hero,
    .admin-stats-card{
      cursor:pointer;
      transition:transform .15s ease, box-shadow .15s ease;
    }
    .admin-stats-hero:hover,
    .admin-stats-card:hover{
      transform:translateY(-1px);
    }
    .admin-stats-hero:active,
    .admin-stats-card:active{
      transform:translateY(0);
    }

    /* ───────── 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{
      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 / value / delta on the left, close button on the right */
    .admin-stats-detail-head{
      display:flex;align-items:flex-start;justify-content:space-between;
      gap:14px;margin-bottom:22px;
    }
    .admin-stats-detail-head-text{min-width:0;flex:1}
    .admin-stats-detail-close{
      flex-shrink:0;margin-top:-4px;margin-right:-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:10px;
    }
    .admin-stats-detail-value{
      font-size:52px;font-weight:700;
      letter-spacing:-.035em;line-height:1;
      color:var(--text);margin-bottom:10px;
    }
    .admin-stats-detail-delta{
      font-size:13.5px;font-weight:600;
      color:var(--text-secondary);
      display:inline-flex;align-items:center;gap:6px;
    }

    /* Chart container — fixed pixel height, SVG fills it with a proper
       aspect-ratio viewBox (NO preserveAspectRatio:none stretching). This is
       what fixes the distorted-dots + stretched-text problems from earlier. */
    .admin-stats-detail-chart{
      position:relative;
      height:240px;
      margin:4px -2px 2px;
      color:var(--text);
    }
    .admin-stats-detail-chart svg{
      width:100%;height:100%;display:block;overflow:visible;
    }
    .admin-stats-detail-chart .grid-line{
      stroke:var(--border);stroke-width:1;stroke-dasharray:3 4;
    }
    .admin-stats-detail-chart .y-label{
      font-size:10.5px;font-weight:600;
      fill:var(--text-tertiary);
      font-family:inherit;
    }
    .admin-stats-detail-chart .area{
      fill:var(--text);opacity:.07;
    }
    .admin-stats-detail-chart .line{
      stroke:var(--text);stroke-width:2;fill:none;
      stroke-linecap:round;stroke-linejoin:round;
    }
    .admin-stats-detail-chart .dot{
      fill:var(--surface-elevated);stroke:var(--text);stroke-width:2;
    }

    /* 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. Divider above for visual rest. */
    .admin-stats-detail-summary{
      display:grid;grid-template-columns:repeat(3, 1fr);
      gap:8px;
      margin-top:22px;
      padding-top:18px;
      border-top:1px solid var(--border);
    }
    .admin-stats-detail-summary-cell{
      text-align:center;
    }
    .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:20px;font-weight:700;
      letter-spacing:-.02em;
      color:var(--text);
    }

    /* Login */
    .login{min-height:100vh;display:flex;flex-direction:column;padding:32px 24px 24px;background:var(--bg);flex:1}
    /* Clean Google-only login: two centered stacks, brand at top half, CTA at bottom half. */
    .login-clean{justify-content:flex-start;padding:max(56px,env(safe-area-inset-top,0px)) 24px calc(env(safe-area-inset-bottom,0px) + 32px)}
    .login-clean-hero{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding-top:8px}
    .login-clean-cta{display:flex;flex-direction:column;gap:14px;align-items:stretch}
    .login-clean-cta .btn{width:100%}
    /* Use compound selector to outrank the later .login-logo rule which would
       otherwise override the gradient via source-order tie-breaking. */
    .login-logo.login-logo-lg{
      width:72px;height:72px;border-radius:22px;
      font-size:34px;letter-spacing:-.01em;margin-bottom:6px;
      /* Subtle vertical gradient + inset highlight give the mark depth at large size. */
      background:linear-gradient(180deg, color-mix(in srgb, var(--primary) 92%, white 8%), var(--primary));
      box-shadow:0 10px 28px rgba(0,0,0,.12), inset 0 1px 0 rgba(255,255,255,.10);
    }
    [data-theme="dark"] .login-logo.login-logo-lg{
      background:linear-gradient(180deg, color-mix(in srgb, var(--primary) 90%, black 10%), var(--primary));
      box-shadow:0 10px 28px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.04);
    }
    .login-brand-name-lg{font-size:32px;font-weight:700;letter-spacing:-.02em;color:var(--text)}
    .login-tagline{font-size:16px;color:var(--text-secondary);margin:4px 0 0;max-width:280px;line-height:1.4}
    .login-fineprint{font-size:12px;color:var(--text-tertiary);text-align:center;margin:4px 0 0;line-height:1.5}
    /* Host-vs-guest note + guest join block on the clean login screen. */
    .login-note{display:flex;gap:8px;align-items:flex-start;background:var(--bg-subtle);border-radius:var(--radius-md);padding:10px 12px;text-align:left}
    .login-note .login-note-icon{flex-shrink:0;margin-top:1px;color:var(--text-tertiary)}
    .login-note span{font-size:12.5px;color:var(--text-secondary);line-height:1.45}
    .login-join{display:flex;flex-direction:column;gap:10px;text-align:left}
    .login-join-label{font-size:13px;color:var(--text-secondary)}
    .login-or{display:flex;align-items:center;gap:10px;color:var(--text-tertiary);font-size:12px;margin:2px 0}
    .login-or::before,.login-or::after{content:"";flex:1;height:1px;background:var(--border)}
    /* In-app QR scanner overlay (Step 3) — always a dark camera screen. */
    .qr-scan-backdrop{position:fixed;inset:0;z-index:200;background:#000;display:none;flex-direction:column;align-items:center;justify-content:center;padding:max(24px,env(safe-area-inset-top,0px)) 20px calc(env(safe-area-inset-bottom,0px) + 24px)}
    .qr-scan-backdrop.active{display:flex}
    .qr-scan-panel{width:100%;max-width:420px;display:flex;flex-direction:column;align-items:center;gap:16px;position:relative}
    .qr-scan-close{position:absolute;top:0;right:0;width:40px;height:40px;border-radius:var(--radius-pill);border:none;background:rgba(255,255,255,.16);color:#fff;font-size:18px;line-height:1;cursor:pointer}
    .qr-scan-title{color:#fff;font-size:18px;font-weight:600;margin-top:2px}
    .qr-scan-video-wrap{width:100%;max-width:320px;aspect-ratio:1;border-radius:20px;overflow:hidden;background:#111}
    #qr-scan-video{width:100%;height:100%;object-fit:cover;display:block}
    .qr-scan-hint{color:rgba(255,255,255,.82);font-size:14px;text-align:center;line-height:1.45;max-width:300px}
    .login-brand{display:flex;align-items:center;gap:10px;margin-bottom:48px}
    .login-logo{width:36px;height:36px;border-radius:10px;background:var(--primary);color:var(--on-primary);
      display:flex;align-items:center;justify-content:center;font-weight:700}
    /* Inline SVG mark inside .login-logo / .login-logo-lg. Inherits color via currentColor
       so it auto-inverts with the theme. The accent dot is a fixed brand green. */
    .login-logo .rl-mark{width:64%;height:64%;display:block}
    .login-logo-lg .rl-mark{width:68%;height:68%}
    .rl-mark text{fill:currentColor}

    /* 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);
      right: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 ===== */
    .room-code-card{
      background:linear-gradient(135deg,#1a1a1a 0%,#3a3a3a 100%);color:#fff;
      border-radius:var(--radius-xl);padding:24px 20px;text-align:center;margin-bottom:24px;position:relative;
    }
    .room-code-label{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.1em;opacity:.7;margin-bottom:8px}
    .room-code-value{font-size:32px;font-weight:700;letter-spacing:.18em;font-feature-settings:"tnum";min-height:38px}
    /* Loading skeleton: while the lobby is fetching the real code, the
       room-code-value is empty. Show a subtle pulsing dash placeholder
       instead of a misleading hardcoded code. The :empty selector stops
       matching the moment openX sets .textContent, so the skeleton
       auto-disappears with no JS toggle needed. */
    .room-code-value:empty::before{
      content:"———— ————";
      opacity:.22;letter-spacing:.18em;
      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){
      .room-code-value:empty::before{animation:none;opacity:.25}
    }
    .room-code-action{position:absolute;top:14px;right:14px;display:flex;gap:8px}
    .room-code-action button{
      background:rgba(255,255,255,.12);color:#fff;border:none;width:36px;height:36px;border-radius:var(--radius-pill);
      display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease;
    }
    .room-code-action button:hover{background:rgba(255,255,255,.2)}
    /* Spin feedback when the refresh button is tapped — fires once, then resets. */
    .room-code-action button.spinning svg{animation:room-refresh-spin .5s ease}
    @keyframes room-refresh-spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}

    .players-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}
    .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)}
    .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)}
    /* Host controls (Batch 2): per-seat kick "×" button + lobby lock toggle.
       The kick button is a flex child appended to a claimed-by-other seat tile
       (.player-tile / .liar-seat are display:flex rows), so it sits at the right
       edge with no positioning hacks. Shown only to the host (server-enforced). */
    .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-left: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}
    /* Hot Seat — seat claim tiles */
    .hot-seat-tile{cursor:default;transition:all .15s ease;border:1.5px solid var(--border-strong)}
    .hot-seat-tile.unclaimed{cursor:pointer;opacity:.85;background:var(--bg-subtle)}
    .hot-seat-tile.unclaimed:hover{border-color:var(--text);opacity:1;transform:translateY(-1px)}
    .hot-seat-tile.claimed-by-me{border-color:var(--success);background:var(--success-soft)}
    .hot-seat-tile.claimed-by-other{opacity:.95}
    .hot-seat-tile .player-tile-status{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-secondary);margin-left:auto}
    .hot-seat-tile.claimed-by-me .player-tile-status{color:var(--success)}
    .hot-seat-tile.unclaimed .player-tile-status{color:var(--text-tertiary)}
    .hot-seat-tile .pulse-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--text-tertiary);animation:hotPulseDot 1.2s ease-in-out infinite}
    @keyframes hotPulseDot{0%,100%{opacity:.3;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}
    /* Empty seat = invite tile (Hot Seat + Chameleon). Mirrors .liar-seat-invite. */
    .hot-seat-tile.invite-tile{
      cursor:pointer;border-style:dashed;border-color:var(--border-strong);
      background:var(--bg);color:var(--text-secondary);opacity:1;
    }
    .hot-seat-tile.invite-tile:hover{border-style:solid;border-color:var(--text);background:var(--bg-subtle);color:var(--text);transform:translateY(-1px)}
    .hot-seat-tile.invite-tile .player-tile-name{color:var(--text-secondary);font-weight:600}
    .hot-seat-tile.invite-tile:hover .player-tile-name{color:var(--text)}
    .hot-seat-tile.invite-tile .invite-plus{
      width:32px;height:32px;border-radius:50%;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:18px;font-weight:600;line-height:1;
    }
    .hot-seat-tile.invite-tile:hover .invite-plus{background:var(--bg);color:var(--text)}
    /* Header row above the player grid: title left, Reset/Leave buttons right */
    .lobby-players-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 6px}
    .lobby-players-header .section-title{margin:0}
    .lobby-players-header-actions{display:flex;gap:6px;align-items:center}
    .lobby-players-header-actions button{
      background:none;border:none;cursor:pointer;font:inherit;
      font-size:13px;font-weight:600;letter-spacing:.01em;
      padding:6px 10px;border-radius:var(--radius-sm);
      color:var(--text-secondary);transition:background .15s ease,color .15s ease;
    }
    .lobby-players-header-actions button:hover{background:var(--bg-subtle);color:var(--text)}
    .lobby-players-header-actions .lobby-leave{color:var(--danger)}
    .lobby-players-header-actions .lobby-leave:hover{background:var(--danger-soft);color:var(--danger)}
    .hot-seats-hint{text-align:center;font-size:12px;color:var(--text-secondary);margin:8px 0 14px;line-height:1.45;font-style:italic}

    /* In-game corner Leave button. Lives in header right slot on screens with a header,
       and absolute-positioned on full-screen splashes (cham-splash, liar-tablecard).
       Resting state is subtle (text-secondary) so it doesn't compete with the screen
       content; on hover/active it turns danger to telegraph the destructive consequence
       before tap. iOS HIG: destructive exit is a labelled control, not the back chevron. */
    .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)}
    .splash-leave-btn{
      position:absolute;
      top:max(16px, env(safe-area-inset-top));
      left:16px;
      z-index:2;
      width:40px;height:40px;
      display:flex;align-items:center;justify-content:center;
      background:transparent;border:none;border-radius:10px;
      color:var(--text);
      cursor:pointer;padding:0;
    }
    .splash-leave-btn svg{stroke-width:2.25}
    .splash-leave-btn:hover,.splash-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;
    }

    /* ===== Game play ===== */
    .play-screen{background:var(--bg);min-height:100vh;display:flex;flex-direction:column;padding:0}
    .play-header{
      display:flex;justify-content:space-between;align-items:center;
      padding:14px 16px;border-bottom:1px solid var(--border);
    }
    .play-stat{display:flex;flex-direction:column;align-items:center;font-size:12px;color:var(--text-secondary);font-weight:500}
    .play-stat strong{font-size:15px;color:var(--text);font-weight:700;line-height:1;display:inline-block;transform-origin:center}
    .play-stat strong.flash-up{animation:score-bump .45s ease}
    @keyframes score-bump{
      0%{transform:scale(1);color:var(--text)}
      40%{transform:scale(1.45);color:var(--success)}
      100%{transform:scale(1);color:var(--text)}
    }
    #skips-left{display:inline-block;transition:color .2s ease}
    #skips-left.flash{animation:skip-bump .45s ease}
    @keyframes skip-bump{
      0%{transform:scale(1);color:var(--text-secondary)}
      40%{transform:scale(1.35);color:var(--danger)}
      100%{transform:scale(1);color:var(--text-secondary)}
    }
    .word-card.flash-correct{animation:card-correct .55s ease}
    @keyframes card-correct{
      0%{background:var(--bg);border-color:var(--border);transform:scale(1)}
      25%{background:#e6f5e7;border-color:var(--success);transform:scale(1.03)}
      100%{background:var(--bg);border-color:var(--border);transform:scale(1)}
    }
    .word-card.flash-skip{animation:card-skip .55s ease}
    @keyframes card-skip{
      0%{background:var(--bg);border-color:var(--border);transform:scale(1)}
      25%{background:#fdf0eb;border-color:var(--danger);transform:scale(1.02)}
      100%{background:var(--bg);border-color:var(--border);transform:scale(1)}
    }
    .feedback-emoji{font-size:48px;line-height:1;margin:6px 0}
    .feedback-label{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.08em}
    .feedback-label.correct{color:var(--success)}
    .feedback-label.skip{color:var(--danger)}
    .feedback-hint{font-size:13px;color:var(--text-secondary);margin-top:4px}

    /* ===== Simplified play screen ===== */
    .role-hero{
      display:flex;flex-direction:column;align-items:center;text-align:center;
      padding:24px 16px;max-width:340px;
    }
    .role-hero-emoji{font-size:80px;line-height:1;margin-bottom:18px;animation:hero-pop .55s cubic-bezier(.34,1.56,.64,1) both}
    @keyframes hero-pop{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}
    .role-hero-title{
      font-size:30px;font-weight:800;letter-spacing:-.02em;margin-bottom:14px;line-height:1.1;
    }
    .role-hero-sub{font-size:15px;color:var(--text-secondary);line-height:1.5;max-width:300px}
    .role-hero-help{
      margin-top:22px;
      display:inline-flex;align-items:center;gap:6px;
      background:var(--bg);
      border:1px solid var(--border);
      color:var(--text-secondary);
      font-size:13px;font-weight:600;
      padding:8px 16px;
      border-radius:var(--radius-pill);
      cursor:pointer;
      transition:all .15s ease;
    }
    .role-hero-help:hover{
      color:var(--text);
      border-color:var(--text);
      background:var(--bg-subtle);
    }
    .role-hero-help svg{width:12px;height:12px;flex-shrink:0}
    .word-text-big{
      font-size:46px;font-weight:800;letter-spacing:-.02em;text-transform:uppercase;
      color:var(--text);line-height:1.05;margin:6px 0 16px;
    }
    .word-label-big{
      font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;
      color:var(--text-secondary);margin-bottom:8px;
    }
    .btn-give-up{background:#fff;border:1.5px solid var(--border-strong);color:var(--text)}
    .btn-give-up:hover{background:#fdf0eb;border-color:var(--danger);color:var(--danger)}
    .btn-got-it{background:var(--success);color:#fff;border:1.5px solid var(--success)}
    .btn-got-it:hover{background:#007a04;border-color:#007a04}

    /* ===== Simplified coach overlay — single info card ===== */
    .coach-info{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      background:#fff;color:var(--text);
      padding:24px 22px;border-radius:var(--radius-lg);
      max-width:320px;width:calc(100% - 48px);
      box-shadow:0 10px 28px rgba(0,0,0,.4);
      animation:coach-pop .3s ease both;
    }
    @keyframes coach-pop{from{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
    .coach-info-title{
      font-size:17px;font-weight:700;margin-bottom:16px;text-align:center;letter-spacing:-.01em;
    }
    .coach-info-row{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px}
    .coach-info-row:last-child{margin-bottom:0}
    .coach-info-icon{font-size:22px;flex-shrink:0;line-height:1.2}
    .coach-info-text{flex:1;color:var(--text-secondary);font-size:13px;line-height:1.5}
    .coach-info-text strong{color:var(--text);font-weight:700}
    .coach-dismiss-new{
      display:block;margin:18px auto 0;
      background:var(--primary);color:var(--on-primary);border:none;border-radius:var(--radius-pill);
      padding:12px 24px;font-weight:700;font-size:14px;cursor:pointer;
    }
    .coach-dismiss-new:hover{background:var(--primary-hover)}

    /* ===== Role-specific coach marks ===== */
    .coach-tip-arrow{
      position:absolute;left:50%;transform:translateX(-50%);
      background:var(--text);color:var(--bg);
      padding:12px 14px;border-radius:10px;
      font-size:13px;font-weight:500;line-height:1.45;
      max-width:260px;width:calc(100% - 60px);
      box-shadow:0 8px 18px rgba(0,0,0,.35);
      text-align:center;
    }
    .coach-tip-arrow strong{font-weight:700}
    .coach-tip-arrow::after{
      content:"";position:absolute;bottom:-9px;left:50%;transform:translateX(-50%);
      width:0;height:0;
      border-left:8px solid transparent;border-right:8px solid transparent;
      border-top:10px solid var(--text);
    }
    .coach-pos-top{top:88px}
    .coach-pos-bottom{bottom:118px}
    .coach-dismiss-arrow{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      background:#fff;color:var(--text);
      border:none;border-radius:var(--radius-pill);
      padding:13px 26px;font-weight:700;font-size:15px;cursor:pointer;
      box-shadow:0 8px 20px rgba(0,0,0,.35);
      white-space:nowrap;
    }
    .coach-dismiss-arrow:hover{transform:translate(-50%,-50%) scale(1.03)}
    @keyframes coach-tip-in-top{
      from{opacity:0;transform:translateX(-50%) translateY(-12px)}
      to{opacity:1;transform:translateX(-50%) translateY(0)}
    }
    @keyframes coach-tip-in-bottom{
      from{opacity:0;transform:translateX(-50%) translateY(12px)}
      to{opacity:1;transform:translateX(-50%) translateY(0)}
    }
    @keyframes coach-dismiss-in{
      from{opacity:0;transform:translate(-50%,-50%) scale(.85)}
      to{opacity:1;transform:translate(-50%,-50%) scale(1)}
    }
    .coach-overlay.active .coach-pos-top{animation:coach-tip-in-top .4s .1s ease both}
    .coach-overlay.active .coach-pos-bottom{animation:coach-tip-in-bottom .4s .2s ease both}
    .coach-overlay.active .coach-dismiss-arrow{animation:coach-dismiss-in .35s .35s ease both}

    .view-toggle{
      display:flex;gap:4px;padding:4px;margin:14px 16px 0;background:var(--bg-subtle);border-radius:var(--radius-pill);
    }
    .view-toggle button{
      flex:1;height:32px;border:none;background:transparent;border-radius:var(--radius-pill);
      font-size:12px;font-weight:600;color:var(--text-secondary);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:4px;
    }
    .view-toggle button.active{background:var(--bg);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.06)}

    .play-body{
      flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:24px 24px;
    }

    .timer-ring{
      width:140px;height:140px;border-radius:50%;background:var(--bg-subtle);border:4px solid var(--text);
      display:flex;align-items:center;justify-content:center;
      font-size:42px;font-weight:700;letter-spacing:-.02em;font-feature-settings:"tnum";margin-bottom:24px;
    }
    .timer-ring.warn{border-color:var(--danger);color:var(--danger)}

    .word-card{
      background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-xl);
      padding:32px 24px;margin-bottom:16px;width:100%;max-width:340px;box-shadow:var(--shadow-md);
    }
    .word-label{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--text-secondary);margin-bottom:10px}
    .word-text{font-size:34px;font-weight:800;letter-spacing:-.02em;text-transform:uppercase}
    .word-hidden{
      font-size:18px;font-weight:500;color:var(--text-secondary);padding:24px 0;line-height:1.5
    }
    .word-hint{font-size:13px;color:var(--text-tertiary);margin-top:10px}

    .play-actions{padding:16px 16px calc(env(safe-area-inset-bottom,0px) + 16px);border-top:1px solid var(--border);display:flex;gap:10px}
    .play-actions .btn{flex:1;height:56px;font-size:16px;border-radius:var(--radius-lg)}
    .skip-info{font-size:12px;color:var(--text-tertiary);text-align:center;margin-top:8px}

    /* ===== Result ===== */
    .result-hero{padding:32px 16px 8px;text-align:center}
    .result-emoji{font-size:48px;margin-bottom:8px}
    .result-title{font-size:24px;font-weight:700;letter-spacing:-.02em;margin-bottom:4px}
    .result-sub{color:var(--text-secondary)}
    .result-score{
      display:inline-flex;align-items:baseline;gap:6px;margin:20px auto 8px;
      background:var(--bg-subtle);border-radius:var(--radius-pill);padding:8px 18px;
    }
    .result-time{
      display:inline-flex;align-items:center;gap:6px;
      margin-top:14px;
      padding:8px 16px;
      background:var(--bg-subtle);
      border-radius:var(--radius-pill);
      font-size:13px;font-weight:600;color:var(--text-secondary);
    }
    .result-score-num{font-size:32px;font-weight:800;letter-spacing:-.02em}
    .result-score-label{font-size:13px;color:var(--text-secondary)}
    .word-list{margin:20px 0;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}
    .word-list-item{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--border);font-size:15px}
    .word-list-item:last-child{border-bottom:none}
    .word-list-status{width:24px;height:24px;border-radius:var(--radius-pill);display:flex;align-items:center;justify-content:center;flex-shrink:0}
    .word-list-status.correct{background:#e6f5e7;color:var(--success)}
    .word-list-status.skipped{background:#fde9e4;color:var(--danger)}
    .word-list-text{flex:1;text-transform:capitalize}
    .leaderboard{margin:20px 0;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}
    .lb-row{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border)}
    .lb-row:last-child{border-bottom:none}
    .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"}

    /* Mode setup screen */
    .setting-row{
      display:flex;align-items:center;justify-content:space-between;gap:12px;
      padding:14px 16px;border-bottom:1px solid var(--border);background:var(--bg);
    }
    .setting-row:last-child{border-bottom:none}
    .setting-row-label{font-weight:500}
    .seg{display:inline-flex;background:var(--bg-subtle);border-radius:var(--radius-pill);padding:3px}
    .seg button{
      border:none;background:transparent;padding:6px 12px;border-radius:var(--radius-pill);
      font-size:13px;font-weight:600;color:var(--text-secondary);cursor:pointer
    }
    .seg button.active{background:var(--bg);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.06)}

    /* ===== Mode hint card (lobby) ===== */
    /* Shown only when state.mode !== 'classic'. Explains the rule twist inline so
       the player doesn't have to leave the lobby. Soft surface, not a CTA. */
    .mode-hint{
      display:flex;gap:10px;padding:12px 14px;margin:-2px 0 8px;
      background:var(--bg-subtle);border:1px solid var(--border);border-radius:var(--radius-md);
      font-size:13px;line-height:1.45;color:var(--text-secondary);
    }
    .mode-hint-icon{font-size:18px;line-height:1.2;flex-shrink:0}
    .mode-hint b{color:var(--text);font-weight:600}

    /* ===== In-play mode pill ===== */
    /* Sits just under the role hero text on the play screen so players are reminded
       of the active mode rule mid-round. Soft, low-emphasis, never blocks gameplay. */
    .play-mode-pill{
      display:inline-flex;align-items:center;gap:6px;
      padding:6px 12px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:12px;font-weight:600;margin-top:8px;
      border:1px solid var(--border);
    }
    .play-mode-pill .mp-icon{font-size:14px;line-height:1}

    /* ===== The Chameleon — game card on Games tab ===== */
    /* Two distinct game tiles need distinct gradient personalities. Chameleon goes warmer
       (terracotta) vs Hot Seat's neutral dark. */
    .hotseat-thumb.chameleon{background:linear-gradient(135deg,#7a3d2a 0%,#a55a3e 100%)}
    [data-theme="dark"] .hotseat-thumb.chameleon{background:linear-gradient(135deg,#5d2d20 0%,#7a3d2a 100%)}

    /* ===== Chameleon lobby + play screens ===== */
    /* Banner above the grid showing the topic name + flavour icon. Big and obvious so the
       category is the first thing players read when the screen loads. */
    .cham-topic-banner{
      display:flex;align-items:center;gap:12px;
      padding:14px 16px;margin-bottom:14px;
      background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);
    }
    .cham-topic-banner-emoji{font-size:28px;line-height:1;flex-shrink:0}
    .cham-topic-banner-text{flex:1;min-width:0}
    .cham-topic-banner-label{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-tertiary);margin-bottom:2px}
    .cham-topic-banner-name{font-size:18px;font-weight:700;letter-spacing:-.01em;color:var(--text)}

    /* The 4×4 word grid. Cells use clamp() so long Turkish words shrink gracefully instead
       of overflowing the cell. Border-only cells keep visual weight light at this density. */
    .cham-grid{
      display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:14px;
    }
    .cham-grid-cell{
      display:flex;align-items:center;justify-content:center;
      aspect-ratio:1;padding:6px 4px;box-sizing:border-box;
      background:var(--bg);border:1px solid var(--border);border-radius:10px;
      font-size:clamp(10px, 2.6vw, 13px);font-weight:600;line-height:1.15;
      text-align:center;color:var(--text);word-break:break-word;
      transition:transform .12s ease, border-color .15s ease, background .15s ease;
    }
    /* The secret word — only highlighted for Players, not the Chameleon. Gold-ish accent so
       it pops on both light and dark surfaces. */
    .cham-grid-cell.secret{
      background:#fff6dc;border-color:#e9b800;color:#7a5a10;font-weight:800;
      box-shadow:0 0 0 2px rgba(233,184,0,.25);
    }
    [data-theme="dark"] .cham-grid-cell.secret{
      background:#332a14;border-color:#e9b800;color:#ffd966;
      box-shadow:0 0 0 2px rgba(233,184,0,.35);
    }

    /* Role banner — persistent reminder of role during the hint phase. Neutral (no color
       tint) so the text + emoji do the work, not the background. Body is medium-weight (500)
       per typography convention — only the role keyword (e.g. "Chameleon") is bold for
       emphasis, so the user's eye lands on what matters. */
    .cham-role-banner{
      display:flex;align-items:center;gap:10px;
      padding:12px 14px;margin-bottom:10px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);
      font-size:14px;font-weight:500;line-height:1.4;color:var(--text);
    }
    .cham-role-banner b{font-weight:700}
    .cham-role-banner-emoji{font-size:20px;line-height:1;flex-shrink:0}

    /* Inline instruction strip between the grid and the action button. */
    .cham-instruction{
      display:flex;gap:10px;padding:12px 14px;margin-bottom:14px;
      background:var(--bg-subtle);border-radius:var(--radius-md);
      font-size:13px;line-height:1.45;color:var(--text-secondary);
    }
    .cham-instruction-icon{font-size:18px;line-height:1.2;flex-shrink:0}
    .cham-instruction b{color:var(--text);font-weight:600}

    /* Role splash variant for the Chameleon — distinct from the regular Player splash so
       the role hits immediately. Uses the existing .splash chrome from Hot Seat. */
    .cham-splash-emoji{font-size:84px;line-height:1;margin-bottom:18px}
    .cham-splash-chameleon{color:#e88a4a}
    [data-theme="dark"] .cham-splash-chameleon{color:#ffa666}

    /* "Your job" callout on the splash. Neutral surface, bold text — colour was removed
       because the role is conveyed by the title + emoji above, not the callout's tint. */
    .cham-splash-job{
      display:flex;flex-direction:column;gap:6px;align-items:center;
      max-width:320px;margin:18px auto 14px;padding:14px 16px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);color:var(--text);text-align:center;
    }
    .cham-splash-job-label{
      font-size:10px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
      color:var(--text-secondary);
    }
    /* Body text is medium-weight (500), not bold. Only the "one word" emphasis (wrapped in <b>
       in the i18n string) is heavy — that's where the user's eye should land. */
    .cham-splash-job-text{
      font-size:14px;font-weight:500;line-height:1.45;
    }
    .cham-splash-job-text b{font-weight:700}

    /* Voting screen — grid of player tiles. 2 columns at 375px, breathable touch targets. */
    .cham-vote-grid{
      display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:14px;
    }
    .cham-vote-tile{
      display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
      padding:16px 10px;background:var(--bg);
      border:1px solid var(--border);border-radius:var(--radius-md);
      cursor:pointer;transition:transform .12s ease, border-color .15s ease;
    }
    .cham-vote-tile:hover{border-color:var(--text);transform:translateY(-1px)}
    .cham-vote-tile.selected{border-color:var(--text);background:var(--bg-subtle);box-shadow:inset 0 0 0 1px var(--text)}
    .cham-vote-tile-name{font-size:13px;font-weight:600;color:var(--text);text-align:center;line-height:1.2}

    /* Vote tally row — shows each player + how many votes they received. */
    .cham-tally-row{
      display:flex;align-items:center;gap:12px;
      padding:10px 14px;margin-bottom:6px;
      background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);
    }
    .cham-tally-row.chameleon{background:var(--winner-bg);border-color:var(--winner-text);color:var(--winner-text)}
    .cham-tally-name{flex:1;font-size:14px;font-weight:600}
    .cham-tally-votes{font-size:12px;font-weight:700;letter-spacing:.04em;color:var(--text-secondary);text-transform:uppercase}
    .cham-tally-row.chameleon .cham-tally-votes{color:var(--winner-text)}

    /* Tiny descriptive caption shown under a section-title to explain what's in the list.
       Stops the user from confusing two similar player-row lists on the result screen. */
    .cham-section-sub{
      font-size:12px;color:var(--text-tertiary);margin-bottom:8px;line-height:1.35;
    }

    /* Result hero — emoji + outcome text + secret reveal. Mirrors Hot Seat's result hero. */
    .cham-result-secret{
      display:inline-flex;align-items:center;gap:8px;padding:8px 14px;margin-top:10px;
      background:var(--bg-subtle);border-radius:var(--radius-pill);
      font-size:13px;font-weight:600;color:var(--text-secondary);
    }
    .cham-result-secret b{color:var(--text);font-weight:700;letter-spacing:.02em}

    /* ===== Liar's Cup (bluffing card game inspired by Liar's Bar) =====
       The "Russian roulette" of the source is replaced with an "unlucky cup"
       (a cocktail glass) that fits Huddle's cafe vibe. Mechanic is identical:
       6 chambers, X are "spill" (start 1, +1 each survived sip).
       Single-device pass-the-phone — each player's hand is hidden when passing. */

    /* Game card thumb */
    .hotseat-thumb.liar{background:linear-gradient(135deg,#7c2d12 0%,#b91c1c 100%)}
    .hotseat-thumb.mafia{background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%)}

    /* Table-card splash + reminder pill */
    .liar-tablecard-splash{
      background:linear-gradient(135deg,#7c2d12 0%,#b91c1c 100%);
      color:#fff;border-radius:var(--radius-lg);padding:26px 22px;
      text-align:center;margin:18px 0;box-shadow:var(--shadow-lg);
    }
    .liar-tablecard-splash-label{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;opacity:.85;margin-bottom:10px}
    .liar-tablecard-splash-icon{font-size:64px;line-height:1;margin-bottom:8px}
    .liar-tablecard-splash-name{font-size:34px;font-weight:900;letter-spacing:-.01em;line-height:1.1}
    .liar-tablecard-splash-sub{font-size:13px;opacity:.9;margin-top:8px;line-height:1.45}

    .liar-tablecard-pill{
      display:inline-flex;align-items:center;gap:6px;padding:6px 12px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-pill);font-size:13px;font-weight:600;color:var(--text);
    }
    .liar-tablecard-pill-icon{font-size:16px;line-height:1}
    .liar-tablecard-pill-strong{font-weight:800;letter-spacing:.02em}

    /* The card visual */
    .liar-card{
      position:relative;width:54px;height:78px;border-radius:8px;
      background:var(--surface);border:1.5px solid var(--border-strong);
      box-shadow:0 1px 3px rgba(0,0,0,.08);
      display:flex;align-items:center;justify-content:center;
      font-weight:800;letter-spacing:-.01em;color:var(--text);
      user-select:none;-webkit-user-select:none;
      transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease;
      cursor:pointer;flex-shrink:0;
    }
    .liar-card-rank{font-size:28px;line-height:1}
    .liar-card-suit{position:absolute;top:4px;left:5px;font-size:11px;font-weight:700;line-height:1}
    .liar-card-suit-br{position:absolute;bottom:4px;right:5px;font-size:11px;font-weight:700;line-height:1;transform:rotate(180deg)}
    .liar-card.joker{background:linear-gradient(135deg,#fef3c7 0%,#fcd34d 100%);color:#78350f;border-color:#fbbf24}
    [data-theme="dark"] .liar-card.joker{background:linear-gradient(135deg,#451a03 0%,#78350f 100%);color:#fbbf24;border-color:#92400e}
    .liar-card.joker .liar-card-rank{font-size:32px}
    .liar-card.face-down{
      background:linear-gradient(135deg,#7c2d12 0%,#b91c1c 100%);
      color:transparent;border-color:#9a3412;
    }
    .liar-card.selected{transform:translateY(-10px);border-color:var(--text);box-shadow:0 4px 14px rgba(0,0,0,.18)}
    .liar-card.revealed-truth{border-color:var(--success);box-shadow:0 0 0 3px var(--success-soft)}
    .liar-card.revealed-lie{border-color:var(--danger);box-shadow:0 0 0 3px var(--danger-soft)}

    /* ===== CARD STYLE VARIANTS — switched via body.card-style-X =====
       Each variant restyles BOTH the hand cards (.liar-card) and the reveal
       flip-card faces (.liar-flip-front / .liar-flip-back) so the look stays
       consistent across the screen. Toggled by liarSetCardStyle(name). */

    /* === 1. CLASSIC CASINO — refined white with gold accents === */
    body.card-style-classic .liar-card,
    body.card-style-classic .liar-flip-front{
      background:linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      border:1.5px solid #c9a227;
      box-shadow:0 2px 6px rgba(0,0,0,.14), inset 0 1px 0 rgba(255,255,255,.7);
      color:#1a1a1a;
    }
    body.card-style-classic .liar-card-rank,
    body.card-style-classic .liar-flip-front .liar-card-rank{
      font-size:28px;font-weight:900;letter-spacing:-.02em;color:#111;
    }
    body.card-style-classic .liar-card-suit,
    body.card-style-classic .liar-card-suit-br,
    body.card-style-classic .liar-flip-front .liar-card-suit,
    body.card-style-classic .liar-flip-front .liar-card-suit-br{color:#a07310;font-weight:800}
    /* Classic front only — back is controlled separately by body.card-back-X. */

    /* === 2. ONYX & GOLD — deep black with bright gold rank === */
    body.card-style-onyx .liar-card,
    body.card-style-onyx .liar-flip-front{
      background:linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%);
      border:1.5px solid #fbbf24;
      box-shadow:0 3px 8px rgba(0,0,0,.55), inset 0 0 0 1px rgba(251,191,36,.25);
      color:#fbbf24;
    }
    body.card-style-onyx .liar-card-rank,
    body.card-style-onyx .liar-flip-front .liar-card-rank{
      font-size:28px;font-weight:900;color:#fbbf24;
      text-shadow:0 1px 2px rgba(0,0,0,.7);
    }
    body.card-style-onyx .liar-card-suit,
    body.card-style-onyx .liar-card-suit-br,
    body.card-style-onyx .liar-flip-front .liar-card-suit,
    body.card-style-onyx .liar-flip-front .liar-card-suit-br{color:#fbbf24;opacity:.85}
    /* Onyx front only — back is controlled separately by body.card-back-X. */

    /* === 3. SNOWFLAKE — minimalist pure white, just the rank === */
    body.card-style-minimal .liar-card,
    body.card-style-minimal .liar-flip-front{
      background:#ffffff;
      border:none;
      border-radius:12px;
      box-shadow:0 6px 16px rgba(0,0,0,.12), 0 1px 3px rgba(0,0,0,.08);
      color:#0a0a0a;
    }
    body.card-style-minimal .liar-card-rank,
    body.card-style-minimal .liar-flip-front .liar-card-rank{
      font-size:34px;font-weight:800;letter-spacing:-.03em;
    }
    body.card-style-minimal .liar-card-suit,
    body.card-style-minimal .liar-card-suit-br,
    body.card-style-minimal .liar-flip-front .liar-card-suit,
    body.card-style-minimal .liar-flip-front .liar-card-suit-br{display:none}
    /* Minimal front only — back is controlled separately by body.card-back-X. */

    /* === 4. AURORA — vivid colorful gradient with white rank === */
    body.card-style-aurora .liar-card,
    body.card-style-aurora .liar-flip-front{
      background:linear-gradient(135deg, #4f46e5 0%, #db2777 50%, #f59e0b 100%);
      border:1.5px solid rgba(255,255,255,.4);
      box-shadow:0 4px 12px rgba(76,46,229,.4);
      color:#ffffff;
    }
    body.card-style-aurora .liar-card-rank,
    body.card-style-aurora .liar-flip-front .liar-card-rank{
      font-size:30px;font-weight:900;color:#fff;
      text-shadow:0 2px 4px rgba(0,0,0,.35), 0 0 16px rgba(255,255,255,.3);
    }
    body.card-style-aurora .liar-card-suit,
    body.card-style-aurora .liar-card-suit-br,
    body.card-style-aurora .liar-flip-front .liar-card-suit,
    body.card-style-aurora .liar-flip-front .liar-card-suit-br{color:rgba(255,255,255,.9)}
    /* Aurora front only — back is controlled separately by body.card-back-X. */

    /* === 5. MONO BOLD — high-contrast modern, black w/ white frame === */
    body.card-style-mono .liar-card,
    body.card-style-mono .liar-flip-front{
      background:#0a0a0a;
      border:3px solid #ffffff;
      border-radius:6px;
      box-shadow:0 3px 10px rgba(0,0,0,.4);
      color:#ffffff;
    }
    body.card-style-mono .liar-card-rank,
    body.card-style-mono .liar-flip-front .liar-card-rank{
      font-size:36px;font-weight:900;letter-spacing:-.05em;color:#fff;
    }
    body.card-style-mono .liar-card-suit,
    body.card-style-mono .liar-card-suit-br,
    body.card-style-mono .liar-flip-front .liar-card-suit,
    body.card-style-mono .liar-flip-front .liar-card-suit-br{display:none}
    /* Mono front only — back is controlled separately by body.card-back-X. */

    /* ===== CARD BACK DESIGN VARIANTS — switched via body.card-back-X =====
       Applies to both .liar-flip-back (the back-face of a reveal flip card)
       AND .liar-card.face-down (face-down hand cards / pile thumbnails).
       All 5 use the cream-gold palette so they pair with the Classic front. */

    /* === A. PINSTRIPE — diagonal gold pinstripes on cream === */
    body.card-back-pinstripe .liar-flip-back,
    body.card-back-pinstripe .liar-card.face-down{
      background:
        repeating-linear-gradient(45deg, rgba(201,162,39,.45) 0 1px, transparent 1px 10px),
        linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      border:1.5px solid #c9a227;
      color:transparent;
    }

    /* === B. ROYAL — central gold crown emblem on cream === */
    body.card-back-royal .liar-flip-back,
    body.card-back-royal .liar-card.face-down{
      background:linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      border:1.5px solid #c9a227;
      color:transparent;
    }
    body.card-back-royal .liar-flip-back::after,
    body.card-back-royal .liar-card.face-down::after{
      content:"♛";
      position:absolute;inset:0;
      display:flex;align-items:center;justify-content:center;
      font-size:24px;color:#c9a227;
      text-shadow:0 1px 0 rgba(255,255,255,.5);
    }

    /* === C. LATTICE — small gold diamond grid on cream === */
    body.card-back-lattice .liar-flip-back,
    body.card-back-lattice .liar-card.face-down{
      background:
        linear-gradient(45deg, transparent 47%, rgba(201,162,39,.35) 47% 53%, transparent 53%),
        linear-gradient(-45deg, transparent 47%, rgba(201,162,39,.35) 47% 53%, transparent 53%),
        linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      background-size: 12px 12px, 12px 12px, 100% 100%;
      border:1.5px solid #c9a227;
      color:transparent;
    }

    /* === D. SUNBURST — radial gold rays with a central dot on cream === */
    body.card-back-sunburst .liar-flip-back,
    body.card-back-sunburst .liar-card.face-down{
      background:
        repeating-conic-gradient(from 0deg at 50% 50%, rgba(201,162,39,.4) 0deg 4deg, transparent 4deg 12deg),
        radial-gradient(circle at center, rgba(201,162,39,.18) 0%, transparent 60%),
        linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      border:1.5px solid #c9a227;
      color:transparent;
    }
    body.card-back-sunburst .liar-flip-back::after,
    body.card-back-sunburst .liar-card.face-down::after{
      content:"";
      position:absolute;top:50%;left:50%;
      width:10px;height:10px;
      transform:translate(-50%,-50%);
      background:radial-gradient(circle, #fbbf24 0%, #c9a227 100%);
      border-radius:50%;
      box-shadow:0 0 0 2px #f5f1e6, 0 1px 2px rgba(0,0,0,.2);
    }

    /* === E. BORDERED — cream with thick gold double-line inner frame === */
    body.card-back-bordered .liar-flip-back,
    body.card-back-bordered .liar-card.face-down{
      background:linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      border:1.5px solid #c9a227;
      box-shadow:
        inset 0 0 0 2px rgba(255,255,255,.7),
        inset 0 0 0 3px #c9a227,
        inset 0 0 0 4px rgba(255,255,255,.5);
      color:transparent;
    }

    /* Hand strip */
    .liar-hand-wrap{margin:14px -4px 0;padding:0 4px 4px;overflow-x:auto;scrollbar-width:none}
    .liar-hand-wrap::-webkit-scrollbar{display:none}
    .liar-hand{display:flex;gap:6px;padding:14px 4px 6px;justify-content:center;min-height:96px}
    .liar-hand.empty{align-items:center;color:var(--text-tertiary);font-size:13px;font-style:italic}

    /* Pile of face-down played cards */
    .liar-pile-area{
      background:var(--bg-subtle);border:1px dashed var(--border-strong);
      border-radius:var(--radius-md);padding:14px;margin:0 0 14px;text-align:center;
    }
    .liar-pile-label{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-tertiary);margin-bottom:8px}
    .liar-pile-claim{font-size:14px;font-weight:600;color:var(--text);margin-bottom:10px;line-height:1.4}
    .liar-pile-claim strong{font-weight:800}
    .liar-pile-claim .liar-pile-claim-name{color:var(--text-secondary);font-weight:500}
    .liar-pile-empty{font-size:13px;color:var(--text-tertiary);font-style:italic;padding:14px 0}
    .liar-pile-stack{display:flex;justify-content:center;align-items:center;height:88px;position:relative}
    .liar-pile-stack .liar-card{position:absolute}
    .liar-pile-count{
      display:inline-block;margin-top:6px;font-size:11px;color:var(--text-tertiary);
      font-weight:600;letter-spacing:.04em;text-transform:uppercase;
    }

    /* Reveal screen */
    .liar-reveal-hero{text-align:center;margin:14px 0 18px}
    .liar-reveal-label{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--text-tertiary);margin-bottom:8px}
    .liar-reveal-title{font-size:26px;font-weight:900;letter-spacing:-.01em;color:var(--text);line-height:1.15}
    .liar-reveal-sub{font-size:14px;color:var(--text-secondary);margin-top:8px;line-height:1.45}
    .liar-reveal-sub strong{color:var(--text);font-weight:800}
    .liar-reveal-cards{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:18px 0}
    .liar-reveal-cards .liar-card{cursor:default;animation:liarCardFlip .55s ease-out backwards}
    .liar-reveal-cards .liar-card:nth-child(2){animation-delay:.15s}
    .liar-reveal-cards .liar-card:nth-child(3){animation-delay:.3s}
    @keyframes liarCardFlip{
      0%{transform:rotateY(180deg) scale(.6);opacity:0}
      60%{transform:rotateY(0deg) scale(1.08);opacity:1}
      100%{transform:rotateY(0deg) scale(1);opacity:1}
    }
    .liar-verdict{
      display:flex;align-items:center;gap:12px;padding:14px;
      background:var(--bg-subtle);border:1px solid var(--border);border-radius:var(--radius-md);
      margin:14px 0;text-align:left;
    }
    .liar-verdict.lied,.liar-verdict.wrongAccuse{background:var(--danger-soft);border-color:var(--danger)}
    .liar-verdict-emoji{font-size:32px;line-height:1;flex-shrink:0;transition:font-size .45s ease}
    .liar-verdict-text{flex:1;font-size:14px;color:var(--text);line-height:1.45;transition:font-size .45s ease}
    .liar-verdict-text strong{font-weight:800}

    /* ===== Cup-mode transitions on the Truth page =====
       When the cup phase begins, the cards + hero + verdict that explained
       WHY this is happening gently recede so the cup gets visual priority.
       Nothing is removed — context stays visible, just dimmed/shrunk so the
       eye flows naturally down to the cup section that's sliding in. */
    .liar-reveal-hero{transition:opacity .45s ease, transform .45s ease, margin .45s ease;transform-origin:top center}
    .liar-reveal-hero.cup-mode{opacity:.38;transform:scale(.92);margin:8px 0 6px}
    .liar-reveal-cards{transition:transform .5s cubic-bezier(.4,0,.2,1), opacity .5s ease, margin .5s ease;transform-origin:top center}
    .liar-reveal-cards.cup-mode{transform:scale(.78);opacity:.5;margin:4px 0}
    .liar-verdict{transition:padding .45s ease, opacity .45s ease, gap .45s ease, margin .45s ease}
    .liar-verdict.cup-mode{padding:10px 12px;opacity:.72;gap:10px;margin:8px 0}
    .liar-verdict.cup-mode .liar-verdict-emoji{font-size:22px}
    .liar-verdict.cup-mode .liar-verdict-text{font-size:12.5px;line-height:1.4}
    /* Stamp ("BUSTED!" / "WRONG CALL!") also recedes so the cup result lands clean. */
    #liar-reveal-stamp{transition:opacity .45s ease, transform .45s ease;transform-origin:top center}
    #liar-reveal-stamp.cup-mode{opacity:.55;transform:scale(.82)}

    /* The cup section itself — slides up from below with smooth overshoot.
       `aria-hidden` keeps screen readers from announcing it before it's
       visible; `.entering` is added by JS when the cup phase begins. */
    .liar-cup-section{
      margin-top:6px;
      opacity:0;
      transform:translateY(28px);
      transition:opacity .55s ease, transform .55s cubic-bezier(.34,1.56,.64,1);
      pointer-events:none;
      will-change:opacity,transform;
    }
    .liar-cup-section.entering{
      opacity:1;
      transform:translateY(0);
      pointer-events:auto;
    }
    @media (prefers-reduced-motion: reduce){
      .liar-cup-section, .liar-reveal-hero, .liar-reveal-cards, .liar-verdict, #liar-reveal-stamp{
        transition:opacity .2s ease !important;
        transform:none !important;
      }
      .liar-cup-section.entering{transform:none}
    }

    /* Cup mechanic */
    .liar-cup-glass{font-size:96px;line-height:1;filter:drop-shadow(0 4px 8px rgba(0,0,0,.15));transition:transform .3s ease}
    .liar-cup-glass.tilting{animation:liarCupTilt 1.4s ease-in-out}
    @keyframes liarCupTilt{
      0%{transform:rotate(0)}
      30%{transform:rotate(-12deg) translateY(-4px)}
      70%{transform:rotate(8deg)}
      100%{transform:rotate(0)}
    }
    .liar-cup-chambers{display:flex;gap:6px;justify-content:center;flex-wrap:wrap;max-width:240px}
    .liar-cup-chamber{
      width:24px;height:24px;border-radius:50%;
      background:var(--bg-subtle);border:1.5px solid var(--border-strong);
      display:inline-flex;align-items:center;justify-content:center;
      font-size:12px;font-weight:700;color:var(--text-tertiary);
      /* Snappier base transition (.16s instead of .25s) so chambers settle
         back to neutral cleanly during the roulette spin — the previous .25s
         meant multiple chambers were mid-transition simultaneously, blurring
         the highlight handoff. .16s is fast enough to cleanly hand off but
         slow enough to feel smooth, not snapped. */
      transition:transform .16s ease, box-shadow .16s ease, background-color .16s ease, border-color .16s ease, color .16s ease;
    }
    .liar-cup-chamber.spill{background:var(--danger);border-color:var(--danger);color:#fff}
    .liar-cup-chamber.safe{background:var(--success);border-color:var(--success);color:#fff}
    .liar-cup-chamber.revealed{transform:scale(1.15);box-shadow:0 0 0 4px var(--focus-ring)}
    /* Roulette spotlight — used during the spin phase. The picked chamber isn't
       revealed yet (no safe/spill colour) — just a moving highlight that ticks
       through positions like a slot-machine wheel slowing down.
       Transition is intentionally short (.14s) so each tick's highlight LANDS
       cleanly before the next chamber takes over. With the new tick gaps that
       grow from ~100ms to ~340ms, this gives a clear baton-pass feel. */
    .liar-cup-chamber.rolling{
      transform:scale(1.35);
      background:#fff5d6;border-color:#e9a857;color:#a06b1c;
      box-shadow:0 0 0 3px rgba(233,168,87,.4),0 0 16px rgba(255,180,40,.6);
      transition:transform .14s cubic-bezier(.34,1.56,.64,1), box-shadow .14s ease, background-color .14s ease, border-color .14s ease, color .14s ease;
    }
    [data-theme="dark"] .liar-cup-chamber.rolling{
      background:#3a2d12;border-color:#f5c451;color:#f5c451;
      box-shadow:0 0 0 3px rgba(245,196,81,.3),0 0 18px rgba(245,196,81,.6);
    }
    /* Settle pulse — applied to the FINAL chamber the roulette lands on,
       during the 500ms held-pause phase. The chamber breathes once to mark
       "this is it" before the cup tilts to drink. */
    .liar-cup-chamber.rolling.settle{
      animation: liarChamberSettle 0.55s cubic-bezier(.4,0,.2,1) 1;
    }
    @keyframes liarChamberSettle{
      0%   { transform:scale(1.35);box-shadow:0 0 0 3px rgba(233,168,87,.4),0 0 16px rgba(255,180,40,.6) }
      35%  { transform:scale(1.55);box-shadow:0 0 0 6px rgba(233,168,87,.5),0 0 26px rgba(255,180,40,.85) }
      100% { transform:scale(1.42);box-shadow:0 0 0 4px rgba(233,168,87,.45),0 0 20px rgba(255,180,40,.7) }
    }
    .liar-cup-chambers-hint{font-size:11px;color:var(--text-tertiary);text-align:center;margin-top:4px;letter-spacing:.04em;text-transform:uppercase;font-weight:600}
    .liar-cup-result{text-align:center;padding:16px;border-radius:var(--radius-md);margin:14px 0;background:var(--bg-subtle);border:1px solid var(--border)}
    .liar-cup-result.safe{background:var(--success-soft);border-color:var(--success)}
    .liar-cup-result.spilled{background:var(--danger-soft);border-color:var(--danger)}
    .liar-cup-result-emoji{font-size:48px;line-height:1;margin-bottom:8px}
    .liar-cup-result-title{font-size:20px;font-weight:900;letter-spacing:-.01em;color:var(--text);margin-bottom:6px}
    .liar-cup-result-text{font-size:14px;color:var(--text);line-height:1.45}

    /* ===== Cup drinking sequence — dramatic animations =====
       Timeline (after the loser taps "Tap to drink"):
         0-200ms:  cup lifts, button fades, suspense begins
         200-2000ms: intensifying wobble + sweat drops + pulse halo
         2000-2400ms: cup tilts to drinking position
         2400-2800ms: hold + chamber blur (the "is it safe?" moment)
         2800ms:   REVEAL — safe burst or spill splash
         3500ms:   result card + continue
       Each device animates independently after seeing sipTaken=true and the
       resolved sipOutcome. State is locked between devices via Supabase
       (everyone sees the result at roughly the same wall-clock time). */

    /* Wrapper that anchors the cup so we can position particles around it. */
    .liar-cup-stage{position:relative;display:flex;flex-direction:column;align-items:center;gap:10px;min-height:170px}
    .liar-cup-stage .liar-cup-glass{transition:transform .25s ease,filter .25s ease;z-index:2;position:relative}

    /* ===== THE VERDICT — gilded wheel of fate (replaces cup visual) =====
       When the cup-stage has .liar-wheel-stage class, the wheel takes over.
       The wheel container is a circular conic-gradient div with a fixed pointer
       at 12 o'clock. JS sets the gradient inline based on cupSpills (N red
       wedges + 6-N green wedges) and rotates the wheel to land on sipChamberIdx. */
    .liar-wheel-stage .liar-cup-glass,
    .liar-wheel-stage .liar-cup-cracks,
    .liar-wheel-stage .liar-puddle,
    .liar-wheel-stage .liar-cup-chambers,
    .liar-wheel-stage .liar-cup-chambers-hint,
    .liar-wheel-stage .liar-cup-aura,
    .liar-wheel-stage .liar-burst-safe,
    .liar-wheel-stage .liar-burst-spill,
    .liar-wheel-stage .liar-cup-sweat{display:none !important}
    .liar-wheel-stage{min-height:240px}

    .liar-wheel-wrap{
      position:relative;width:200px;height:200px;
      margin:8px auto 0;
      transform:translateY(40px) scale(.3);opacity:0;
      transition:transform .7s cubic-bezier(.34,1.56,.64,1), opacity .55s ease;
    }
    .liar-wheel-stage .liar-wheel-wrap{
      transform:translateY(0) scale(1);opacity:1;
    }
    /* Wheel itself — conic-gradient set INLINE by JS. CSS provides border/shadow/shape. */
    .liar-wheel{
      position:relative;
      width:200px;height:200px;border-radius:50%;
      border:6px solid #6b4818;
      box-shadow:
        0 8px 24px rgba(0,0,0,.6),
        0 0 0 4px #fbbf24,
        inset 0 0 0 3px rgba(0,0,0,.35);
      transform:rotate(0deg);
    }
    /* Wedge dividers — 60° radial lines for that real-wheel feel */
    .liar-wheel::before{
      content:"";position:absolute;inset:0;border-radius:50%;
      background:conic-gradient(
        transparent 0deg, transparent 59deg, rgba(0,0,0,.6) 59deg, rgba(0,0,0,.6) 61deg,
        transparent 61deg, transparent 119deg, rgba(0,0,0,.6) 119deg, rgba(0,0,0,.6) 121deg,
        transparent 121deg, transparent 179deg, rgba(0,0,0,.6) 179deg, rgba(0,0,0,.6) 181deg,
        transparent 181deg, transparent 239deg, rgba(0,0,0,.6) 239deg, rgba(0,0,0,.6) 241deg,
        transparent 241deg, transparent 299deg, rgba(0,0,0,.6) 299deg, rgba(0,0,0,.6) 301deg,
        transparent 301deg, transparent 360deg);
      pointer-events:none;
    }
    /* Centre gilded hub */
    .liar-wheel::after{
      content:"";position:absolute;top:50%;left:50%;
      width:38px;height:38px;border-radius:50%;
      background:radial-gradient(circle, #fbbf24 0%, #b8631a 60%, #6b4818 100%);
      transform:translate(-50%,-50%);
      box-shadow:0 0 0 3px #3a2410, 0 4px 8px rgba(0,0,0,.6);
      pointer-events:none;
    }
    .liar-wheel.spinning{
      animation: liarWheelSpin 6.1s cubic-bezier(.08,.7,.12,1) forwards;
    }
    /* JS sets --liar-wheel-target (the final rotation degrees) before adding .spinning */
    @keyframes liarWheelSpin{
      from{transform:rotate(0deg)}
      to  {transform:rotate(var(--liar-wheel-target, 2370deg))}
    }
    /* Pointer triangle at the top of the wheel — wiggles during spin */
    .liar-wheel-pointer{
      position:absolute;top:-14px;left:50%;
      width:0;height:0;
      border-left:14px solid transparent;border-right:14px solid transparent;
      border-top:22px solid #fbbf24;
      filter:drop-shadow(0 2px 4px rgba(0,0,0,.6));
      transform:translateX(-50%);
      z-index:2;pointer-events:none;
    }
    .liar-wheel.spinning ~ .liar-wheel-pointer{
      animation: liarWheelPointerWiggle .12s linear infinite;
    }
    @keyframes liarWheelPointerWiggle{
      0%,100%{transform:translateX(-50%) rotate(0)}
      50%    {transform:translateX(-50%) rotate(-3deg)}
    }
    /* ===== WHEEL STYLE VARIANTS — switched via body.wheel-style-X =====
       Each variant changes the wheel's ring/border, the central hub, and the
       pointer. Wedge colours (red = poison, green = safe) stay intact so the
       game's safe/danger semantics aren't disturbed. */

    /* 1. CASINO — current default-ish: brown ring, gold outer, orange hub */
    body.wheel-style-casino .liar-wheel{
      border:6px solid #6b4818;
      box-shadow:
        0 8px 24px rgba(0,0,0,.6),
        0 0 0 4px #fbbf24,
        inset 0 0 0 3px rgba(0,0,0,.35);
    }
    body.wheel-style-casino .liar-wheel::after{
      background:radial-gradient(circle, #fbbf24 0%, #b8631a 60%, #6b4818 100%);
      box-shadow:0 0 0 3px #3a2410, 0 4px 8px rgba(0,0,0,.6);
      content:"";color:transparent;
    }
    body.wheel-style-casino .liar-wheel-pointer{border-top-color:#fbbf24}

    /* 2. ROYAL — matches the Royal card back: gold ring, cream outer, crown hub */
    body.wheel-style-royal .liar-wheel{
      border:6px solid #c9a227;
      box-shadow:
        0 8px 24px rgba(0,0,0,.55),
        0 0 0 5px #f5f1e6,
        0 0 0 7px #c9a227,
        inset 0 0 0 2px rgba(201,162,39,.5);
    }
    body.wheel-style-royal .liar-wheel::after{
      width:44px;height:44px;
      background:linear-gradient(180deg, #ffffff 0%, #f5f1e6 100%);
      box-shadow:0 0 0 2px #c9a227, 0 4px 8px rgba(0,0,0,.45);
      content:"♛";
      color:#c9a227;
      font-size:22px;font-weight:900;line-height:44px;
      text-align:center;
      text-shadow:0 1px 0 rgba(255,255,255,.5);
    }
    body.wheel-style-royal .liar-wheel-pointer{border-top-color:#c9a227}

    /* 3. NEON — dark bezel with cyan glow + magenta core */
    body.wheel-style-neon .liar-wheel{
      border:6px solid #0f172a;
      box-shadow:
        0 0 24px rgba(6,182,212,.55),
        0 0 0 3px #06b6d4,
        0 0 0 7px rgba(6,182,212,.35),
        inset 0 0 0 2px rgba(6,182,212,.6);
    }
    body.wheel-style-neon .liar-wheel::after{
      background:radial-gradient(circle, #ff00ff 0%, #c026d3 50%, #0f172a 100%);
      box-shadow:
        0 0 0 3px #0f172a,
        0 0 16px rgba(255,0,255,.7),
        0 4px 8px rgba(0,0,0,.5);
      content:"";color:transparent;
    }
    body.wheel-style-neon .liar-wheel-pointer{
      border-top-color:#06b6d4;
      filter:drop-shadow(0 0 6px rgba(6,182,212,.9)) drop-shadow(0 2px 4px rgba(0,0,0,.6));
    }

    /* 4. VINTAGE — dark wood ring, brass outer, antique brass hub */
    body.wheel-style-vintage .liar-wheel{
      border:7px solid #5a3210;
      background-clip:padding-box;
      box-shadow:
        0 6px 20px rgba(0,0,0,.65),
        0 0 0 3px #b08440,
        0 0 0 4px #4a2810,
        inset 0 0 0 2px rgba(0,0,0,.5);
    }
    body.wheel-style-vintage .liar-wheel::after{
      width:40px;height:40px;
      background:radial-gradient(circle at 35% 30%, #f4e4a8 0%, #b08440 55%, #5a3210 100%);
      box-shadow:0 0 0 2px #2f1a08, inset 0 -2px 4px rgba(0,0,0,.4), 0 3px 6px rgba(0,0,0,.5);
      content:"";color:transparent;
    }
    body.wheel-style-vintage .liar-wheel-pointer{border-top-color:#b08440}
    /* Vintage: kill the post-roll wedge shine (.liar-wheel-spotwedge.flash) so
       neither red nor green flashes when the wheel lands. The wedge highlights
       stay visible in the other styles. */
    body.wheel-style-vintage .liar-wheel-spotwedge{
      display:none !important;
    }

    /* ===== NEW GREEN-THEMED VARIANTS — match Huddle's site palette ===== */

    /* 6. WOOD — premium crafted wood frame with multi-stop bevel rings,
       concave bowl shadow inside, polished brass hub, refined pointer.
       The chambers (red/green) keep game semantics; only the frame +
       hub + pointer are premium-styled. */
    body.wheel-style-emerald .liar-wheel{
      /* Inner dark border (the wheel's own border property) — sharp inner edge */
      border:4px solid #2a1810;
      box-shadow:
        /* === atmospheric shadow on the ground === */
        0 18px 36px -8px rgba(0,0,0,.55),
        0 6px 12px rgba(0,0,0,.35),
        /* === outer beveled ring stack (4 concentric ring layers) === */
        /* outer dark walnut */
        0 0 0 3px #3a2410,
        /* mid wood band */
        0 0 0 8px #8b5a2b,
        /* highlight ring (top-light catching brass-tinted wood) */
        0 0 0 10px #c89968,
        /* outermost dark walnut (defines silhouette) */
        0 0 0 13px #1c0f06,
        /* === inner bowl effect (chambers feel recessed) === */
        inset 0 0 32px rgba(0,0,0,.4),
        inset 0 4px 12px rgba(255,220,180,.16),
        inset 0 -4px 12px rgba(0,0,0,.25);
    }
    body.wheel-style-emerald .liar-wheel::after{
      /* Polished brass hub — 48px with metallic highlight + recessed bezel */
      width:48px;height:48px;
      background:
        /* bright highlight spot (top-left light source) */
        radial-gradient(circle at 32% 26%, rgba(255,255,255,.75) 0%, rgba(255,255,255,0) 28%),
        /* main brass dome gradient */
        radial-gradient(circle at 35% 30%, #fef3c7 0%, #fde68a 22%, #d4af37 52%, #92400e 84%, #3a2410 100%);
      box-shadow:
        /* recessed bezel rings */
        0 0 0 2px #2a1810,
        0 0 0 4px #8b5a2b,
        /* hub's own inner shading */
        inset 0 -3px 6px rgba(0,0,0,.45),
        inset 0 2px 3px rgba(255,255,255,.35),
        /* dropshadow under the hub */
        0 6px 12px rgba(0,0,0,.55);
      content:"";color:transparent;
    }
    body.wheel-style-emerald .liar-wheel-pointer{
      /* Refined brass-tipped pointer with layered shadow for definition */
      border-top-color:#d4af37;
      filter:
        drop-shadow(0 0 1px #5a3210)
        drop-shadow(0 1px 2px rgba(0,0,0,.45))
        drop-shadow(0 4px 6px rgba(0,0,0,.55));
    }
    /* Make wedge dividers softer/more premium — replace harsh black radial
       lines with subtle warm-shadow lines that fit the wood theme. */
    body.wheel-style-emerald .liar-wheel::before{
      background:conic-gradient(
        transparent 0deg, transparent 59deg, rgba(58,36,16,.55) 59deg, rgba(58,36,16,.55) 61deg,
        transparent 61deg, transparent 119deg, rgba(58,36,16,.55) 119deg, rgba(58,36,16,.55) 121deg,
        transparent 121deg, transparent 179deg, rgba(58,36,16,.55) 179deg, rgba(58,36,16,.55) 181deg,
        transparent 181deg, transparent 239deg, rgba(58,36,16,.55) 239deg, rgba(58,36,16,.55) 241deg,
        transparent 241deg, transparent 299deg, rgba(58,36,16,.55) 299deg, rgba(58,36,16,.55) 301deg,
        transparent 301deg, transparent 360deg);
    }

    /* 7. MINT — soft glassy mint, clean and light */
    body.wheel-style-mint .liar-wheel{
      border:5px solid #6ee7b7;
      box-shadow:
        0 10px 24px rgba(16,185,129,.18),
        0 0 0 3px #ffffff,
        0 0 0 5px #a7f3d0,
        inset 0 0 0 2px rgba(255,255,255,.7);
    }
    body.wheel-style-mint .liar-wheel::after{
      width:42px;height:42px;
      background:radial-gradient(circle at 35% 30%, #ffffff 0%, #ecfdf5 50%, #a7f3d0 100%);
      box-shadow:0 0 0 2px #6ee7b7, inset 0 -1px 3px rgba(110,231,183,.5), 0 3px 7px rgba(0,0,0,.18);
      content:"";color:transparent;
    }
    body.wheel-style-mint .liar-wheel-pointer{
      border-top-color:#10b981;
      filter:drop-shadow(0 2px 3px rgba(0,0,0,.25));
    }

    /* 8. ROULETTE — classic casino brass + deep felt green */
    body.wheel-style-roulette .liar-wheel{
      border:7px solid #14532d;
      box-shadow:
        0 10px 28px rgba(0,0,0,.55),
        0 0 0 4px #d4af37,
        0 0 0 6px #92400e,
        inset 0 0 0 2px rgba(212,175,55,.45);
    }
    body.wheel-style-roulette .liar-wheel::after{
      width:44px;height:44px;
      background:radial-gradient(circle at 35% 30%, #fef3c7 0%, #fde68a 40%, #d4af37 70%, #92400e 100%);
      box-shadow:0 0 0 3px #14532d, inset 0 -2px 4px rgba(0,0,0,.4), 0 4px 10px rgba(0,0,0,.55);
      content:"";color:transparent;
    }
    body.wheel-style-roulette .liar-wheel-pointer{
      border-top-color:#d4af37;
      filter:drop-shadow(0 2px 4px rgba(0,0,0,.55));
    }

    /* 9. LIME — bold vivid lime, energetic */
    body.wheel-style-lime .liar-wheel{
      border:6px solid #365314;
      box-shadow:
        0 10px 28px rgba(54,83,20,.4),
        0 0 0 4px #a3e635,
        0 0 0 6px #365314,
        inset 0 0 0 2px rgba(163,230,53,.45);
    }
    body.wheel-style-lime .liar-wheel::after{
      width:42px;height:42px;
      background:radial-gradient(circle at 35% 30%, #ecfccb 0%, #bef264 45%, #84cc16 75%, #4d7c0f 100%);
      box-shadow:0 0 0 3px #1a2e05, inset 0 -2px 4px rgba(0,0,0,.3), 0 4px 8px rgba(0,0,0,.45);
      content:"";color:transparent;
    }
    body.wheel-style-lime .liar-wheel-pointer{
      border-top-color:#84cc16;
      filter:drop-shadow(0 2px 4px rgba(0,0,0,.4));
    }

    /* 10. FOREST — dark forest with subtle gold accent, premium dark-mode feel */
    body.wheel-style-forest .liar-wheel{
      border:6px solid #022c22;
      box-shadow:
        0 10px 28px rgba(0,0,0,.7),
        0 0 0 3px #fde68a,
        0 0 0 5px #064e3b,
        inset 0 0 0 2px rgba(110,231,183,.32);
    }
    body.wheel-style-forest .liar-wheel::after{
      width:42px;height:42px;
      background:radial-gradient(circle at 35% 30%, #fef3c7 0%, #fde68a 35%, #92400e 75%, #022c22 100%);
      box-shadow:0 0 0 3px #022c22, inset 0 -2px 4px rgba(0,0,0,.45), 0 4px 10px rgba(0,0,0,.6);
      content:"";color:transparent;
    }
    body.wheel-style-forest .liar-wheel-pointer{
      border-top-color:#fde68a;
      filter:drop-shadow(0 2px 4px rgba(0,0,0,.65));
    }
    /* ===== END NEW GREEN VARIANTS ===== */

    /* 5. MINIMAL — clean thin black ring, small black dot, simple triangle */
    body.wheel-style-minimal .liar-wheel{
      border:2px solid #111;
      box-shadow:0 4px 14px rgba(0,0,0,.2);
    }
    body.wheel-style-minimal .liar-wheel::before{
      background:conic-gradient(
        transparent 0deg, transparent 59.5deg, rgba(0,0,0,.5) 59.5deg, rgba(0,0,0,.5) 60.5deg,
        transparent 60.5deg, transparent 119.5deg, rgba(0,0,0,.5) 119.5deg, rgba(0,0,0,.5) 120.5deg,
        transparent 120.5deg, transparent 179.5deg, rgba(0,0,0,.5) 179.5deg, rgba(0,0,0,.5) 180.5deg,
        transparent 180.5deg, transparent 239.5deg, rgba(0,0,0,.5) 239.5deg, rgba(0,0,0,.5) 240.5deg,
        transparent 240.5deg, transparent 299.5deg, rgba(0,0,0,.5) 299.5deg, rgba(0,0,0,.5) 300.5deg,
        transparent 300.5deg, transparent 360deg);
    }
    body.wheel-style-minimal .liar-wheel::after{
      width:18px;height:18px;
      background:#111;
      box-shadow:none;
      content:"";color:transparent;
    }
    body.wheel-style-minimal .liar-wheel-pointer{
      border-top-color:#111;
      filter:drop-shadow(0 1px 2px rgba(0,0,0,.25));
    }

    /* Spotwedge — highlight on the landed wedge (top, 30°-spread cone). */
    .liar-wheel-spotwedge{
      position:absolute;top:50%;left:50%;
      width:200px;height:200px;border-radius:50%;
      transform:translate(-50%,-50%) scale(1);
      opacity:0;pointer-events:none;z-index:1;
      background:conic-gradient(from -30deg,
        transparent 0deg,
        rgba(255,255,150,.65) 30deg, rgba(255,255,150,.65) 60deg,
        transparent 60deg);
      mask-image:radial-gradient(circle, transparent 25px, #000 26px);
      -webkit-mask-image:radial-gradient(circle, transparent 25px, #000 26px);
    }
    .liar-wheel-spotwedge.flash{animation: liarWheelWedgeFlash 1.2s ease-out forwards}
    @keyframes liarWheelWedgeFlash{
      0%   {opacity:0;transform:translate(-50%,-50%) scale(.95)}
      30%  {opacity:1;transform:translate(-50%,-50%) scale(1.05)}
      100% {opacity:0;transform:translate(-50%,-50%) scale(1.12)}
    }
    .liar-wheel-spotwedge.out{
      background:conic-gradient(from -30deg,
        transparent 0deg,
        rgba(255,80,80,.85) 30deg, rgba(255,80,80,.85) 60deg,
        transparent 60deg);
    }

    /* Big SAFE / OUT stamp that slams in over the wheel */
    .liar-wheel-stamp{
      position:absolute;top:50%;left:50%;
      display:none;
      font-family:Georgia,'Times New Roman',serif;
      font-weight:900;letter-spacing:.22em;
      text-transform:uppercase;
      text-shadow:0 6px 20px rgba(0,0,0,.85), 0 0 24px rgba(0,0,0,.6);
      transform:translate(-50%,-50%);
      z-index:11;white-space:nowrap;font-size:64px;
    }
    .liar-wheel-stamp.show{display:block;animation: liarWheelStampSlam .55s cubic-bezier(.34,1.56,.64,1) forwards}
    .liar-wheel-stamp.safe{color:#4ade80}
    .liar-wheel-stamp.out {color:#f87171}
    @keyframes liarWheelStampSlam{
      0%   {transform:translate(-50%,-50%) scale(3.4) rotate(-3deg);opacity:0}
      55%  {transform:translate(-50%,-50%) scale(.88) rotate(-1deg);opacity:1}
      100% {transform:translate(-50%,-50%) scale(1)   rotate(0);opacity:1}
    }
    .liar-wheel-stamp.hold{animation: liarWheelStampBreath 2s ease-in-out .55s infinite}
    @keyframes liarWheelStampBreath{
      0%,100%{transform:translate(-50%,-50%) scale(1)}
      50%    {transform:translate(-50%,-50%) scale(1.05)}
    }

    @media (prefers-reduced-motion: reduce){
      .liar-wheel-wrap{transition:none;transform:translateY(0) scale(1);opacity:1}
      .liar-wheel.spinning{animation:none;transform:rotate(var(--liar-wheel-target, 0deg))}
      .liar-wheel-pointer,.liar-wheel-spotwedge.flash,
      .liar-wheel-stamp.show,.liar-wheel-stamp.hold{animation:none}
      .liar-wheel-stamp.show{opacity:1}
    }
    /* ===== END THE VERDICT wheel ===== */

    /* Anticipation phase — cup lifts and starts wobbling with a heartbeat halo. */
    .liar-cup-stage.anticipating .liar-cup-glass{
      animation: liarCupWobble 1.8s cubic-bezier(.36,.07,.19,.97) 1;
      transform-origin: 50% 90%;
    }
    @keyframes liarCupWobble{
      0%   { transform:translateY(0)   rotate(0deg);   filter:drop-shadow(0 4px 8px rgba(0,0,0,.15)) }
      6%   { transform:translateY(-6px) rotate(-2deg);  filter:drop-shadow(0 8px 14px rgba(0,0,0,.2)) }
      14%  { transform:translateY(-7px) rotate(3deg);   filter:drop-shadow(0 8px 14px rgba(0,0,0,.2)) }
      24%  { transform:translateY(-5px) rotate(-4deg);  filter:drop-shadow(0 8px 14px rgba(0,0,0,.2)) }
      36%  { transform:translateY(-7px) rotate(5deg);   filter:drop-shadow(0 10px 16px rgba(0,0,0,.22)) }
      50%  { transform:translateY(-6px) rotate(-6deg);  filter:drop-shadow(0 10px 16px rgba(0,0,0,.22)) }
      64%  { transform:translateY(-8px) rotate(7deg);   filter:drop-shadow(0 12px 18px rgba(0,0,0,.24)) }
      78%  { transform:translateY(-6px) rotate(-7deg);  filter:drop-shadow(0 12px 18px rgba(0,0,0,.24)) }
      90%  { transform:translateY(-8px) rotate(6deg);   filter:drop-shadow(0 14px 20px rgba(0,0,0,.26)) }
      100% { transform:translateY(-6px) rotate(0deg);   filter:drop-shadow(0 12px 18px rgba(0,0,0,.24)) }
    }
    /* Pulsing aura behind the cup during anticipation */
    .liar-cup-aura{
      position:absolute;left:50%;top:42%;transform:translate(-50%,-50%);
      width:140px;height:140px;border-radius:50%;pointer-events:none;
      background:radial-gradient(circle,rgba(255,200,80,.36) 0%,rgba(255,160,40,0) 70%);
      opacity:0;z-index:1;
    }
    .liar-cup-stage.anticipating .liar-cup-aura{
      animation: liarCupAuraPulse 0.6s ease-in-out 3;
    }
    @keyframes liarCupAuraPulse{
      0%,100%{opacity:0;transform:translate(-50%,-50%) scale(.85)}
      50%    {opacity:1;transform:translate(-50%,-50%) scale(1.2)}
    }
    /* Sweat-drop emoji that flies off the cup during anticipation */
    .liar-cup-sweat{
      position:absolute;top:18%;left:62%;font-size:18px;line-height:1;
      pointer-events:none;opacity:0;z-index:3;
    }
    .liar-cup-stage.anticipating .liar-cup-sweat{
      animation: liarCupSweat 1.6s ease-in 1 0.2s;
    }
    @keyframes liarCupSweat{
      0%   {opacity:0;transform:translate(0,0) scale(.6)}
      20%  {opacity:1;transform:translate(2px,-2px) scale(1)}
      80%  {opacity:1;transform:translate(8px,28px) scale(1.05)}
      100% {opacity:0;transform:translate(12px,40px) scale(.7)}
    }
    /* Drinking tilt — the cup goes to the mouth */
    .liar-cup-stage.drinking .liar-cup-glass{
      animation: liarCupDrink 0.45s cubic-bezier(.4,0,.2,1) forwards;
    }
    @keyframes liarCupDrink{
      from { transform:translateY(-6px) rotate(0deg) }
      to   { transform:translateY(-14px) rotate(-32deg) }
    }
    /* Reveal pose — held while the chambers settle, before the burst */
    .liar-cup-stage.revealing .liar-cup-glass{
      transform:translateY(-2px) rotate(0deg);
    }

    /* SAFE reveal — green flash + burst particles + confetti */
    .liar-cup-stage.revealing.safe .liar-cup-glass{
      animation: liarCupBounceSafe 0.6s cubic-bezier(.34,1.56,.64,1) 1;
      filter:drop-shadow(0 0 12px rgba(62,197,106,.6)) drop-shadow(0 4px 8px rgba(0,0,0,.15));
    }
    @keyframes liarCupBounceSafe{
      0%  {transform:translateY(-2px) rotate(0)   scale(1)}
      40% {transform:translateY(-14px) rotate(-4deg) scale(1.18)}
      70% {transform:translateY(-4px) rotate(2deg)  scale(1.05)}
      100%{transform:translateY(-2px) rotate(0)   scale(1)}
    }
    .liar-burst-safe{
      position:absolute;left:50%;top:42%;transform:translate(-50%,-50%);
      width:160px;height:160px;border-radius:50%;pointer-events:none;
      background:radial-gradient(circle,rgba(62,197,106,.55) 0%,rgba(62,197,106,0) 65%);
      opacity:0;z-index:1;
    }
    .liar-cup-stage.revealing.safe .liar-burst-safe{
      animation: liarBurstSafe 0.7s ease-out 1;
    }
    @keyframes liarBurstSafe{
      0%  {opacity:0;transform:translate(-50%,-50%) scale(.4)}
      30% {opacity:1;transform:translate(-50%,-50%) scale(1.1)}
      100%{opacity:0;transform:translate(-50%,-50%) scale(2.2)}
    }
    /* Confetti pieces floating up from the cup on safe */
    .liar-confetti-piece{
      position:absolute;left:50%;top:50%;width:8px;height:12px;border-radius:2px;
      pointer-events:none;opacity:0;z-index:3;
      background:var(--confetti-color,#3ec56a);
    }
    .liar-cup-stage.revealing.safe .liar-confetti-piece{
      animation: liarConfettiFly 1s cubic-bezier(.2,.6,.4,1) 1 forwards;
    }
    @keyframes liarConfettiFly{
      0%   {opacity:0;transform:translate(-50%,-50%) rotate(0)}
      10%  {opacity:1}
      100% {opacity:0;transform:translate(calc(-50% + var(--fly-x,0px)),calc(-50% + var(--fly-y,-80px))) rotate(var(--fly-rot,180deg))}
    }

    /* SPILL reveal — red flash + descending droplets + screen shake */
    .liar-cup-stage.revealing.spilled .liar-cup-glass{
      animation: liarCupSpillTilt 0.7s ease-in 1 forwards;
      filter:drop-shadow(0 0 14px rgba(193,53,21,.6)) drop-shadow(0 4px 8px rgba(0,0,0,.18));
    }
    @keyframes liarCupSpillTilt{
      0%  {transform:translateY(-2px) rotate(0)}
      30% {transform:translateY(-4px) rotate(-46deg)}
      55% {transform:translateY(2px)  rotate(-58deg)}
      100%{transform:translateY(6px)  rotate(-52deg)}
    }
    .liar-burst-spill{
      position:absolute;left:50%;top:46%;transform:translate(-50%,-50%);
      width:200px;height:200px;border-radius:50%;pointer-events:none;
      background:radial-gradient(circle,rgba(193,53,21,.5) 0%,rgba(193,53,21,0) 60%);
      opacity:0;z-index:1;
    }
    .liar-cup-stage.revealing.spilled .liar-burst-spill{
      animation: liarBurstSpill 0.55s ease-out 1;
    }
    @keyframes liarBurstSpill{
      0%  {opacity:0;transform:translate(-50%,-50%) scale(.5)}
      40% {opacity:1;transform:translate(-50%,-50%) scale(1.2)}
      100%{opacity:0;transform:translate(-50%,-50%) scale(2)}
    }
    .liar-droplet{
      position:absolute;left:50%;top:38%;font-size:18px;line-height:1;
      pointer-events:none;opacity:0;z-index:3;
    }
    .liar-cup-stage.revealing.spilled .liar-droplet{
      animation: liarDropletFall 0.95s cubic-bezier(.3,.5,.7,1) 1 forwards;
    }
    @keyframes liarDropletFall{
      0%  {opacity:0;transform:translate(-50%,-50%) scale(.4)}
      15% {opacity:1;transform:translate(-50%,-50%) scale(1)}
      90% {opacity:1;transform:translate(calc(-50% + var(--drop-x,0px)),calc(60px + var(--drop-y,0px))) scale(1) rotate(var(--drop-rot,0deg))}
      100%{opacity:0;transform:translate(calc(-50% + var(--drop-x,0px)),calc(80px + var(--drop-y,0px))) scale(.6) rotate(var(--drop-rot,0deg))}
    }
    /* Full-screen colored flash overlay for the reveal moment */
    .liar-flash{
      position:fixed;inset:0;background:var(--success);opacity:0;pointer-events:none;
      z-index:300;
    }
    .liar-flash.safe   { background:var(--success); animation: liarFlash 0.45s ease-out 1; }
    .liar-flash.spilled{ background:var(--danger);  animation: liarFlash 0.5s  ease-out 1; }
    .liar-flash.busted { background:var(--danger);  animation: liarFlash 0.4s  ease-out 1; }
    .liar-flash.wrong  { background:#c9a04d;        animation: liarFlash 0.4s  ease-out 1; }
    @keyframes liarFlash{
      0%{opacity:0}
      25%{opacity:.55}
      100%{opacity:0}
    }

    /* ===== GLASS SHATTER VFX =====
       Used for the dramatic spill moment. The cup visibly cracks for ~150ms,
       then breaks: 12 glass shards explode outward, a liquid puddle spreads
       below, a full-screen vignette closes in from the edges, and the cup
       emoji vanishes. Cafe-friendly drama — no death imagery, just a
       broken-glass moment with weight. */

    /* Crack lines drawn over the still-intact cup right before shatter. */
    .liar-cup-cracks{
      position:absolute;left:50%;top:50%;
      width:96px;height:96px;
      pointer-events:none;
      transform:translate(-50%,-50%) scale(.35);
      opacity:0;
      z-index:3;
    }
    .liar-cup-cracks svg{
      width:100%;height:100%;
      stroke:#f4f7fb;stroke-width:2.4;stroke-linecap:round;fill:none;
      filter:drop-shadow(0 0 3px rgba(255,255,255,.85)) drop-shadow(0 0 6px rgba(120,170,255,.5));
    }
    .liar-cup-stage.cracking .liar-cup-cracks{
      animation:liarCrackAppear 0.22s cubic-bezier(.4,0,.2,1) 1 forwards;
    }
    @keyframes liarCrackAppear{
      0%   { opacity:0;transform:translate(-50%,-50%) scale(.35) }
      55%  { opacity:1;transform:translate(-50%,-50%) scale(1.08) }
      100% { opacity:1;transform:translate(-50%,-50%) scale(1) }
    }
    /* Once shatter fires the cracks fade out (the shards take over). */
    .liar-cup-stage.revealing.spilled .liar-cup-cracks{
      animation:liarCrackFade 0.3s ease-out 1 forwards;
    }
    @keyframes liarCrackFade{
      0%   { opacity:1 }
      100% { opacity:0;transform:translate(-50%,-50%) scale(1.3) }
    }

    /* On shatter, the cup emoji itself vanishes (the shards are the new visual).
       It returns as 💧 droplet via JS to mark where the liquid pooled. */
    .liar-cup-stage.revealing.spilled .liar-cup-glass{
      /* Override the existing tilt animation — we want the cup to disappear
         immediately on shatter rather than rotate. The 💧 swap (done in JS)
         shows briefly with a fade-in as the puddle settles. */
      animation:liarCupShatter 0.5s ease-out 1 forwards;
    }
    @keyframes liarCupShatter{
      0%   { transform:translateY(-2px) scale(1);opacity:1;filter:drop-shadow(0 0 14px rgba(193,53,21,.6)) drop-shadow(0 4px 8px rgba(0,0,0,.18)) }
      20%  { transform:translateY(-1px) scale(1.05);opacity:1 }
      30%  { opacity:0;transform:translateY(2px) scale(.6) }
      55%  { opacity:0 }
      100% { opacity:1;transform:translateY(4px) scale(.55);filter:drop-shadow(0 0 8px rgba(193,53,21,.4)) drop-shadow(0 2px 6px rgba(0,0,0,.2)) }
    }
    .liar-cup-stage.spill-aftermath .liar-cup-glass{
      /* In the aftermath state the small 💧 sits as the puddle remnant. */
      animation:liarCupShatterRest 1.2s ease-out 1 forwards;
    }
    @keyframes liarCupShatterRest{
      0%   { transform:translateY(4px) scale(.55) }
      100% { transform:translateY(8px) scale(.5);filter:drop-shadow(0 0 6px rgba(193,53,21,.3)) drop-shadow(0 2px 4px rgba(0,0,0,.2)) }
    }

    /* Individual glass shard — small angular shape that explodes outward.
       Light-blue/white gradient with a subtle glow so it reads as glass. */
    .liar-shard{
      position:absolute;left:50%;top:46%;
      width:11px;height:15px;
      pointer-events:none;opacity:0;z-index:4;
      background:linear-gradient(135deg,#f4f9ff 0%,#bcd3ee 55%,#7da3cf 100%);
      clip-path:polygon(50% 0,100% 38%,82% 100%,18% 92%,0 48%);
      box-shadow:0 0 6px rgba(150,190,235,.65),inset 0 0 2px rgba(255,255,255,.7);
      transform:translate(-50%,-50%);
    }
    .liar-cup-stage.revealing.spilled .liar-shard{
      animation:liarShardFly 0.95s cubic-bezier(.18,.7,.4,1) 1 forwards;
    }
    @keyframes liarShardFly{
      0%   { opacity:0;transform:translate(-50%,-50%) rotate(0) scale(.4) }
      10%  { opacity:1;transform:translate(-50%,-50%) rotate(0) scale(1) }
      100% { opacity:0;transform:translate(calc(-50% + var(--shard-x,0px)),calc(-50% + var(--shard-y,40px))) rotate(var(--shard-rot,720deg)) scale(.85) }
    }

    /* Liquid puddle — spreads below the cup as it shatters. */
    .liar-puddle{
      position:absolute;left:50%;top:62%;
      width:0;height:0;
      background:radial-gradient(ellipse,rgba(95,130,205,.55) 0%,rgba(55,85,160,.32) 60%,transparent 100%);
      border-radius:50%;
      pointer-events:none;
      transform:translate(-50%,0);
      opacity:0;
      z-index:1;
      filter:blur(.5px);
    }
    .liar-cup-stage.revealing.spilled .liar-puddle,
    .liar-cup-stage.spill-aftermath .liar-puddle{
      animation:liarPuddleSpread 1.6s ease-out 1 forwards;
    }
    @keyframes liarPuddleSpread{
      0%   { width:0;height:0;opacity:0 }
      20%  { opacity:1 }
      100% { width:200px;height:48px;opacity:.85 }
    }

    /* Full-screen vignette — closes in from edges during shatter, retracts
       slowly during the aftermath. This is the "darkness eats your screen"
       moment that makes the spill feel HEAVY without any death imagery. */
    .liar-vignette{
      position:fixed;inset:0;
      background:radial-gradient(ellipse at center,transparent 22%,rgba(0,0,0,.78) 85%);
      pointer-events:none;
      z-index:298;
      opacity:0;
    }
    .liar-vignette.show{
      animation:liarVignetteShow 2.4s ease-out 1;
    }
    @keyframes liarVignetteShow{
      0%   { opacity:0 }
      18%  { opacity:1 }
      55%  { opacity:.78 }
      100% { opacity:0 }
    }

    /* "OUT" stamp — slams in on the spill result panel like the BUSTED/WRONG
       stamps on the truth page. Bigger, red, slight rotation, drop shadow. */
    .liar-out-stamp{
      display:inline-block;
      padding:6px 22px;
      border:3.5px solid currentColor;
      color:var(--danger);
      font-size:30px;font-weight:900;letter-spacing:.18em;
      border-radius:6px;
      margin-bottom:10px;
      text-shadow:0 1px 0 rgba(0,0,0,.04);
      transform:rotate(-6deg) scale(2);
      opacity:0;
      animation:liarOutStampSlam 0.55s cubic-bezier(.34,1.56,.64,1) 0.18s 1 forwards;
    }
    @keyframes liarOutStampSlam{
      0%   { opacity:0;transform:rotate(-14deg) scale(2.8) }
      55%  { opacity:1;transform:rotate(-4deg) scale(.92) }
      75%  { transform:rotate(-7deg) scale(1.06) }
      100% { opacity:1;transform:rotate(-6deg) scale(1) }
    }

    /* Strikethrough animation on the eliminated player's name in the
       result panel — the line draws left-to-right as the panel lands. */
    .liar-name-strike{
      position:relative;display:inline-block;
    }
    .liar-name-strike::after{
      content:'';position:absolute;left:-2px;right:-2px;top:54%;height:2.5px;
      background:var(--danger);
      border-radius:2px;
      transform:scaleX(0);transform-origin:left center;
      animation:liarNameStrike 0.45s cubic-bezier(.4,0,.2,1) 0.55s 1 forwards;
    }
    @keyframes liarNameStrike{
      0%   { transform:scaleX(0) }
      100% { transform:scaleX(1) }
    }

    /* Reduced-motion fallback — all the new shatter effects calm down. */
    @media (prefers-reduced-motion: reduce){
      .liar-cup-stage.cracking .liar-cup-cracks,
      .liar-cup-stage.revealing.spilled .liar-cup-cracks,
      .liar-cup-stage.revealing.spilled .liar-shard,
      .liar-cup-stage.revealing.spilled .liar-puddle,
      .liar-cup-stage.spill-aftermath .liar-puddle,
      .liar-cup-stage.revealing.spilled .liar-cup-glass,
      .liar-cup-stage.spill-aftermath .liar-cup-glass,
      .liar-vignette.show,
      .liar-out-stamp,
      .liar-name-strike::after{ animation:none }
      .liar-vignette{ opacity:0 }
      .liar-out-stamp{ opacity:1;transform:rotate(-4deg) scale(1) }
      .liar-name-strike::after{ transform:scaleX(1) }
    }
    /* Screen-shake — applied to <body> for ~600ms on spill.
       .heavy variant = bigger amplitude + longer duration for the primary impact.
       .soft variant  = smaller aftershock used ~600ms after the main hit. */
    .liar-shake{ animation: liarShake 0.55s cubic-bezier(.36,.07,.19,.97); }
    .liar-shake.heavy{ animation: liarShakeHeavy 0.72s cubic-bezier(.36,.07,.19,.97); }
    .liar-shake.soft{  animation: liarShakeSoft  0.42s cubic-bezier(.36,.07,.19,.97); }
    @keyframes liarShake{
      0%,100% { transform:translate3d(0,0,0) }
      10%     { transform:translate3d(-6px,2px,0) }
      20%     { transform:translate3d(7px,-3px,0) }
      30%     { transform:translate3d(-9px,4px,0) }
      40%     { transform:translate3d(8px,-2px,0) }
      55%     { transform:translate3d(-5px,3px,0) }
      70%     { transform:translate3d(4px,-2px,0) }
      85%     { transform:translate3d(-2px,1px,0) }
    }
    @keyframes liarShakeHeavy{
      0%,100% { transform:translate3d(0,0,0) }
      6%      { transform:translate3d(-12px,5px,0) }
      14%     { transform:translate3d(13px,-6px,0) }
      22%     { transform:translate3d(-15px,7px,0) }
      30%     { transform:translate3d(14px,-5px,0) }
      40%     { transform:translate3d(-11px,6px,0) }
      52%     { transform:translate3d(10px,-4px,0) }
      64%     { transform:translate3d(-7px,3px,0) }
      76%     { transform:translate3d(5px,-2px,0) }
      88%     { transform:translate3d(-3px,1px,0) }
    }
    @keyframes liarShakeSoft{
      0%,100% { transform:translate3d(0,0,0) }
      20%     { transform:translate3d(-4px,1px,0) }
      40%     { transform:translate3d(5px,-2px,0) }
      60%     { transform:translate3d(-3px,2px,0) }
      80%     { transform:translate3d(2px,-1px,0) }
    }

    /* Post-reveal lingering states — applied AFTER the .revealing phase ends
       so the moment doesn't snap back to "neutral" instantly. */
    .liar-cup-stage.spill-aftermath{
      animation: liarSpillAftermathBg 2.6s ease-out 1 forwards;
    }
    .liar-cup-stage.spill-aftermath .liar-cup-glass{
      animation: liarCupSpillRest 2.6s ease-out 1 forwards;
      filter:drop-shadow(0 0 18px rgba(193,53,21,.55)) drop-shadow(0 4px 8px rgba(0,0,0,.2));
    }
    @keyframes liarCupSpillRest{
      0%   { transform:translateY(6px) rotate(-52deg) scale(1) }
      30%  { transform:translateY(8px) rotate(-58deg) scale(.97) }
      60%  { transform:translateY(9px) rotate(-60deg) scale(.94) }
      100% { transform:translateY(9px) rotate(-60deg) scale(.92);filter:drop-shadow(0 0 10px rgba(193,53,21,.35)) drop-shadow(0 4px 8px rgba(0,0,0,.2)) }
    }
    @keyframes liarSpillAftermathBg{
      0%   { box-shadow:inset 0 0 0 rgba(193,53,21,0) }
      30%  { box-shadow:inset 0 0 100px rgba(193,53,21,.22) }
      70%  { box-shadow:inset 0 0 100px rgba(193,53,21,.16) }
      100% { box-shadow:inset 0 0 0 rgba(193,53,21,0) }
    }
    /* Safe celebration linger — gentle pulsing green halo behind the cup so
       the "phew!" moment breathes for an extra beat before the result card. */
    .liar-cup-stage.safe-celebrate .liar-cup-glass{
      animation: liarCupSafeLinger 1.6s ease-in-out 1 forwards;
      filter:drop-shadow(0 0 18px rgba(62,197,106,.55)) drop-shadow(0 4px 8px rgba(0,0,0,.15));
    }
    @keyframes liarCupSafeLinger{
      0%   { transform:translateY(-2px) scale(1) }
      40%  { transform:translateY(-6px) scale(1.04) }
      100% { transform:translateY(-2px) scale(1);filter:drop-shadow(0 0 8px rgba(62,197,106,.3)) drop-shadow(0 4px 8px rgba(0,0,0,.15)) }
    }
    /* Result card dramatize — slams in on spill, soft-pops in on safe. */
    .liar-cup-result.spilled.dramatize{
      animation: liarSpillCardSlam 0.6s cubic-bezier(.34,1.56,.64,1) 1;
    }
    .liar-cup-result.safe.dramatize{
      animation: liarSafeCardPop 0.5s cubic-bezier(.34,1.56,.64,1) 1;
    }
    @keyframes liarSpillCardSlam{
      0%   { opacity:0;transform:scale(.78) translateY(22px) rotate(-1.5deg) }
      45%  { opacity:1;transform:scale(1.06) translateY(-3px) rotate(.8deg) }
      70%  { transform:scale(.97) translateY(2px) rotate(-.3deg) }
      100% { transform:scale(1) translateY(0) rotate(0) }
    }
    @keyframes liarSafeCardPop{
      0%   { opacity:0;transform:scale(.9) translateY(8px) }
      55%  { opacity:1;transform:scale(1.03) translateY(0) }
      100% { transform:scale(1) translateY(0) }
    }

    /* Big stamp animation used on both reveal screen (BUSTED/WRONG CALL) and
       cup screen (PHEW/SPILLED). Slams in with rotation + sticks for a beat. */
    .liar-stamp{
      display:inline-block;padding:8px 22px;border-radius:8px;
      font-weight:900;letter-spacing:.12em;text-transform:uppercase;
      font-size:24px;line-height:1.1;
      border:3px solid currentColor;color:var(--danger);
      opacity:0;transform:rotate(-8deg) scale(2);
      animation: liarStampSlam 0.5s cubic-bezier(.34,1.56,.64,1) 1 forwards;
      text-shadow:0 1px 0 rgba(0,0,0,.05);
    }
    .liar-stamp.safe-stamp { color:var(--success) }
    .liar-stamp.wrong-stamp{ color:#a07310 }
    [data-theme="dark"] .liar-stamp.wrong-stamp{ color:#f5c451 }
    @keyframes liarStampSlam{
      0%   {opacity:0;transform:rotate(-14deg) scale(2.6)}
      55%  {opacity:1;transform:rotate(-6deg)  scale(.9)}
      75%  {opacity:1;transform:rotate(-9deg)  scale(1.08)}
      100% {opacity:1;transform:rotate(-7deg)  scale(1)}
    }
    /* Pulsing CTA — used on reveal page's "Time for the cup" button when ready */
    .liar-cta-pulse{ animation: liarCtaPulse 1.6s ease-in-out infinite; }
    @keyframes liarCtaPulse{
      0%,100% { box-shadow:0 0 0 0   rgba(193,53,21,0)  }
      50%     { box-shadow:0 0 0 12px rgba(193,53,21,.18) }
    }
    /* Reveal screen — verdict gets a slam-in too on first paint */
    .liar-verdict.dramatize{ animation: liarVerdictSlam 0.4s cubic-bezier(.34,1.56,.64,1) 1; }
    @keyframes liarVerdictSlam{
      0%  {opacity:0;transform:translateY(8px) scale(.92)}
      60% {opacity:1;transform:translateY(0)  scale(1.04)}
      100%{opacity:1;transform:translateY(0)  scale(1)}
    }
    /* Auto-advance hint — small pulsing dot + text shown when the game is about
       to transition on its own. Used on the Truth page (under the verdict) and
       on the Cup result card. Subtle so it doesn't compete with the main reveal. */
    .liar-auto-dot{
      display:inline-block;width:6px;height:6px;border-radius:50%;
      background:var(--text-secondary);vertical-align:middle;margin-right:2px;
      animation: liarAutoDot 1s ease-in-out infinite;
    }
    @keyframes liarAutoDot{
      0%,100% { opacity:.35; transform:scale(.85) }
      50%     { opacity:1;   transform:scale(1.15) }
    }
    .liar-cup-autohint{
      margin-top:8px;font-size:12px;color:var(--text-secondary);
      letter-spacing:.02em;display:flex;align-items:center;justify-content:center;gap:6px;
    }
    @media (prefers-reduced-motion: reduce){
      .liar-auto-dot{ animation:none; opacity:.7 }
    }

    /* Reduced-motion fallback — calm static states; no shaking, no spinning,
       no big bouncy reveals. The reveal still happens (state changes), just
       without the kinetic flourish. */
    @media (prefers-reduced-motion: reduce){
      .liar-cup-stage.anticipating .liar-cup-glass,
      .liar-cup-stage.drinking    .liar-cup-glass,
      .liar-cup-stage.revealing.safe    .liar-cup-glass,
      .liar-cup-stage.revealing.spilled .liar-cup-glass,
      .liar-cup-stage.spill-aftermath .liar-cup-glass,
      .liar-cup-stage.safe-celebrate  .liar-cup-glass{ animation:none }
      .liar-cup-aura, .liar-burst-safe, .liar-burst-spill,
      .liar-confetti-piece, .liar-droplet, .liar-cup-sweat,
      .liar-flash, .liar-shake, .liar-stamp, .liar-verdict.dramatize,
      .liar-cta-pulse,
      .liar-cup-result.spilled.dramatize,
      .liar-cup-result.safe.dramatize{ animation:none }
      .liar-cup-stage.spill-aftermath, .liar-cup-stage.safe-celebrate{ animation:none }
      .liar-cup-chamber.rolling{ transition:none }
      .liar-flash{ opacity:0 }
      .liar-stamp{ opacity:1;transform:rotate(-4deg) scale(1) }
    }

    /* Win screen */
    .liar-win-hero{text-align:center;margin:24px 0 18px}
    .liar-win-crown{font-size:80px;line-height:1;margin-bottom:12px;animation:liarCrownPop .8s ease-out}
    @keyframes liarCrownPop{
      0%{transform:scale(.4) rotate(-12deg);opacity:0}
      60%{transform:scale(1.2) rotate(6deg);opacity:1}
      100%{transform:scale(1) rotate(0);opacity:1}
    }
    .liar-win-title{font-size:28px;font-weight:900;letter-spacing:-.01em;color:var(--text);margin-bottom:6px}
    .liar-win-sub{font-size:14px;color:var(--text-secondary)}

    /* ===== Play screen — round-table layout (Design A) =====
       All seated players sit evenly around a circular felt; ME locks at 6
       o'clock, opponents fill the rest of the rim at 360°/N intervals.
       Glow ring (.current) follows whichever player is on turn — synced
       across devices via liarState.currentPlayerIdx. */
    .liar-play-main{display:flex;flex-direction:column;padding:6px 12px 16px;gap:10px}
    /* Single-screen Liar's Cup — only the .liar-stage matching #screen-liar-play[data-stage] is visible.
       Stage swapping is CSS-only; JS just sets data-stage on the screen element. */
    #screen-liar-play .liar-stage{display:none;flex-direction:column;flex:1 1 auto;min-height:0;gap:10px}
    #screen-liar-play[data-stage="tablecard"] .liar-stage[data-stage="tablecard"],
    #screen-liar-play[data-stage="play"]      .liar-stage[data-stage="play"],
    #screen-liar-play[data-stage="reveal"]    .liar-stage[data-stage="reveal"],
    #screen-liar-play[data-stage="cup"]       .liar-stage[data-stage="reveal"],
    #screen-liar-play[data-stage="result"]    .liar-stage[data-stage="result"]{display:flex}
    /* Tablecard: vertically centered splash, matches the look of the old standalone splash. */
    #screen-liar-play[data-stage="tablecard"] .liar-stage[data-stage="tablecard"]{justify-content:center;align-items:center;text-align:center;min-height:calc(100vh - 120px)}
    #screen-liar-play[data-stage="tablecard"] .liar-stage[data-stage="tablecard"] > .btn{width:100%;max-width:340px;margin-top:24px}
    /* Rules button only makes sense during active play. */
    #screen-liar-play:not([data-stage="play"]) .liar-play-rules-btn{display:none}
    /* ===== Reveal + Cup overlay (CARDS and WHEEL centred at SCREEN centre) =====
       The overlay is a zero-sized anchor positioned at the section's exact centre
       (top:50%; left:50%). Its children are absolute-positioned relative to that
       anchor so we can place the CARDS row AND the WHEEL itself geometrically at
       the screen centre, with stamp/verdict/cup-result text positioned BELOW the
       anchor (not pulling the geometric centre off). */
    #screen-liar-play{position:relative}
    .liar-play-reveal-overlay{
      position:absolute;top:50%;left:50%;
      width:0;height:0;
      overflow:visible;
      opacity:0;pointer-events:none;
      transition:opacity .35s ease;
      z-index:50;
    }
    #screen-liar-play.reveal-mode .liar-play-reveal-overlay,
    #screen-liar-play.cup-mode    .liar-play-reveal-overlay{
      opacity:1;pointer-events:auto;
    }
    /* Hide the ACE pill / table-card label while reveal or cup is active. */
    #screen-liar-play.reveal-mode .liar-play-center,
    #screen-liar-play.cup-mode    .liar-play-center{
      opacity:0;pointer-events:none;
      transition:opacity .25s ease;
    }
    /* Hide redundant hero + waiting bits — seat indicators already show the claim,
       and the cards-flip + verdict pill carry the moment. */
    .liar-play-reveal-overlay .liar-reveal-hero,
    .liar-play-reveal-overlay .liar-reveal-waiting{display:none}

    /* ===== 3-D flip card used only inside the reveal overlay =====
       Cards start face-down (red back facing user). Each one flips face-up on a
       stagger driven by --i (set in JS). Backface-visibility hides the away side
       so users see a real card flip, not a mirrored letter.
       The cards ROW is anchored such that its geometric centre = screen centre. */
    .liar-play-reveal-overlay .liar-reveal-cards{
      position:absolute;top:0;left:0;
      transform:translate(-50%,-50%);
      display:flex;gap:8px;justify-content:center;flex-wrap:nowrap;margin:0;
      perspective:700px;
      white-space:nowrap;
    }
    .liar-flip-card{
      width:52px;height:74px;flex-shrink:0;
      transform-style:preserve-3d;
      transform:rotateY(180deg);  /* default: back-of-card facing user */
      animation:liarFlipCardReveal .55s cubic-bezier(.34,1.2,.5,1) forwards;
      animation-delay:calc(.3s + var(--i, 0) * .6s);
    }
    .liar-flip-face{
      position:absolute;inset:0;
      backface-visibility:hidden;
      -webkit-backface-visibility:hidden;
      border-radius:8px;
      border:1.5px solid var(--border-strong);
      background:var(--surface);
      color:var(--text);
      display:flex;align-items:center;justify-content:center;
      font-weight:800;
      box-shadow:0 2px 6px rgba(0,0,0,.25);
    }
    .liar-flip-back{
      transform:rotateY(180deg);
      background:
        repeating-linear-gradient(45deg, rgba(255,255,255,.06) 0 6px, transparent 6px 12px),
        linear-gradient(135deg,#7c2d12 0%,#b91c1c 60%,#7c2d12 100%);
      border-color:#9a3412;
    }
    .liar-flip-front{transform:rotateY(0deg)}
    .liar-flip-front.revealed-truth{border-color:var(--success);box-shadow:0 0 0 3px var(--success-soft),0 2px 6px rgba(0,0,0,.25)}
    .liar-flip-front.revealed-lie{border-color:var(--danger);box-shadow:0 0 0 3px var(--danger-soft),0 2px 6px rgba(0,0,0,.25)}
    .liar-flip-front .liar-card-rank{font-size:22px;line-height:1}
    .liar-flip-front .liar-card-suit{position:absolute;top:4px;left:5px;font-size:10px;font-weight:700;line-height:1}
    .liar-flip-front .liar-card-suit-br{position:absolute;bottom:4px;right:5px;font-size:10px;font-weight:700;line-height:1;transform:rotate(180deg)}
    @keyframes liarFlipCardReveal{
      0%{transform:rotateY(180deg)}
      100%{transform:rotateY(0deg)}
    }

    /* Reveal stamp (BUSTED / WRONG CALL) — positioned below the screen-centre
       anchor. This is the ONLY post-flip text on the reveal — the verdict pill
       and the cup-result panel are hidden via the rules below. */
    .liar-play-reveal-overlay #liar-reveal-stamp{
      position:absolute;top:55px;left:0;
      transform:translateX(-50%);
      white-space:nowrap;min-height:24px;
    }
    /* HIDE the verdict pill ("Jordan was LYING." / "You accused wrong!") and
       the cup-result panel ("You survived!", body, next-round hint). The
       BUSTED/WRONG CALL stamp and the SAFE/OUT stamp carry the moment alone. */
    .liar-play-reveal-overlay .liar-verdict{display:none !important}
    .liar-play-reveal-overlay .liar-cup-result{display:none !important}

    /* Cup section is a logical wrapper at the anchor; the WHEEL itself is the
       child that's geometrically centred at screen centre. */
    .liar-play-reveal-overlay .liar-cup-section{
      position:absolute;top:0;left:0;
      width:0;height:0;margin:0;padding:0;
      opacity:0;pointer-events:none;
      transition:opacity .4s ease;
      transform:none;
    }
    #screen-liar-play.cup-mode .liar-play-reveal-overlay .liar-cup-section{
      opacity:1;pointer-events:auto;
    }
    #screen-liar-play.cup-mode .liar-play-reveal-overlay .liar-reveal-cards,
    #screen-liar-play.cup-mode .liar-play-reveal-overlay .liar-verdict,
    #screen-liar-play.cup-mode .liar-play-reveal-overlay #liar-reveal-stamp{
      opacity:0;transition:opacity .3s ease;pointer-events:none;
      animation:none;
    }
    /* Wheel-wrap = the WHEEL's bounding box, centred exactly at screen centre. */
    .liar-play-reveal-overlay .liar-wheel-wrap{
      position:absolute;top:0;left:0;
      width:200px;height:200px;margin:0;
      transform:translate(-50%, calc(-50% + 20px)) scale(.3);
      opacity:0;
      transition:transform .7s cubic-bezier(.34,1.56,.64,1), opacity .55s ease;
    }
    #screen-liar-play.cup-mode .liar-play-reveal-overlay .liar-wheel-wrap{
      transform:translate(-50%, -50%) scale(1);
      opacity:1;
    }
    .liar-play-reveal-overlay .liar-wheel{width:200px;height:200px}
    /* Wheel-stage is now layout-irrelevant — the wheel-wrap is absolute. Keep
       a placeholder so nothing breaks but zero its layout impact. */
    .liar-play-reveal-overlay .liar-cup-stage,
    .liar-play-reveal-overlay .liar-wheel-stage{
      position:absolute;top:0;left:0;width:0;height:0;min-height:0;
    }
    /* SAFE/OUT stamp below the wheel. Wheel half-height is 100px and we want
       the stamp to sit with a comfortable gap below the wheel rim — like how
       the BUSTED stamp sits ~18px below the cards (cards half-height 37). */
    .liar-play-reveal-overlay .liar-wheel-stamp{
      position:absolute;top:155px;left:0;
      transform:translateX(-50%);
      white-space:nowrap;
    }
    /* Result text panel — below the wheel. */
    .liar-play-reveal-overlay .liar-cup-result{
      position:absolute;top:130px;left:0;
      transform:translateX(-50%);
      padding:6px 10px;text-align:center;max-width:280px;
    }
    .liar-play-reveal-overlay .liar-cup-result-title{font-size:20px;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.6)}
    .liar-play-reveal-overlay .liar-cup-result-text{font-size:12px;color:rgba(255,255,255,.85)}
    .liar-play-reveal-overlay .liar-cup-result-emoji{font-size:28px}
    /* Particles container — keep at the anchor, no layout space. */
    .liar-play-reveal-overlay #liar-cup-particles{
      position:absolute;top:0;left:0;width:0;height:0;
    }

    /* ===== Spotlight backdrop =====
       During reveal/cup, a dark layer covers the play stage (felt + hand + buttons)
       so the reveal cards / wheel above it pop. Header and lab bar stay bright
       since they sit outside the stage. Hand + buttons stay drawn underneath the
       backdrop — visible but dimmed, non-interactive. */
    .liar-stage[data-stage="play"]{position:relative}
    .liar-stage[data-stage="play"]::before{
      content:"";
      position:absolute;
      inset:-12px -12px -16px -12px; /* extend slightly past the stage padding edges */
      background:rgba(0,0,0,.6);
      opacity:0;
      pointer-events:none;
      transition:opacity .35s ease;
      z-index:5;
    }
    #screen-liar-play.reveal-mode .liar-stage[data-stage="play"]::before,
    #screen-liar-play.cup-mode    .liar-stage[data-stage="play"]::before{
      opacity:1;
    }
    /* Bottom UI stays visible (the dark backdrop dims it) but non-interactive. */
    #screen-liar-play.reveal-mode .liar-play-status,
    #screen-liar-play.reveal-mode .liar-hand-wrap,
    #screen-liar-play.reveal-mode .liar-play-actions,
    #screen-liar-play.cup-mode .liar-play-status,
    #screen-liar-play.cup-mode .liar-hand-wrap,
    #screen-liar-play.cup-mode .liar-play-actions{
      pointer-events:none;
    }
    /* Lab mode bar — perspective switcher + card-style picker. */
    .liar-lab-bar{display:flex;flex-direction:column;gap:6px;padding:8px 10px;margin:2px 0 4px;background:rgba(0,0,0,.04);border:1px dashed var(--text-tertiary);border-radius:10px;font-size:12px;flex:0 0 auto}
    .liar-lab-bar-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
    [data-theme="dark"] .liar-lab-bar{background:rgba(255,255,255,.04)}
    .liar-lab-bar[hidden]{display:none}
    .liar-lab-bar-label{font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-secondary);font-size:11px}
    .liar-lab-bar-chips{display:flex;gap:6px;flex:1 1 auto;flex-wrap:wrap}
    .liar-lab-bar-chip{padding:5px 10px;border-radius:999px;border:1px solid var(--text-tertiary);background:transparent;color:var(--text);font-weight:600;font-size:12px;cursor:pointer;position:relative}
    .liar-lab-bar-chip.active{background:var(--text);color:var(--bg);border-color:var(--text)}
    .liar-lab-bar-chip.current::after{content:"";position:absolute;top:3px;right:4px;width:6px;height:6px;border-radius:50%;background:#16a34a;box-shadow:0 0 0 2px var(--bg)}
    .liar-lab-bar-exit{padding:5px 10px;border-radius:999px;border:1px solid #dc2626;background:transparent;color:#dc2626;font-weight:700;font-size:12px;cursor:pointer}

    /* ============================================================
       SYNC OVERLAY — the cross-device "waiting for everyone" moment
       ============================================================
       Every phase transition writes phaseStartAt = now + UPLINK_BUFFER (700ms).
       liarRerender defers content rendering until phaseStartAt, and shows this
       overlay during the buffer. The result: writer + watchers see the new phase
       at the same wall-clock moment (within phone clock-skew, ~50ms).

       Animation style is swappable via body.sync-style-* (set from the lab bar):
         dots     — three pulsing dots (iMessage typing indicator vibe)        DEFAULT
         cards    — three card silhouettes settling into a stack
         cup      — micro Liar's Cup with a sweat drop rolling down
         ring     — sonar-style concentric rings expanding from a dot
         bar      — Material 3 indeterminate linear-progress bar
         shuffle  — three card-backs fanned out, rotating around centre
       Every style fits inside a 120×80 stage so the card sizing stays consistent. */
    .liar-sync-overlay{
      position:fixed;inset:0;z-index:9200;
      display:none;align-items:center;justify-content:center;
      background:rgba(0,0,0,.42);
      -webkit-backdrop-filter:blur(3px) saturate(120%);
      backdrop-filter:blur(3px) saturate(120%);
      opacity:0;transition:opacity .22s ease;
      pointer-events:auto;
    }
    .liar-sync-overlay.active{display:flex;opacity:1}
    [data-theme="dark"] .liar-sync-overlay{background:rgba(0,0,0,.55)}
    .liar-sync-card{
      background:var(--surface,#fff);
      border:1px solid var(--border, rgba(0,0,0,.08));
      border-radius:20px;
      padding:22px 26px 18px;
      display:flex;flex-direction:column;align-items:center;gap:10px;
      box-shadow:0 12px 40px rgba(0,0,0,.18), 0 2px 6px rgba(0,0,0,.08);
      transform:translateY(8px) scale(.97);opacity:0;
      animation:liarSyncCardIn .26s cubic-bezier(.34,1.4,.6,1) .04s forwards;
      min-width:200px;max-width:88vw;
    }
    [data-theme="dark"] .liar-sync-card{
      background:var(--surface, #1a1a1a);
      border-color:rgba(255,255,255,.08);
      box-shadow:0 12px 40px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.4);
    }
    @keyframes liarSyncCardIn{to{transform:translateY(0) scale(1);opacity:1}}
    .liar-sync-anim{
      width:120px;height:80px;
      display:flex;align-items:center;justify-content:center;
      position:relative;
    }
    .liar-sync-label{
      font-size:13px;font-weight:600;color:var(--text-secondary);
      letter-spacing:.01em;text-align:center;
      margin-top:2px;
    }

    /* ===== Style 1 — DOTS (default) ===================================
       iMessage typing indicator: three dots pulsing in sequence. Universal
       "in progress" signal; minimal and calm. */
    body.sync-style-dots .liar-sync-anim{gap:8px}
    body.sync-style-dots .liar-sync-anim::before,
    body.sync-style-dots .liar-sync-anim::after,
    body.sync-style-dots .liar-sync-anim > .liar-sync-dot{
      content:"";display:block;width:12px;height:12px;border-radius:50%;
      background:var(--text);opacity:.25;
      animation:liarSyncDot 1.2s ease-in-out infinite;
    }
    body.sync-style-dots .liar-sync-anim::before{animation-delay:0s}
    body.sync-style-dots .liar-sync-anim > .liar-sync-dot{animation-delay:.18s}
    body.sync-style-dots .liar-sync-anim::after{animation-delay:.36s}
    @keyframes liarSyncDot{
      0%, 60%, 100%{opacity:.22;transform:scale(.78)}
      30%          {opacity:1;  transform:scale(1.0)}
    }

    /* ===== Style 2 — CARDS (settling deck) ============================
       Three small card silhouettes lift and settle in sequence. On-theme
       for a card game. Inspired by Apple Wallet card-stack animation. */
    body.sync-style-cards .liar-sync-anim{gap:6px;perspective:240px}
    body.sync-style-cards .liar-sync-card-mini{
      width:26px;height:36px;border-radius:5px;
      background:linear-gradient(145deg, var(--text), color-mix(in srgb, var(--text) 75%, transparent));
      box-shadow:0 2px 5px rgba(0,0,0,.18);
      transform-origin:50% 100%;
      animation:liarSyncCardSettle 1.35s cubic-bezier(.5,.05,.3,1) infinite;
    }
    body.sync-style-cards .liar-sync-card-mini:nth-child(1){animation-delay:0s}
    body.sync-style-cards .liar-sync-card-mini:nth-child(2){animation-delay:.15s}
    body.sync-style-cards .liar-sync-card-mini:nth-child(3){animation-delay:.30s}
    @keyframes liarSyncCardSettle{
      0%, 70%, 100%{transform:translateY(0)   rotateX(0deg)}
      30%          {transform:translateY(-12px) rotateX(-22deg)}
    }

    /* ===== Style 3 — CUP (Liar's Cup with sweat) ======================
       Micro-version of the existing cup vocabulary. The cup leans slightly
       forward while a sweat-drop rolls down its side. Most on-brand. */
    body.sync-style-cup .liar-sync-anim{justify-content:center}
    body.sync-style-cup .liar-sync-cup{
      position:relative;width:44px;height:54px;
      animation:liarSyncCupLean 1.6s ease-in-out infinite;
      transform-origin:50% 100%;
    }
    body.sync-style-cup .liar-sync-cup-body{
      position:absolute;inset:0;
      background:linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,.02));
      border:2px solid var(--text);
      border-top:none;border-radius:0 0 12px 12px / 0 0 16px 16px;
      box-shadow:inset 0 -4px 8px rgba(0,0,0,.1);
    }
    body.sync-style-cup .liar-sync-cup-fill{
      position:absolute;left:3px;right:3px;bottom:2px;height:30%;
      background:linear-gradient(180deg, #dc2626, #991b1b);
      border-radius:0 0 9px 9px / 0 0 13px 13px;
      opacity:.85;
    }
    body.sync-style-cup .liar-sync-cup-drop{
      position:absolute;top:-2px;left:50%;width:5px;height:8px;
      background:linear-gradient(180deg, #6cb6ff, #2563eb);
      border-radius:50% 50% 50% 50% / 70% 70% 30% 30%;
      transform:translateX(-50%);
      animation:liarSyncCupDrop 1.6s ease-in infinite;
    }
    @keyframes liarSyncCupLean{
      0%, 100%{transform:rotate(0deg)}
      40%     {transform:rotate(-6deg)}
      70%     {transform:rotate(3deg)}
    }
    @keyframes liarSyncCupDrop{
      0%, 20%{transform:translate(-50%, 0);opacity:0}
      35%    {transform:translate(-50%, 4px);opacity:1}
      85%    {transform:translate(-50%, 46px);opacity:.9}
      100%   {transform:translate(-50%, 52px);opacity:0}
    }

    /* ===== Style 4 — RING (sonar pulse) ===============================
       Central dot with two concentric rings expanding outward and fading.
       References iOS AirPods/Find My; reads as "active connection". */
    body.sync-style-ring .liar-sync-anim{position:relative}
    body.sync-style-ring .liar-sync-ring-core{
      width:14px;height:14px;border-radius:50%;
      background:var(--text);
      position:relative;z-index:2;
      box-shadow:0 0 0 0 currentColor;
    }
    body.sync-style-ring .liar-sync-ring-wave{
      position:absolute;left:50%;top:50%;
      width:14px;height:14px;border-radius:50%;
      border:2px solid var(--text);
      transform:translate(-50%,-50%);
      opacity:0;
      animation:liarSyncRingPulse 1.8s cubic-bezier(.2,.6,.3,1) infinite;
    }
    body.sync-style-ring .liar-sync-ring-wave:nth-child(2){animation-delay:.6s}
    @keyframes liarSyncRingPulse{
      0%  {transform:translate(-50%,-50%) scale(.6); opacity:.0}
      15% {opacity:.55}
      100%{transform:translate(-50%,-50%) scale(4.0); opacity:0}
    }

    /* ===== Style 5 — BAR (Material 3 indeterminate) ===================
       Horizontal track with a sliding 30%-width highlight pill. The most
       clinically clear "loading" signal — best when you want zero whimsy. */
    body.sync-style-bar .liar-sync-anim{align-items:center}
    body.sync-style-bar .liar-sync-bar-track{
      width:140px;height:4px;border-radius:999px;
      background:color-mix(in srgb, var(--text) 12%, transparent);
      overflow:hidden;position:relative;
    }
    body.sync-style-bar .liar-sync-bar-fill{
      position:absolute;top:0;bottom:0;width:36%;
      background:linear-gradient(90deg,
        transparent 0%,
        var(--text) 30%,
        var(--text) 70%,
        transparent 100%);
      border-radius:999px;
      animation:liarSyncBarSlide 1.4s cubic-bezier(.4,0,.2,1) infinite;
    }
    @keyframes liarSyncBarSlide{
      0%  {left:-40%}
      100%{left:104%}
    }

    /* ===== Style 6 — SHUFFLE (rotating card fan) ======================
       Three card-backs arranged in a fan, the whole fan slowly rotating
       around its centre. Most playful / explicitly game-flavoured. */
    body.sync-style-shuffle .liar-sync-anim{perspective:300px}
    body.sync-style-shuffle .liar-sync-fan{
      position:relative;width:60px;height:60px;
      animation:liarSyncFanSpin 2.2s cubic-bezier(.45,.05,.55,.95) infinite;
    }
    body.sync-style-shuffle .liar-sync-fan-card{
      position:absolute;left:50%;top:50%;
      width:22px;height:32px;border-radius:4px;
      background:linear-gradient(145deg, var(--text), color-mix(in srgb, var(--text) 70%, transparent));
      transform-origin:50% 100%;
      box-shadow:0 1px 3px rgba(0,0,0,.2);
      margin-left:-11px;margin-top:-16px;
    }
    body.sync-style-shuffle .liar-sync-fan-card:nth-child(1){transform:rotate(-18deg) translateY(-4px)}
    body.sync-style-shuffle .liar-sync-fan-card:nth-child(2){transform:rotate(0deg)   translateY(-8px)}
    body.sync-style-shuffle .liar-sync-fan-card:nth-child(3){transform:rotate(18deg)  translateY(-4px)}
    @keyframes liarSyncFanSpin{
      0%  {transform:rotate(0deg)}
      100%{transform:rotate(360deg)}
    }

    /* Reduced-motion fallback — keep the layout, drop the keyframes.
       (Sync timing still works; the overlay just sits still during the wait.) */
    @media (prefers-reduced-motion: reduce){
      .liar-sync-card{animation:none;opacity:1;transform:none}
      body.sync-style-dots    .liar-sync-anim::before,
      body.sync-style-dots    .liar-sync-anim::after,
      body.sync-style-dots    .liar-sync-anim > .liar-sync-dot,
      body.sync-style-cards   .liar-sync-card-mini,
      body.sync-style-cup     .liar-sync-cup,
      body.sync-style-cup     .liar-sync-cup-drop,
      body.sync-style-ring    .liar-sync-ring-wave,
      body.sync-style-bar     .liar-sync-bar-fill,
      body.sync-style-shuffle .liar-sync-fan{animation:none}
      body.sync-style-dots    .liar-sync-anim::before,
      body.sync-style-dots    .liar-sync-anim::after,
      body.sync-style-dots    .liar-sync-anim > .liar-sync-dot{opacity:.55}
    }

    .liar-play-felt{
      position:relative;
      width:100%;aspect-ratio:1/1;max-width:400px;margin:0 auto;
      border-radius:50%;
      background:radial-gradient(ellipse at 50% 45%, #2a7a47 0%, #1a6135 50%, #103f23 88%, #082a17 100%);
      border:6px solid #4a3318;
      box-shadow:
        inset 0 3px 14px rgba(0,0,0,.4),
        inset 0 -3px 10px rgba(0,0,0,.3),
        0 6px 22px rgba(0,0,0,.32);
    }
    /* Slot — absolute-positioned by inline (top,left) from JS. translate(-50%,-50%)
       centres on the slot's anchor so circle-edge math is clean. */
    .liar-play-slot{
      position:absolute;display:none;
      flex-direction:column;align-items:center;gap:3px;
      width:74px;transform:translate(-50%,-50%);
    }
    .liar-play-slot.active{display:flex}
    .liar-play-slot.eliminated{opacity:.45;filter:grayscale(1)}
    /* ME at 6 o'clock (inside the felt). */
    .liar-play-me{
      position:absolute;top:88%;left:50%;transform:translate(-50%,-50%);
      display:flex;flex-direction:column;align-items:center;gap:3px;
      width:80px;
    }
    .liar-play-me.eliminated{opacity:.45;filter:grayscale(1)}
    /* Centre — single bold "rank button" naming the current table card. */
    .liar-play-center{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      display:flex;flex-direction:column;align-items:center;gap:6px;
      pointer-events:none;
    }
    .liar-play-rank-button{
      display:inline-flex;align-items:center;justify-content:center;
      padding:10px 22px;min-width:120px;
      background:#fff;color:#1a1a1a;border-radius:var(--radius-pill);
      box-shadow:0 6px 14px rgba(0,0,0,.45), 0 0 0 2px rgba(255,215,0,.45);
    }
    .liar-play-rank-word{
      font-size:22px;font-weight:800;letter-spacing:.06em;color:#1a1a1a;
    }
    .liar-play-rank-label{
      font-size:10px;font-weight:700;color:rgba(255,255,255,.78);
      letter-spacing:.08em;text-transform:uppercase;
      text-shadow:0 1px 2px rgba(0,0,0,.5);margin-top:2px;
    }
    /* Seat-content (used by both opponent slots and ME) — avatar, name, claim. */
    .liar-play-seat-avatar{
      position:relative;
      display:inline-flex;line-height:0;
      filter:drop-shadow(0 2px 5px rgba(0,0,0,.5));
    }
    /* Pulse glow on current player — override drop-shadow so the halo stays
       a perfect circle (no shadow elongating it). */
    .liar-play-slot.current .liar-play-seat-avatar,
    .liar-play-me.current .liar-play-seat-avatar{
      filter:none;
    }
    .liar-play-slot.current .liar-play-seat-avatar::before,
    .liar-play-me.current .liar-play-seat-avatar::before{
      content:"";position:absolute;inset:-5px;border-radius:50%;
      border:2px solid rgba(255,255,255,.92);
      box-shadow:0 0 12px rgba(255,255,255,.5);
      animation:liarPlayPulse 1.6s ease-in-out infinite;
    }
    @keyframes liarPlayPulse{
      0%,100%{opacity:.45;transform:scale(1)}
      50%    {opacity:1;transform:scale(1.05)}
    }
    .liar-play-handcount{
      position:absolute;bottom:-3px;right:-6px;
      display:inline-flex;align-items:center;justify-content:center;
      min-width:20px;height:16px;padding:0 4px;
      background:#fff;border:1.5px solid #4a3318;
      border-radius:9px;font-size:9px;font-weight:800;color:#222;
      box-shadow:0 1px 2px rgba(0,0,0,.25);
    }
    .liar-play-seat-name{
      font-size:11px;font-weight:600;color:#fff;
      text-shadow:0 1px 2px rgba(0,0,0,.65);
      max-width:78px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    }
    .liar-play-me .liar-play-seat-name{max-width:80px}
    /* Claim pill — count + full rank word ("3 Queens" / "1 King"). Compact white
       chip that floats on the felt. */
    .liar-play-claim{
      display:inline-flex;align-items:center;
      padding:2px 8px 2px 6px;
      background:rgba(255,255,255,.96);border-radius:var(--radius-pill);
      box-shadow:0 1px 3px rgba(0,0,0,.45);
      font-size:10px;font-weight:800;color:#1a1a1a;line-height:1.05;
      animation:liarPlayClaimIn .25s ease-out;
      white-space:nowrap;max-width:78px;
    }
    .liar-play-me .liar-play-claim{max-width:90px}
    @keyframes liarPlayClaimIn{
      from{opacity:0;transform:translateY(-3px) scale(.96)}
      to  {opacity:1;transform:translateY(0)     scale(1)}
    }
    /* OUT tag for eliminated players (replaces the claim pill). */
    .liar-play-out-tag{
      font-size:9px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
      color:#fff;background:var(--danger);padding:2px 6px;border-radius:var(--radius-pill);
    }
    /* Status line under the felt — conversational, plain language. */
    .liar-play-status{
      font-size:13px;color:var(--text-secondary);text-align:center;line-height:1.4;
      padding:4px 8px;min-height:18px;
    }
    .liar-play-status strong{color:var(--text);font-weight:700}
    /* Hand — preserve existing .liar-hand styles; add top padding so the
       selected-card lift (translateY(-10px)) has room. */
    .liar-play-main .liar-hand-wrap{margin-top:2px}
    .liar-play-main .liar-hand{min-height:96px;padding-top:18px}
    /* Action row — side-by-side buttons. */
    .liar-play-actions{
      display:flex;gap:8px;padding-bottom:env(safe-area-inset-bottom,0);
    }
    .liar-play-btn{
      flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;
      padding:14px 12px;border-radius:var(--radius-pill);
      font:inherit;font-size:14px;font-weight:700;letter-spacing:.02em;
      cursor:pointer;transition:transform .1s ease, background-color .15s ease, opacity .15s ease;
      border:1px solid transparent;
    }
    .liar-play-btn:active{transform:scale(.98)}
    .liar-play-btn:disabled{opacity:.4;cursor:not-allowed}
    /* Button-level "tap acknowledged" state. During the 700ms sync buffer the
       button stays visibly pressed and runs a soft shimmer sweep — enough to
       feel acknowledged without screaming "loading". Auto-clears when the
       button is re-rendered into a new phase (no JS cleanup needed). */
    .liar-play-btn.is-syncing{
      transform:scale(.97);
      filter:saturate(.85);
      pointer-events:none;
      position:relative;overflow:hidden;
    }
    .liar-play-btn.is-syncing::after{
      content:"";position:absolute;inset:0;
      background:linear-gradient(100deg,
        transparent 30%,
        rgba(255,255,255,.28) 50%,
        transparent 70%);
      transform:translateX(-100%);
      animation:liarBtnSyncShimmer .85s ease-in-out infinite;
      pointer-events:none;
    }
    @keyframes liarBtnSyncShimmer{
      from{transform:translateX(-100%)}
      to  {transform:translateX(100%)}
    }
    @media (prefers-reduced-motion: reduce){
      .liar-play-btn.is-syncing::after{animation:none;opacity:.4;transform:translateX(0)}
    }
    .liar-play-btn-call{
      background:var(--danger-soft);color:var(--danger);
      border-color:color-mix(in srgb, var(--danger) 35%, transparent);
    }
    .liar-play-btn-play{
      background:var(--primary);color:var(--on-primary);border-color:var(--primary);
    }
    /* Compact "Rules" pill in the header — clearer than a bare ? icon at
       teaching new players what's behind the help. */
    .liar-play-rules-btn{
      display:inline-flex;align-items:center;gap:5px;
      height:34px;padding:0 12px;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-pill);
      color:var(--text-secondary);font:inherit;font-size:13px;font-weight:600;
      cursor:pointer;transition:background-color .15s ease,color .15s ease,border-color .15s ease;
    }
    .liar-play-rules-btn:hover{background:var(--bg-hover);color:var(--text);border-color:var(--text)}
    .liar-play-rules-btn svg{flex-shrink:0;opacity:.85}
    @media(max-width:380px){
      .liar-play-seat-name{font-size:10px;max-width:72px}
      .liar-play-rank-button{padding:8px 16px;min-width:100px}
      .liar-play-rank-word{font-size:18px}
      .liar-play-btn{font-size:13px;padding:13px 8px}
    }

    /* Multiplayer seat picker (lobby) */
    .liar-prototype-hint{
      background:var(--bg-subtle);border:1px dashed var(--border-strong);
      border-radius:var(--radius-md);padding:10px 12px;margin:0 0 14px;
      font-size:12px;color:var(--text-secondary);line-height:1.45;
    }
    .liar-prototype-hint strong{color:var(--text);font-weight:700}

    /* 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)}
    /* 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. */
    .lobby-toast{
      position:fixed;top:14px;left:50%;transform:translate(-50%,-8px);
      z-index:140;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}
    .liar-seats-header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 6px}
    .liar-seats-header .section-title{margin:0}
    .liar-seats-header-actions{display:flex;gap:6px;align-items:center}
    .liar-seats-header-actions button{
      background:none;border:none;cursor:pointer;font:inherit;
      font-size:13px;font-weight:600;letter-spacing:.01em;
      padding:6px 10px;border-radius:var(--radius-sm);
      color:var(--text-secondary);transition:background .15s ease,color .15s ease;
    }
    .liar-seats-header-actions button:hover{background:var(--bg-subtle);color:var(--text)}
    .liar-seats-header-actions .liar-leave{color:var(--danger)}
    .liar-seats-header-actions .liar-leave:hover{background:var(--danger-soft);color:var(--danger)}
    .liar-seats{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin:0 0 8px}
    .liar-seat{
      display:flex;align-items:center;gap:10px;padding:12px;
      background:var(--bg);border:1.5px solid var(--border-strong);border-radius:var(--radius-md);
      cursor:pointer;font:inherit;color:inherit;text-align:left;
      transition:all .15s ease;width:100%;
    }
    .liar-seat:hover:not(:disabled){border-color:var(--text);transform:translateY(-1px)}
    .liar-seat:disabled{opacity:.55;cursor:not-allowed;background:var(--bg-subtle)}
    .liar-seat.claimed-by-me{border-color:var(--success);background:var(--success-soft)}
    .liar-seat-info{flex:1;min-width:0}
    .liar-seat-name{font-weight:700;color:var(--text);font-size:14px;line-height:1.2;letter-spacing:-.01em}
    .liar-seat-status{font-size:10px;color:var(--text-secondary);font-weight:700;letter-spacing:.05em;text-transform:uppercase;margin-top:2px}
    .liar-seat.claimed-by-me .liar-seat-status{color:var(--success)}
    /* Empty seat = invite tile. Dashed border + plus icon makes it read as
       "tap to fill" instead of a regular player slot. */
    .liar-seat.liar-seat-invite{
      border-style:dashed;border-color:var(--border-strong);background:var(--bg);
      color:var(--text-secondary);
    }
    .liar-seat.liar-seat-invite:hover{border-style:solid;border-color:var(--text);color:var(--text);background:var(--bg-subtle)}
    .liar-seat-invite-icon{
      width:32px;height:32px;border-radius:50%;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:18px;font-weight:600;line-height:1;
    }
    .liar-seat.liar-seat-invite:hover .liar-seat-invite-icon{background:var(--bg);color:var(--text)}
    .liar-seat-invite .liar-seat-name{color:var(--text-secondary);font-weight:600}
    .liar-seat.liar-seat-invite:hover .liar-seat-name{color:var(--text)}
    .liar-seats-hint{
      text-align:center;font-size:12px;color:var(--text-secondary);
      margin:0 0 14px;line-height:1.45;font-style:italic;
    }

    /* ===== Mafia lobby (mirrors .liar-seats chrome, with extras) =====
       Mafia has TWO claim concepts at the lobby:
         1. Regular seats — for the 6-8 actual players, same .mafia-seats grid
            as Liar's two-col layout.
         2. Narrator slot — a SEPARATE card sitting above the player seats.
            Distinct visual so users immediately understand the narrator is
            a special role (they don't play). Host picks one claimant to fill
            it via the narrator-picker sheet. */
    .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:left;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)}

    /* Player seats grid — same shape as .liar-seats so the visual rhythm holds */
    .mafia-seats{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin:0 0 8px}
    .mafia-seat{
      display:flex;align-items:center;gap:10px;padding:12px;
      background:var(--bg);border:1.5px solid var(--border-strong);border-radius:var(--radius-md);
      cursor:pointer;font:inherit;color:inherit;text-align:left;
      transition:all .15s ease;width:100%;
    }
    .mafia-seat:hover:not(:disabled){border-color:var(--text);transform:translateY(-1px)}
    .mafia-seat:disabled{opacity:.55;cursor:not-allowed;background:var(--bg-subtle)}
    .mafia-seat.claimed-by-me{border-color:var(--success);background:var(--success-soft)}
    .mafia-seat.is-narrator{border-color:var(--text);background:var(--bg-subtle);cursor:default}
    .mafia-seat.is-narrator:hover{transform:none}
    .mafia-seat-info{flex:1;min-width:0}
    .mafia-seat-name{font-weight:700;color:var(--text);font-size:14px;line-height:1.2;letter-spacing:-.01em}
    .mafia-seat-status{font-size:10px;color:var(--text-secondary);font-weight:700;letter-spacing:.05em;text-transform:uppercase;margin-top:2px}
    .mafia-seat.claimed-by-me .mafia-seat-status{color:var(--success)}
    .mafia-seat.is-narrator .mafia-seat-status{color:var(--text)}

    .mafia-seat.mafia-seat-invite{
      border-style:dashed;border-color:var(--border-strong);background:var(--bg);
      color:var(--text-secondary);
    }
    .mafia-seat.mafia-seat-invite:hover{border-style:solid;border-color:var(--text);color:var(--text);background:var(--bg-subtle)}
    .mafia-seat-invite-icon{
      width:32px;height:32px;border-radius:50%;flex-shrink:0;
      display:flex;align-items:center;justify-content:center;
      background:var(--bg-subtle);color:var(--text-secondary);
      font-size:18px;font-weight:600;line-height:1;
    }
    .mafia-seat.mafia-seat-invite:hover .mafia-seat-invite-icon{background:var(--bg);color:var(--text)}
    .mafia-seat-invite .mafia-seat-name{color:var(--text-secondary);font-weight:600}
    .mafia-seat.mafia-seat-invite:hover .mafia-seat-name{color:var(--text)}

    .mafia-seats-hint{
      text-align:center;font-size:12px;color:var(--text-secondary);
      margin:0 0 14px;line-height:1.45;font-style:italic;
    }

    /* Role-mix preview — small read-only card showing what roles will be dealt
       given the current player count. Updates live as seats fill. */
    .mafia-rolemix-card{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:12px 14px;margin:0 0 14px;
    }
    .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{
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:12px 14px;margin:0 0 14px;
    }
    .mafia-optional-title{
      font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
      color:var(--text-secondary);margin-bottom:4px;
    }
    .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:11px 13px;background:var(--bg);
      border:1px solid var(--border);border-radius:var(--radius-sm);
      font-family:inherit;text-align:left;cursor:pointer;width:100%;
      transition:border-color .12s ease, background-color .12s ease;
    }
    .mafia-optional-row:hover{border-color:var(--text-secondary)}
    .mafia-optional-row[aria-pressed="true"]{
      padding:10px 12px;
      border:2px solid var(--text);
      background:rgba(0,0,0,.04);
    }
    [data-theme="dark"] .mafia-optional-row[aria-pressed="true"]{
      background:rgba(255,255,255,.06);
    }
    .mafia-optional-row-emoji{
      font-size:22px;line-height:1;flex-shrink:0;width:30px;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;margin-bottom:2px;
    }
    .mafia-optional-row-desc{
      display:block;
      font-size:12px;color:var(--text-secondary);line-height:1.4;
    }
    .mafia-optional-row-mark{
      flex-shrink:0;width:20px;height:20px;
      display:inline-flex;align-items:center;justify-content:center;
      color:var(--text);font-weight:800;
      visibility:hidden;
    }
    .mafia-optional-row[aria-pressed="true"] .mafia-optional-row-mark{
      visibility:visible;
    }

    /* ===== 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:8px}
    .mafia-narr-tool{
      flex:1;min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:7px;
      padding:11px 6px;border-radius:var(--radius-md);
      background:var(--bg-subtle);border:1px solid var(--border);
      font-size:13px;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}

    /* 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-left: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-left:17px;position:relative;
    }
    .mafia-narr-say::before{
      content:"\201C";position:absolute;left: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-left: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:left;
      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:right;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 (full-screen reveal) ========
       Mirrors the classic Mafia role card layout: large emoji + role name
       + description, with a "Reveal Role" button gating the reveal. The
       role is HIDDEN by default — player must tap Reveal to see it. */
    #screen-mafia-cards-role > main{
      padding:0;display:flex;flex-direction:column;min-height:100%;
    }
    .mafia-cards-role-screen{
      flex:1;display:flex;flex-direction:column;
      padding:32px 20px 28px;min-height:100%;
    }
    .mafia-cards-role-body{
      flex:1;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:14px;
    }
    .mafia-cards-role-hidden-icon{
      font-size:84px;line-height:1;opacity:.35;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;
    }
    .mafia-cards-role-emoji{
      font-size:88px;line-height:1;margin-bottom:6px;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;
    }
    .mafia-cards-role-toggle{
      margin-top:12px;display:inline-flex;align-items:center;gap:8px;
      padding:11px 22px;background:transparent;
      border:1.5px solid var(--text);border-radius:var(--radius-pill);
      color:var(--text);font:inherit;font-size:14px;font-weight:700;
      letter-spacing:.01em;cursor:pointer;
      transition:background-color .12s ease;
    }
    .mafia-cards-role-toggle:hover{background:var(--bg-hover)}
    .mafia-cards-role-toggle svg{width:14px;height:14px;flex-shrink:0}
    /* "How to win" card — win conditions shown to every player on their role
       screen (general info, not secret). Always visible, sits above the
       narrator-status footer. */
    .mafia-cards-role-win{
      margin:18px auto 0;max-width:340px;width:100%;
      background:var(--bg-subtle);border:1px solid var(--border);
      border-radius:var(--radius-md);padding:14px 16px;
      display:flex;flex-direction:column;gap:8px;text-align:left;
    }
    .mafia-cards-role-win-head{
      display:flex;align-items:center;gap:8px;
      font-size:13px;font-weight:800;color:var(--text);letter-spacing:.01em;
    }
    .mafia-cards-role-win-row{
      font-size:13px;line-height:1.5;color:var(--text-secondary);
      padding-left:16px;position:relative;
    }
    .mafia-cards-role-win-row::before{
      content:"";position:absolute;left:5px;top:8px;
      width:4px;height:4px;border-radius:50%;background:var(--text-tertiary);
    }
    /* How-to-play trigger on the player role screen — constrained to the same
       width as the win card above it (the lobby .howto-trigger is full-width). */
    .mafia-cards-role-screen .howto-trigger{
      max-width:340px;width:100%;margin:14px auto 0;
    }
    .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;
    }

    /* Prototype hint — same shape as .liar-prototype-hint. */
    .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-left:18px;position:relative}
    .mafia-rules-tips li::before{content:"";position:absolute;left: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 */
    @media(prefers-reduced-motion:reduce){
      .liar-reveal-cards .liar-card,.liar-cup-glass.tilting,.liar-win-crown{animation:none}
    }

    /* ===== 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:right;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:left;
      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}

    /* Info button */
    .info-btn{
      width:18px;height:18px;border-radius:50%;border:1px solid var(--border-strong);
      background:var(--bg);color:var(--text-secondary);
      display:inline-flex;align-items:center;justify-content:center;
      font-size:11px;font-weight:700;cursor:pointer;margin-left:6px;
      font-style:italic;font-family:Georgia,"Times New Roman",serif;line-height:1;padding:0;
      vertical-align:middle;flex-shrink:0;
    }
    .info-btn:hover{background:var(--bg-subtle);color:var(--text);border-color:var(--text)}
    .setting-row-label{display:inline-flex;align-items:center}

    /* Settings layout adjustments */
    .setting-row{flex-wrap:wrap;gap:10px}
    .setting-row .seg{flex-wrap:wrap}
    .setting-row .seg.full{width:100%;justify-content:center}
    /* Equal-width segments inside full-row controls — kills the grey "rail" by
       letting each option claim 1/N of the available width. Apple HIG + M3 default. */
    .setting-row .seg.full button{flex:1;text-align:center}

    /* 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);
    }

    /* Player picker (host picks mode) */
    .pick-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:20px}
    .pick-tile{
      display:flex;align-items:center;gap:10px;padding:14px;border:1px solid var(--border);
      border-radius:var(--radius-md);background:var(--bg);cursor:pointer;transition:all .15s ease;
      position:relative;
    }
    .pick-tile:hover{border-color:var(--text)}
    .pick-tile.done{opacity:.5;cursor:not-allowed}
    .pick-tile.done::after{
      content:"✓ done";position:absolute;top:6px;right:8px;
      font-size:10px;font-weight:600;color:var(--text-tertiary)
    }
    .pick-tile-name{font-weight:600;font-size:14px}

    /* ===== 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:left;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-left: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 + Chameleon lobbies) =====
       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:left;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-top{display:flex;justify-content:space-between;align-items:center;padding:10px 8px 0}
    .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;
    }
    .role-tag.tag-hotseat{background:#fde9e4;color:#c13515}
    .role-tag.tag-helper{background:#e6f5e7;color:var(--success)}
    .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%;right:-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;right:-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}

    /* ===== Chameleon how-to slide visuals ===== */
    .role-tag.tag-cham{background:#e8e6ff;color:#4f46c4}
    .role-tag.tag-knower{background:#e6f5e7;color:var(--success)}
    [data-theme="dark"] .role-tag.tag-cham{background:rgba(120,108,255,.18);color:#b9b1ff}
    [data-theme="dark"] .role-tag.tag-knower{background:var(--success-soft);color:var(--success)}
    /* Mini word-grid that fits inside an .mp mockup */
    .mp-grid-mini{
      display:grid;grid-template-columns:repeat(3,1fr);gap:3px;width:100%;
    }
    .mp-grid-cell{
      background:var(--bg);border:1px solid var(--border);border-radius:4px;
      font-size:6.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
      color:var(--text);padding:3px 1px;text-align:center;line-height:1.1;min-height:14px;
      display:flex;align-items:center;justify-content:center;
    }
    .mp-grid-cell.secret{background:#fff8e6;color:#a5760c;border-color:#f3d28a}
    [data-theme="dark"] .mp-grid-cell.secret{background:var(--winner-bg);color:var(--winner-text);border-color:var(--winner-text)}
    .mp-grid-cell.qmark{background:repeating-linear-gradient(45deg,var(--bg-subtle),var(--bg-subtle) 2px,var(--bg) 2px,var(--bg) 4px);color:var(--text-tertiary)}
    /* Cham slide-3 — clue bubbles */
    .visual-clues{display:flex;flex-direction:column;gap:8px;align-items:stretch;width:240px}
    .clue-bubble{
      display:flex;align-items:center;gap:8px;padding:6px 14px 6px 6px;
      background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-pill);
      opacity:0;
    }
    .clue-bubble.is-cham{border-color:#b9b1ff;background:rgba(120,108,255,.08)}
    .clue-avatar-sm{
      width:26px;height:26px;border-radius:50%;
      background:linear-gradient(135deg,#e4e4e4 0%,#cfcfcf 100%);
      display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;
      flex-shrink:0;
    }
    .clue-word{font-size:13px;font-weight:600;color:var(--text)}
    .clue-tag{margin-left:auto;font-size:9px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#4f46c4}
    [data-theme="dark"] .clue-tag{color:#b9b1ff}
    .howto-slide[data-slide="3"].active .clue-bubble{animation:clue-in .35s ease both}
    .howto-slide[data-slide="3"].active .clue-bubble:nth-child(1){animation-delay:.1s}
    .howto-slide[data-slide="3"].active .clue-bubble:nth-child(2){animation-delay:.55s}
    .howto-slide[data-slide="3"].active .clue-bubble:nth-child(3){animation-delay:1s}
    .howto-slide[data-slide="3"].active .clue-bubble:nth-child(4){animation-delay:1.45s}
    @keyframes clue-in{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}
    /* Cham slide-4 — vote faces */
    .visual-vote{display:flex;flex-direction:column;align-items:center;gap:14px}
    .vote-row{display:flex;gap:10px}
    .vote-face{
      width:54px;height:54px;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;
      position:relative;border:3px solid transparent;color:var(--text);
    }
    .vote-face.guilty{border-color:#4f46c4}
    .vote-face.guilty::after{content:"🦎";position:absolute;bottom:-8px;right:-8px;font-size:18px}
    [data-theme="dark"] .vote-face{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    .howto-slide[data-slide="4"].active .vote-face{animation:avatar-in .4s ease both}
    .howto-slide[data-slide="4"].active .vote-row > :nth-child(1){animation-delay:0s}
    .howto-slide[data-slide="4"].active .vote-row > :nth-child(2){animation-delay:.1s}
    .howto-slide[data-slide="4"].active .vote-row > :nth-child(3){animation-delay:.2s}
    .howto-slide[data-slide="4"].active .vote-row > :nth-child(4){animation-delay:.3s}
    .howto-slide[data-slide="4"].active .vote-face.guilty{
      animation:avatar-in .4s ease both,vote-pulse 1.6s 1s ease infinite;
    }
    @keyframes vote-pulse{0%,100%{box-shadow:0 0 0 0 rgba(79,70,196,0)}50%{box-shadow:0 0 0 8px rgba(79,70,196,.22)}}

    /* ===== Liar's Cup how-to slide visuals ===== */
    .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}
    /* Liar slide-2 — single phone with hand + table card */
    .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)}}
    /* Liar slide-2 — mini opponents row inside the phone mockup (shows hand counts) */
    .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 5px 2px 3px;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}

    /* Liar slide-3 — split phones, play vs accuse */
    .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 6px 3px 4px;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){left:0;transform:rotate(-10deg)}
    .mp-played-cards span:nth-child(2){left:5px;transform:rotate(8deg)}
    .howto-slide[data-slide="3"].active .mp-played-badge{animation:tap-glow 1.6s 1.1s ease infinite}
    /* Liar slide-4 — cup with chambers */
    .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-radius:var(--radius-md);padding:10px;
      display:inline-block;margin:14px 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:rgba(255,255,255,.65);margin-top:8px;
    }

    /* ===== Recommended setup button ===== */
    .btn-recommended{
      width:100%;display:flex;align-items:center;gap:12px;padding:12px 14px;
      background:linear-gradient(135deg,#f9f9f9 0%,#fff 100%);
      border:1px solid var(--border);border-radius:var(--radius-md);
      cursor:pointer;margin-bottom:12px;text-align:left;font:inherit;color:inherit;
      transition:all .2s ease;
    }
    .btn-recommended:hover{border-color:var(--text);transform:translateY(-1px)}
    .btn-recommended-icon{
      font-size:18px;width:32px;height:32px;border-radius:50%;
      background:var(--bg-subtle);display:flex;align-items:center;justify-content:center;flex-shrink:0;
    }
    .btn-recommended-text{flex:1;min-width:0}
    .btn-recommended-title{font-weight:600;font-size:14px;letter-spacing:-.005em}
    .btn-recommended-sub{font-size:12px;color:var(--text-secondary);margin-top:1px}
    /* Selected state: single 2px border in var(--text). Padding shrinks by 1px to keep total
       (border+padding) constant — no layout shift on toggle. ONE drawing layer = perfectly
       uniform around the rounded corners. Don't stack border + inset box-shadow (corner radii
       differ by border-width, the two layers don't merge cleanly). */
    .btn-recommended.applied{
      border:2px solid var(--text);
      padding:11px 13px;
    }

    /* ===== Role splash screen ===== */
    #screen-splash{background:var(--bg)}
    .splash{
      min-height:100vh;display:flex;flex-direction:column;padding:32px 24px;
      align-items:center;justify-content:center;text-align:center;cursor:pointer;
    }
    .splash-emoji{
      font-size:88px;line-height:1;margin-bottom:24px;
      animation:splash-emoji .6s cubic-bezier(.34,1.56,.64,1) both;
    }
    @keyframes splash-emoji{
      from{opacity:0;transform:scale(.4) rotate(-12deg)}
      to{opacity:1;transform:scale(1) rotate(0)}
    }
    .splash-label{
      font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.14em;
      color:var(--text-secondary);margin-bottom:6px;opacity:0;
      animation:splash-fade .5s .2s ease both;
    }
    .splash-name{
      font-size:38px;font-weight:800;letter-spacing:-.02em;margin-bottom:8px;
      opacity:0;animation:splash-fade .5s .3s ease both;
    }
    .splash-role{
      font-size:18px;font-weight:600;color:var(--text);margin-bottom:18px;
      opacity:0;animation:splash-fade .5s .4s ease both;
    }
    .splash-context{
      font-size:14px;color:var(--text-secondary);margin-bottom:40px;line-height:1.5;max-width:300px;
      opacity:0;animation:splash-fade .5s .5s ease both;
    }
    @keyframes splash-fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
    .splash-cta{
      display:inline-flex;align-items:center;gap:8px;font-size:14px;font-weight:600;
      color:var(--text-secondary);padding:12px 22px;border-radius:var(--radius-pill);
      background:var(--bg-subtle);
      animation:splash-cta 1.6s ease-out infinite;
    }
    @keyframes splash-cta{0%,100%{opacity:.7;transform:scale(1)}50%{opacity:1;transform:scale(1.03)}}

    /* ===== Coach marks ===== */
    .coach-overlay{
      position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:250;
      display:none;
    }
    .coach-overlay.active{display:block;animation:coach-fade .3s ease both}
    @media(min-width:600px){
      .coach-overlay{max-width:480px;left:50%;transform:translateX(-50%)}
    }
    @keyframes coach-fade{from{opacity:0}to{opacity:1}}
    .coach-tip{
      position:absolute;background:var(--text);color:var(--bg);
      padding:10px 14px;border-radius:10px;font-size:13px;font-weight:500;line-height:1.35;
      max-width:200px;box-shadow:0 6px 16px rgba(0,0,0,.35);
    }
    .coach-tip strong{font-weight:700}
    .coach-tip::after{
      content:"";position:absolute;width:0;height:0;
      border-left:8px solid transparent;border-right:8px solid transparent;
    }
    .coach-tip-timer{top:160px;left:50%;transform:translateX(-50%);text-align:center}
    .coach-tip-timer::after{top:-9px;left:50%;transform:translateX(-50%);border-bottom:10px solid var(--text)}
    .coach-tip-skip{bottom:110px;left:14px}
    .coach-tip-skip::after{bottom:-9px;left:34px;border-top:10px solid var(--text)}
    .coach-tip-got{bottom:110px;right:14px}
    .coach-tip-got::after{bottom:-9px;right:34px;border-top:10px solid var(--text)}
    .coach-dismiss{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      background:#fff;color:var(--text);border:none;border-radius:var(--radius-pill);
      padding:12px 22px;font-weight:700;font-size:14px;cursor:pointer;
      box-shadow:0 6px 16px rgba(0,0,0,.3);white-space:nowrap;
    }
    .coach-dismiss:hover{transform:translate(-50%,-50%) scale(1.03)}

    /* ============================================================
       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-outline{background:var(--surface)}
    [data-theme="dark"] .chip.active{color:var(--on-primary)}
    [data-theme="dark"] .hotseat-thumb.classic{background:linear-gradient(135deg,#26262a 0%,#3a3a3e 100%)}
    [data-theme="dark"] .hotseat-thumb.mafia{background:linear-gradient(135deg,#1e293b 0%,#334155 100%)}
    [data-theme="dark"] .avatar{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    [data-theme="dark"] .avatar-lg{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    [data-theme="dark"] .login-logo{color:var(--on-primary)}
    [data-theme="dark"] .room-code-card{background:linear-gradient(135deg,var(--room-grad-from) 0%,var(--room-grad-to) 100%)}
    [data-theme="dark"] .sticky-bottom{background:linear-gradient(180deg,rgba(14,14,16,0) 0%,var(--bg) 24px)}
    [data-theme="dark"] .btn-give-up{background:var(--surface);border-color:var(--border-strong);color:var(--text)}
    [data-theme="dark"] .btn-give-up:hover{background:var(--danger-soft);border-color:var(--danger);color:var(--danger)}
    [data-theme="dark"] .btn-got-it{color:#fff}
    [data-theme="dark"] .btn-got-it:hover{background:var(--success-hover);border-color:var(--success-hover)}
    [data-theme="dark"] .coach-info{background:var(--surface-elevated);color:var(--text);box-shadow:0 10px 28px rgba(0,0,0,.7)}
    [data-theme="dark"] .coach-dismiss-new{color:var(--on-primary)}
    [data-theme="dark"] .coach-tip-arrow{background:var(--surface-elevated);color:var(--text);box-shadow:0 8px 18px rgba(0,0,0,.55)}
    [data-theme="dark"] .coach-tip-arrow::after{border-top-color:var(--surface-elevated)}
    [data-theme="dark"] .coach-tip{background:var(--surface-elevated);color:var(--text);box-shadow:0 6px 16px rgba(0,0,0,.5)}
    [data-theme="dark"] .coach-tip::after{border-top-color:var(--surface-elevated)}
    [data-theme="dark"] .coach-tip-timer::after{border-bottom-color:var(--surface-elevated)}
    [data-theme="dark"] .coach-tip-skip::after{border-top-color:var(--surface-elevated)}
    [data-theme="dark"] .coach-tip-got::after{border-top-color:var(--surface-elevated)}
    [data-theme="dark"] .coach-dismiss-arrow{background:var(--surface-elevated);color:var(--text);box-shadow:0 8px 20px rgba(0,0,0,.55)}
    [data-theme="dark"] .coach-dismiss{background:var(--surface-elevated);color:var(--text);box-shadow:0 6px 16px rgba(0,0,0,.5)}
    [data-theme="dark"] .view-toggle button.active{background:var(--surface-elevated);box-shadow:0 1px 2px rgba(0,0,0,.4)}
    [data-theme="dark"] .seg button.active{background:var(--surface-elevated);box-shadow:0 1px 2px rgba(0,0,0,.4)}
    [data-theme="dark"] .word-list-status.correct{background:var(--success-soft);color:var(--success)}
    [data-theme="dark"] .word-list-status.skipped{background:var(--danger-soft-2);color:var(--danger)}
    [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"] .role-tag.tag-hotseat{background:var(--danger-soft-2);color:var(--danger)}
    [data-theme="dark"] .role-tag.tag-helper{background:var(--success-soft);color:var(--success)}
    [data-theme="dark"] .rotation-avatar{background:linear-gradient(135deg,var(--avatar-grad-from) 0%,var(--avatar-grad-to) 100%)}
    /* QR — keep the wrapper white so the standard black-on-white QR stays
       scannable AND pops nicely against the dark room-code-card gradient. */
    [data-theme="dark"] .room-qr-wrap{background:#fff}
    [data-theme="dark"] .room-qr{background:#fff}
    [data-theme="dark"] .btn-recommended{background:linear-gradient(135deg,var(--surface) 0%,var(--surface-elevated) 100%)}
    /* 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}
    [data-theme="dark"] .word-card.flash-correct{animation:card-correct-dark .55s ease}
    [data-theme="dark"] .word-card.flash-skip{animation:card-skip-dark .55s ease}
    @keyframes card-correct-dark{
      0%{background:var(--bg);border-color:var(--border);transform:scale(1)}
      25%{background:var(--success-soft);border-color:var(--success);transform:scale(1.03)}
      100%{background:var(--bg);border-color:var(--border);transform:scale(1)}
    }
    @keyframes card-skip-dark{
      0%{background:var(--bg);border-color:var(--border);transform:scale(1)}
      25%{background:var(--danger-soft);border-color:var(--danger);transform:scale(1.02)}
      100%{background:var(--bg);border-color:var(--border);transform:scale(1)}
    }
    [data-theme="dark"] .play-stat strong.flash-up{animation:score-bump-dark .45s ease}
    @keyframes score-bump-dark{
      0%{transform:scale(1);color:var(--text)}
      40%{transform:scale(1.45);color:var(--success)}
      100%{transform:scale(1);color:var(--text)}
    }

    /* ===== 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);
      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;
      right: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-right: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:left;
      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(--text);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}

    /* ===== Wheel test picker card (Lab demo only) ===== */
    .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:left;
      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);right: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}

    /* ----- Scene 1: table with phones around it ----- */
    .mh-table{
      position:relative;width:280px;height:280px;
    }
    .mh-table-felt{
      position:absolute;inset:60px;border-radius:50%;
      background:radial-gradient(circle, rgba(34,197,94,.18), rgba(34,197,94,0) 70%);
      opacity:0;transform:scale(.7);
      transition:opacity .6s ease, transform .6s ease;
    }
    .mh-scene[data-scene="1"].is-active .mh-table-felt{opacity:1;transform:scale(1)}
    .mh-phone{
      position:absolute;width:36px;height:56px;
      border-radius:8px;background:linear-gradient(180deg,#2a2a32,#1a1a20);
      border:1.5px solid rgba(255,255,255,.12);
      display:flex;align-items:center;justify-content:center;
      opacity:0;transform:scale(.6) translateY(8px);
      transition:opacity .45s cubic-bezier(.34,1.56,.64,1), transform .45s cubic-bezier(.34,1.56,.64,1);
    }
    .mh-scene[data-scene="1"].is-active .mh-phone{opacity:1;transform:scale(1) translateY(0)}
    .mh-phone-screen{
      width:80%;height:75%;border-radius:4px;
      background:linear-gradient(135deg,#fbbf24,#f59e0b);opacity:.85;
    }
    .mh-phone-badge{
      position:absolute;top:-10px;right:-10px;width:22px;height:22px;border-radius:50%;
      background:#fbbf24;color:#0a0a0d;font-size:12px;
      display:flex;align-items:center;justify-content:center;
      box-shadow:0 2px 8px rgba(251,191,36,.4);
    }
    .mh-phone--1{top:0;left:50%;transform-origin:center;transform:translateX(-50%)}
    .mh-phone--2{top:30%;right:0}
    .mh-phone--3{bottom:30%;right:0}
    .mh-phone--4{bottom:0;left:50%;transform:translateX(-50%)}
    .mh-phone--5{bottom:30%;left:0}
    .mh-phone--narrator{top:30%;left:0}
    .mh-scene[data-scene="1"].is-active .mh-phone--1{transition-delay:.15s}
    .mh-scene[data-scene="1"].is-active .mh-phone--2{transition-delay:.30s}
    .mh-scene[data-scene="1"].is-active .mh-phone--3{transition-delay:.45s}
    .mh-scene[data-scene="1"].is-active .mh-phone--4{transition-delay:.60s}
    .mh-scene[data-scene="1"].is-active .mh-phone--5{transition-delay:.75s}
    .mh-scene[data-scene="1"].is-active .mh-phone--narrator{transition-delay:1.5s}
    .mh-phone--narrator{
      background:linear-gradient(180deg,#3a2a08,#1a1a20);
      border-color:rgba(251,191,36,.4);
    }
    .mh-phone--narrator .mh-phone-screen{
      background:linear-gradient(135deg,#fbbf24,#d97706);
    }

    /* ----- Scene 2: role cards flipping ----- */
    .mh-cards{
      display:grid;grid-template-columns:repeat(3,1fr);gap:14px;
      width:100%;max-width:340px;
    }
    .mh-card{
      aspect-ratio:3/4;border-radius:12px;
      background:linear-gradient(135deg,#2a2a32,#1a1a20);
      border:1.5px solid rgba(255,255,255,.12);
      display:flex;flex-direction:column;align-items:center;justify-content:center;
      gap:6px;
      transform-style:preserve-3d;perspective:600px;
      opacity:0;transform:rotateY(180deg);
      transition:opacity .5s ease, transform .7s cubic-bezier(.34,1.2,.64,1);
    }
    .mh-card-face{font-size:32px;display:block}
    .mh-card-label{
      font-size:10px;font-weight:700;letter-spacing:.08em;
      text-transform:uppercase;color:rgba(255,255,255,.65);
    }
    .mh-card[data-role="mafia"]{border-color:rgba(239,68,68,.35)}
    .mh-card[data-role="doctor"]{border-color:rgba(34,197,94,.35)}
    .mh-card[data-role="detective"]{border-color:rgba(59,130,246,.35)}
    .mh-card[data-role="villager"]{border-color:rgba(168,168,168,.35)}
    .mh-scene[data-scene="2"].is-active .mh-card{opacity:1;transform:rotateY(0)}
    .mh-scene[data-scene="2"].is-active .mh-card--1{transition-delay:.2s}
    .mh-scene[data-scene="2"].is-active .mh-card--2{transition-delay:.35s}
    .mh-scene[data-scene="2"].is-active .mh-card--3{transition-delay:.5s}
    .mh-scene[data-scene="2"].is-active .mh-card--4{transition-delay:.65s}
    .mh-scene[data-scene="2"].is-active .mh-card--5{transition-delay:.8s}
    .mh-scene[data-scene="2"].is-active .mh-card--6{transition-delay:.95s}

    /* ----- Scene 3: night ----- */
    .mh-scene-visual--night{flex-direction:column;gap:20px;width:100%}
    .mh-night-sky{
      position:relative;width:100%;height:90px;
      background:linear-gradient(180deg, rgba(30,30,60,.6), transparent);
      border-radius:12px;display:flex;align-items:center;justify-content:center;overflow:hidden;
    }
    .mh-moon{font-size:42px;
      animation:mh-moon-glow 3s ease-in-out infinite alternate;
    }
    @keyframes mh-moon-glow{from{filter:drop-shadow(0 0 6px rgba(255,255,255,.3))} to{filter:drop-shadow(0 0 14px rgba(255,255,255,.6))}}
    .mh-star{position:absolute;width:2px;height:2px;background:#fff;border-radius:50%;opacity:0;
      animation:mh-twinkle 2.2s ease-in-out infinite;
    }
    .mh-star--a{top:18%;left:15%;animation-delay:.2s}
    .mh-star--b{top:30%;left:75%;animation-delay:.7s}
    .mh-star--c{top:50%;left:35%;animation-delay:1.2s}
    .mh-star--d{top:25%;left:55%;animation-delay:1.6s}
    @keyframes mh-twinkle{0%,100%{opacity:0}50%{opacity:1}}
    .mh-night-roles{
      display:flex;gap:16px;justify-content:center;width:100%;flex-wrap:wrap;
    }
    .mh-night-role{
      flex:1;min-width:90px;max-width:120px;
      padding:14px 8px;border-radius:12px;
      background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);
      display:flex;flex-direction:column;align-items:center;gap:8px;
      opacity:0;transform:translateY(10px);position:relative;
      transition:opacity .5s ease, transform .5s ease;
    }
    .mh-night-role-emoji{font-size:32px}
    .mh-night-role-label{
      font-size:11px;font-weight:600;color:rgba(255,255,255,.75);
      letter-spacing:.02em;text-align:center;
    }
    .mh-scene[data-scene="3"].is-active .mh-night-role{opacity:1;transform:none}
    .mh-scene[data-scene="3"].is-active .mh-night-role--mafia    {transition-delay:.5s}
    .mh-scene[data-scene="3"].is-active .mh-night-role--doctor   {transition-delay:3.5s}
    .mh-scene[data-scene="3"].is-active .mh-night-role--detective{transition-delay:6.5s}
    .mh-night-role--mafia    {border-color:rgba(239,68,68,.4)}
    .mh-night-role--doctor   {border-color:rgba(34,197,94,.4)}
    .mh-night-role--detective{border-color:rgba(59,130,246,.4)}
    .mh-thumb{
      position:absolute;top:-12px;right:-8px;font-size:22px;
      opacity:0;transform:scale(.5);
      transition:opacity .35s ease 7.5s, transform .35s cubic-bezier(.34,1.56,.64,1) 7.5s;
    }
    .mh-scene[data-scene="3"].is-active .mh-thumb{opacity:1;transform:scale(1)}

    /* ----- Scene 4: morning ----- */
    .mh-scene-visual--day{flex-direction:column;gap:14px;width:100%}
    .mh-day-sky{
      width:100%;height:80px;border-radius:12px;
      background:linear-gradient(180deg, #fde68a 0%, #fbbf24 100%);
      display:flex;align-items:center;justify-content:center;overflow:hidden;
      opacity:0;transition:opacity .6s ease;
    }
    .mh-scene[data-scene="4"].is-active .mh-day-sky{opacity:.92}
    .mh-sun{font-size:42px;
      animation:mh-sun-pulse 4s ease-in-out infinite alternate;
    }
    @keyframes mh-sun-pulse{from{transform:scale(1)} to{transform:scale(1.08)}}
    .mh-day-scene{
      width:100%;display:flex;align-items:center;gap:20px;padding:10px;
    }
    .mh-day-victim{
      flex-shrink:0;width:80px;text-align:center;
      opacity:0;transform:scale(.7);
      transition:opacity .5s ease .4s, transform .5s cubic-bezier(.34,1.56,.64,1) .4s;
    }
    .mh-scene[data-scene="4"].is-active .mh-day-victim{opacity:1;transform:scale(1)}
    .mh-day-victim-emoji{font-size:46px;line-height:1}
    .mh-day-victim-label{
      font-size:11px;color:rgba(255,255,255,.5);margin-top:4px;
      text-decoration:line-through;
    }
    .mh-day-bubbles{flex:1;display:flex;flex-direction:column;gap:6px;align-items:flex-start;}
    .mh-bubble{
      padding:8px 12px;border-radius:14px 14px 14px 4px;
      background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.12);
      font-size:13px;color:rgba(255,255,255,.9);
      opacity:0;transform:translateX(-12px);
      transition:opacity .35s ease, transform .35s ease;
    }
    .mh-scene[data-scene="4"].is-active .mh-bubble--1{opacity:1;transform:none;transition-delay:1.2s}
    .mh-scene[data-scene="4"].is-active .mh-bubble--2{opacity:1;transform:none;transition-delay:2.2s}
    .mh-scene[data-scene="4"].is-active .mh-bubble--3{opacity:1;transform:none;transition-delay:3.2s}

    /* ----- Scene 5: vote ----- */
    .mh-vote{position:relative;width:280px;height:240px}
    .mh-vote-target{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
      width:90px;height:120px;
      display:flex;flex-direction:column;align-items:center;justify-content:center;
      gap:8px;z-index:2;
    }
    .mh-vote-target-face{
      font-size:54px;
      opacity:0;transform:scale(.5);
      transition:opacity .4s ease, transform .4s cubic-bezier(.34,1.56,.64,1);
    }
    .mh-scene[data-scene="5"].is-active .mh-vote-target-face{opacity:1;transform:scale(1);transition-delay:.2s}
    .mh-vote-target-tally{display:flex;gap:4px}
    .mh-tally-pip{
      width:6px;height:6px;border-radius:50%;background:#ef4444;
      opacity:0;transform:scale(0);
      transition:opacity .25s ease, transform .25s cubic-bezier(.34,1.56,.64,1);
    }
    .mh-scene[data-scene="5"].is-active .mh-tally-pip:nth-child(1){opacity:1;transform:scale(1);transition-delay:2.0s}
    .mh-scene[data-scene="5"].is-active .mh-tally-pip:nth-child(2){opacity:1;transform:scale(1);transition-delay:2.3s}
    .mh-scene[data-scene="5"].is-active .mh-tally-pip:nth-child(3){opacity:1;transform:scale(1);transition-delay:2.6s}
    .mh-scene[data-scene="5"].is-active .mh-tally-pip:nth-child(4){opacity:1;transform:scale(1);transition-delay:2.9s}
    .mh-pointer{
      position:absolute;font-size:28px;
      opacity:0;
      transition:opacity .35s ease;
    }
    .mh-pointer--1{top:10%;left:10%;transform:rotate(-25deg)}
    .mh-pointer--2{top:10%;right:10%;transform:rotate(25deg) scaleX(-1)}
    .mh-pointer--3{bottom:10%;left:10%;transform:rotate(25deg)}
    .mh-pointer--4{bottom:10%;right:10%;transform:rotate(-25deg) scaleX(-1)}
    .mh-scene[data-scene="5"].is-active .mh-pointer--1{opacity:1;transition-delay:1.8s}
    .mh-scene[data-scene="5"].is-active .mh-pointer--2{opacity:1;transition-delay:2.1s}
    .mh-scene[data-scene="5"].is-active .mh-pointer--3{opacity:1;transition-delay:2.4s}
    .mh-scene[data-scene="5"].is-active .mh-pointer--4{opacity:1;transition-delay:2.7s}
    .mh-vote-reveal{
      position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);
      font-size:80px;
      filter:drop-shadow(0 0 24px rgba(239,68,68,.6));
      transition:transform .5s cubic-bezier(.34,1.56,.64,1);
      z-index:3;
    }
    .mh-scene[data-scene="5"].is-active .mh-vote-reveal{
      transform:translate(-50%,-50%) scale(1);
      transition-delay:4.5s;
    }

    /* ----- Scene 6: win ----- */
    .mh-win{
      display:flex;flex-direction:column;align-items:center;gap:24px;
    }
    .mh-scales{position:relative}
    .mh-scale-arm{
      display:flex;align-items:center;gap:20px;
      transform:rotate(0deg);transform-origin:center;
      animation:mh-tip-tip 4s ease-in-out infinite alternate;
    }
    @keyframes mh-tip-tip{
      0%{transform:rotate(-6deg)} 100%{transform:rotate(6deg)}
    }
    .mh-scale-side{
      width:90px;height:80px;
      display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
      background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);
      border-radius:12px;
    }
    .mh-scale-emoji{font-size:32px}
    .mh-scale-label{font-size:11px;font-weight:700;letter-spacing:.05em;color:rgba(255,255,255,.75)}
    .mh-scale-pivot{
      width:12px;height:12px;border-radius:50%;background:#fbbf24;
      box-shadow:0 0 16px rgba(251,191,36,.5);
    }
    .mh-tagline{
      font-size:14px;font-style:italic;color:rgba(255,255,255,.7);
      letter-spacing:.01em;
      opacity:0;
      transition:opacity .6s ease 2.5s;
    }
    .mh-scene[data-scene="6"].is-active .mh-tagline{opacity:1}

    /* ----- 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%);
    }
    .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{
      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:right;
      font-variant-numeric:tabular-nums;
    }

