/* ═══════════════════════════════════════════════════════════════
   WILDCARD — app base styles (lobby, room, moderation)
   Loaded by the chat app pages. Contains:
     • CSS variables, reset, body baseline
     • Toasts, keyframes, scrollbar
     • Forms, buttons, modals
     • Top navigation
     • Video tile & grid (shared by lobby + room)
     • Setup-preview, pill toggle, auth panel
   ═══════════════════════════════════════════════════════════════ */

/* ── Variables ── */
:root {
    /* Accent colour — change these 3 lines to re-theme the whole site. */
    --primary: #f02070;                          /* pink (matches the front page) */
    --primary-rgb: 240, 32, 112;                 /* same, as RGB for rgba() */
    --primary-hover: #ff4f93;                    /* lighter pink */
    --primary-glow: rgba(var(--primary-rgb), 0.4);
    --accent: #6c63ff;
    --accent-glow: rgba(108, 99, 255, 0.5);
    --deep-blue: #1c4870;   /* cog hover + toggle ON — matches the chat 'mine' bubble */
    --bg-gradient-start: #0a0e27;
    --bg-gradient-end: #1a1d35;
    --dark-bg: #0d0d0d;
    --dark-panel: #15161d;
    --dark-border: #2a2d3a;
    --text-primary: #e0e0e0;
    --text-secondary: #808899;

    /* ── Theme tokens — every theme-able surface reads these; a theme is just a
       redefinition of this block (see [data-theme=...]). Defaults below ARE the
       dark "pleasure" theme, so pleasure/business render exactly as before. */
    --app-bg: linear-gradient(125deg, #0a1733 0%, #110a1c 55%, #280a13 100%);  /* page backdrop */
    --surface:        rgba(13, 15, 22, 0.92);   /* cards, panels, drawers */
    --surface-2:      #161a26;                   /* inset: avatars, inputs, wells */
    --surface-raised: #15161d;                   /* nav, modal, toast */
    --border:         rgba(255, 255, 255, 0.08); /* faint hairline */
    --border-strong:  rgba(255, 255, 255, 0.18); /* visible divider */
    --on-accent:      #ffffff;                   /* text on a --primary fill (pink → white) */
    --ctrl-ink:       #fff;                       /* icons/outlines that sit directly on --app-bg */

    /* Translucent "ink" overlays for borders, hovers and wells. White on the
       dark themes (defaults below = the original values, so nothing changes);
       vacation flips the whole scale to black so they're visible on light. */
    --ovl-03: rgba(255,255,255,0.03); --ovl-04: rgba(255,255,255,0.04);
    --ovl-05: rgba(255,255,255,0.05); --ovl-06: rgba(255,255,255,0.06);
    --ovl-07: rgba(255,255,255,0.07); --ovl-08: rgba(255,255,255,0.08);
    --ovl-09: rgba(255,255,255,0.09); --ovl-10: rgba(255,255,255,0.10);
    --ovl-12: rgba(255,255,255,0.12); --ovl-14: rgba(255,255,255,0.14);
    --ovl-15: rgba(255,255,255,0.15); --ovl-16: rgba(255,255,255,0.16);
    --ovl-18: rgba(255,255,255,0.18); --ovl-22: rgba(255,255,255,0.22);

    --success: #00ff88;
    --warning: #ffa500;
    --danger: #ff4757;
    --radius: 10px;
    --radius-sm: 5px;
    --radius-lg: 15px;
    --spacing: 15px;
    --transition: all 0.3s ease;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: "Exo 2", -apple-system, BlinkMacSystemFont, 'Segoe UI', Tahoma, sans-serif;
    background: #000;
    color: var(--text-primary);
    min-height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
}

.hidden { display: none !important; }

/* ── Keyframes ── */
@keyframes slideIn  { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(400px); opacity: 0; } }
@keyframes shake    { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
@keyframes pulse    { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.7; transform: scale(1.1); } }
@keyframes callPulse { 0%,100% { box-shadow: 0 4px 20px rgba(245,158,11,0.4); } 50% { box-shadow: 0 4px 32px rgba(245,158,11,0.8); } }

/* ── Toasts ── */
/* Notices drop in from the top, centred under the nav, and stack downward.
   pointer-events:none so the transient strip never blocks the UI beneath it. */
.toast-container {
    position: fixed;
    top: 64px;                 /* just below the 56px nav */
    left: 50%;
    transform: translateX(-50%);
    z-index: 10000;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-width: 92vw;
    pointer-events: none;
}

/* Flat card — solid surface, thin border, a coloured left accent + type glyph.
   No glow; the subtle drop shadow is neutral, just for lift. All colours are
   theme tokens, so it reads correctly in pleasure / business / vacation. */
.toast {
    display: flex;
    align-items: center;
    gap: 9px;
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-left: 3px solid var(--primary);
    border-radius: var(--radius-sm);
    padding: 11px 16px;
    color: var(--text-primary);
    font-size: 0.86rem;
    box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.5);
    animation: toast-drop 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
    max-width: 420px;
}
.toast::before { font-weight: 700; font-size: 0.95rem; line-height: 1; }
.toast.info    { border-left-color: var(--primary); }
.toast.success { border-left-color: var(--success); }
.toast.success::before { content: '✓'; color: var(--success); }
.toast.error   { border-left-color: var(--danger); }
.toast.error::before   { content: '✕'; color: var(--danger); }

@keyframes toast-drop { from { transform: translateY(-14px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes toast-out  { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-14px); opacity: 0; } }

/* ── Avatar speech-bubble toasts (lobby only) ──────────────────────────────
   Light speech bubbles that appear BESIDE the call avatar, ALTERNATING right
   then left, vertically centred on it, with the tail on the edge facing the
   avatar pointing horizontally INTO it. The layer is a zero-size anchor at the
   avatar's centre; --av-r is half the avatar box so a bubble's inner edge lands
   just off the avatar's side (it shrinks with the avatar on mobile). Bubbles
   overlap in place rather than stacking, so a fast burst just fades in over the
   top and nothing runs off-screen. The layer lives inside .avatar-cluster
   (position:relative) so it tracks the avatar; only lobby.html renders it. */
.avatar-toast-layer {
    position: absolute;
    left: 50%;                         /* avatar's horizontal centre */
    top: 50%;                          /* avatar's vertical centre */
    width: 0;
    height: 0;
    z-index: 6;                        /* above .call-wave (0) and .speaker-row (1) */
    pointer-events: none;
    --av-r: 80px;                      /* half the 160px avatar box (desktop) */
}
.toast-bubble {
    position: absolute;
    top: 50%;
    /* The bubble's containing block (.avatar-toast-layer) is 0×0, so with width
       auto the browser shrink-to-fits against zero width and collapses the text
       to min-content (one word per line). width: max-content sizes it to a single
       line instead, and max-width then wraps it only when it runs out of room.
       (block, not the inherited .toast flex, so the text run isn't a flex item.) */
    display: block;
    width: max-content;
    max-width: min(280px, calc(50vw - var(--av-r) - 14px));
    padding: 10px 14px;
    line-height: 1.34;
    /* Light bubble in every theme (not the theme's surface token), with dark ink. */
    background: #ffffff;
    color: #16181d;
    border: 1px solid rgba(0, 0, 0, 0.07);
    border-radius: 16px;
    /* Classy layered shadow: a tight contact shadow + a soft, wide ambient one. */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.10), 0 18px 44px -12px rgba(0, 0, 0, 0.30);
    animation: bubble-pop-right 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* No type glyph on bubbles — just the message. */
.toast-bubble::before { content: none !important; }
/* Tail — a rotated square poking out the inner edge, pointing sideways at the avatar. */
.toast-bubble::after {
    content: '';
    position: absolute;
    top: 50%;
    margin-top: -7px;
    width: 13px;
    height: 13px;
    background: #ffffff;
    transform: rotate(45deg);
}
/* Right bubble: sits to the RIGHT of the avatar; tail on its left edge points left at it. */
.toast-bubble.side-right {
    left: calc(var(--av-r) + 10px);
    transform-origin: left center;
    animation-name: bubble-pop-right;
}
.toast-bubble.side-right::after {
    left: -6px;
    border-left: 1px solid rgba(0, 0, 0, 0.07);
    border-bottom: 1px solid rgba(0, 0, 0, 0.07);
}
/* Left bubble: sits to the LEFT of the avatar; tail on its right edge points right at it. */
.toast-bubble.side-left {
    right: calc(var(--av-r) + 10px);
    transform-origin: right center;
    animation-name: bubble-pop-left;
}
.toast-bubble.side-left::after {
    right: -6px;
    border-top: 1px solid rgba(0, 0, 0, 0.07);
    border-right: 1px solid rgba(0, 0, 0, 0.07);
}
/* Slide out of the avatar's side as it fades in (origin = the tail edge). */
@keyframes bubble-pop-right {
    from { opacity: 0; transform: translate(-14px, -50%) scale(0.5); }
    to   { opacity: 1; transform: translate(0, -50%) scale(1); }
}
@keyframes bubble-pop-left {
    from { opacity: 0; transform: translate(14px, -50%) scale(0.5); }
    to   { opacity: 1; transform: translate(0, -50%) scale(1); }
}
@keyframes bubble-out {
    from { opacity: 1; transform: translate(0, -50%) scale(1); }
    to   { opacity: 0; transform: translate(0, -50%) scale(0.9); }
}
/* On mobile the avatar box shrinks to 80px, so the bubble hugs closer to it. */
@media (max-width: 800px) {
    .avatar-toast-layer { --av-r: 40px; }
}

/* ── Scrollbar ── */
::-webkit-scrollbar       { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--dark-bg); }
::-webkit-scrollbar-thumb { background: var(--primary); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--primary-hover); }

/* ── Form Elements ── */
.form-group { margin-bottom: 15px; }

.form-group label {
    display: block;
    margin-bottom: 6px;
    color: var(--text-primary);
    font-size: 0.85em;
    font-weight: 500;
}

.form-group input[type="text"],
.form-group input[type="email"],
.form-group input[type="password"],
.form-group select {
    width: 100%;
    padding: 10px 12px;
    background: var(--surface-2);
    border: 1px solid var(--dark-border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 0.9em;
    transition: var(--transition);
}
.form-group input:-webkit-autofill,
.form-group input:-webkit-autofill:hover,
.form-group input:-webkit-autofill:focus,
.form-group input:-webkit-autofill:active {
    -webkit-text-fill-color: var(--text-primary);
    -webkit-box-shadow: 0 0 0 1000px #15161d inset;
    caret-color: var(--text-primary);
}

.form-group input:focus,
.form-group select:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 15px var(--primary-glow), inset 0 0 10px rgba(var(--primary-rgb), 0.05);
    background: linear-gradient(145deg, #121218, #1a1b22);
}

.field-error {
    display: none;
    color: var(--danger);
    font-size: 0.75em;
    margin-top: 4px;
    animation: shake 0.3s ease;
}

.label-hint {
    font-size: 0.7rem;
    color: var(--text-secondary);
    font-weight: 400;
}

/* ── Buttons (modal/text variants — round action buttons live in lobby.css) ── */
.btn {
    padding: 12px 30px;
    border: none;
    border-radius: 25px;
    font-size: 1em;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition);
    display: inline-flex;
    align-items: center;
    gap: 10px;
    justify-content: center;
}

.btn-primary {
    background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
    color: #fff;
    box-shadow: 0 5px 15px var(--primary-glow);
    position: relative;
    overflow: hidden;
}

.btn-primary:hover {
    background: linear-gradient(135deg, var(--primary-hover) 0%, var(--accent) 100%);
    transform: scale(1.03);
    box-shadow: 0 8px 30px var(--primary-glow);
}

.btn:active { transform: scale(0.95); }

.btn-full { width: 100%; }

.btn-text {
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 0.8rem;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    transition: var(--transition);
    text-decoration: underline;
}
.btn-text:hover { color: var(--text-primary); }

.btn-icon-only {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-size: 1.3em;
    cursor: pointer;
    padding: 5px;
    transition: var(--transition);
}
.btn-icon-only:hover { color: var(--primary); transform: scale(1.1); }

/* ── Modals ── */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(10, 14, 39, 0.9);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
}

.modal-content {
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: 0 24px 70px -10px rgba(0, 0, 0, 0.85);
    max-width: 500px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    font-family: "Exo 2", sans-serif;   /* default for all modal text */
    scrollbar-width: thin;
    scrollbar-color: var(--dark-border) transparent;
}
/* Subtle dark scrollbar in modals — overrides the global peach thumb (styles.css). */
.modal-content::-webkit-scrollbar { width: 8px; }
.modal-content::-webkit-scrollbar-track { background: transparent; }
.modal-content::-webkit-scrollbar-thumb { background: var(--dark-border); border-radius: 4px; }
.modal-content::-webkit-scrollbar-thumb:hover { background: #3a3d4a; }

.modal-header {
    padding: 18px 22px;
    border-bottom: 1px solid var(--ovl-08);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h2 { color: var(--primary); font-size: 1.2rem; font-weight: 700; }
.modal-close-x { background: none; border: none; color: var(--text-secondary); font-size: 1.1rem; line-height: 1; cursor: pointer; padding: 2px 4px; transition: var(--transition); }
.modal-close-x:hover { color: var(--text-primary); }
.modal-body     { padding: 24px 22px; }
.modal-footer   { padding: 18px 22px; border-top: 1px solid var(--ovl-08); display: flex; justify-content: flex-end; }
.modal-narrow   { max-width: 380px; }

/* ── Top Navigation (shared by lobby + room) ── */
.main-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 56px;
    padding: 0 20px;
    background: var(--surface-raised);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 100;
    flex-shrink: 0;
}

/* Classy sharp sans across the bar; mono kept only for the profile label. */
.main-nav, .nav-item { font-family: "Exo 2", system-ui, sans-serif; }
.nav-profile-btn { font-family: 'Space Mono', ui-monospace, monospace; }

/* Centre group is absolutely pinned to the bar's true centre so it stays dead-
   centre regardless of side-zone content widths. Equal-flex alone drifts once one
   side (e.g. the left logo + presence readout) outgrows its half. .main-nav is
   position:sticky, so it anchors this absolute child. */
.nav-left   { display: flex; align-items: center; gap: 10px; min-width: 120px; flex: 1; }
.nav-center { display: flex; align-items: stretch; gap: 4px; position: absolute; left: 50%; top: 0; height: 100%; transform: translateX(-50%); }
.nav-right  { display: flex; align-items: center; gap: 9px; min-width: 120px; justify-content: flex-end; padding-right: 2px; flex: 1; }

/* In-app nav logo (lobby + room) — links back to landing home.
   ventlogo-outline.png is a transparent dark-stroke raster; we mask it and paint
   the brand cyan through, so it matches the theme and can glow on hover. */
.nav-logo-link { display: inline-flex; align-items: center; line-height: 0; }
.nav-logo {
    display: block;
    width: 51px; height: 34px;                 /* PNG is 3:2 (1536×1024) */
    background: #fff;                           /* white */
    -webkit-mask: url(/ventlogo-outline.png?v=1) left center/contain no-repeat;
            mask: url(/ventlogo-outline.png?v=1) left center/contain no-repeat;
    transition: var(--transition);
}
.nav-logo-link:hover .nav-logo { filter: drop-shadow(0 0 5px rgba(255,255,255,0.45)); }

/* Presence — the live online count as a bare bordered pill: no fill, no dot.
   Online → green border + green number; queuing → both turn blue and flash. */
.nav-presence  {
    display: flex; align-items: center;
}

/* Bare bordered pill — no fill, sized to match the theme icon + hamburger so the
   nav-right cluster reads as one equally-sized, equally-spaced row. */
.presence-stat {
    display: inline-flex; align-items: center;
    height: 34px; padding: 0 13px;
    border-radius: 999px;
    background: none;
    border: 1px solid var(--border-strong);   /* token: subtle, adapts per theme */
    box-shadow: none;
    line-height: 1;
}
.presence-stat[hidden] { display: none; }
/* Green status dot before the count (online = green, queuing = primary). */
.presence-dot {
    width: 10px; height: 10px; border-radius: 2px;   /* square — every theme */
    background: #22c55e;
    box-shadow: 0 0 6px rgba(34, 197, 94, 0.6);
    margin-right: 8px; flex-shrink: 0;
}
.presence-val {
    display: inline-flex; align-items: center;
    font-family: "Exo 2", -apple-system, sans-serif;
    font-size: 0.95rem; font-weight: 700; color: #22c55e;   /* green count, matches the dot */
    text-shadow: none;
}
/* Queuing — dot + count turn primary and the pill gently pulses */
.presence-stat.active .presence-dot { background: var(--primary); box-shadow: 0 0 6px rgba(var(--primary-rgb), 0.6); }
.presence-stat.active .presence-val { color: var(--primary); }
.presence-stat.active {
    animation: nav-queue-pulse 1.6s ease-in-out infinite;
}
@keyframes nav-queue-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

/* Games stays a standalone button; everything else lives in the "Menu" overflow,
   a dropdown anchored under its button on every screen size. */
/* The Menu sits in a folder-style tab: an SVG draws the bar's bottom edge so it
   flows down and around the hamburger (a continuous notch, not a detached box). */
.nav-menu-wrap {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: 0 32px;
}
.nav-more-btn  { display: flex; }
/* White text across the Games / Menu buttons. */
.nav-center .nav-item { color: var(--text-primary); }
.nav-more-btn { position: relative; }   /* anchor for the unread badge that now rides the Menu button */

.nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 6px 12px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: var(--transition);
    white-space: nowrap;
}
.nav-item:hover  { color: var(--text-primary); background: var(--ovl-06); }
.nav-item.active { color: var(--primary); }
.nav-icon        { width: 18px; height: 18px; color: var(--text-primary); }
/* Menu is icon-only — white glyph with a pure grey shadow for depth. */
#nav-more .nav-icon { width: 30px; height: 30px; color: var(--ctrl-ink); filter: drop-shadow(0 1px 4px rgba(60,60,60,0.6)); }
#nav-more { padding: 4px; background: none; }
#nav-more:hover { background: var(--ovl-07); }

/* Profile button — plain hamburger glyph, matches the front-page mobile-menu-btn */
.nav-profile-btn { position: relative; flex-direction: row; align-items: center; background: none; border: none; color: var(--ctrl-ink); cursor: pointer; padding: 6px 4px; }
.nav-profile-btn .nav-hamburger { width: 30px; height: 30px; display: block; }   /* matches the front-page nav hamburger; sized to balance the theme icon + pill */
/* Thin vertical rule separating the hamburger from the rest of the nav-right cluster. */
.nav-divider { width: 1px; height: 24px; background: var(--border-strong); flex-shrink: 0; align-self: center; }
#nav-profile:hover { color: var(--ctrl-ink); background: none; opacity: 0.8; }

/* Nav theme toggle — light/dark sunburst icon cycles through themes */
.nav-theme-btn { position: relative; padding: 4px; color: var(--ctrl-ink); }
.nav-theme-btn svg { width: 26px; height: 26px; display: block; }   /* up from 18px — matches the hamburger + pill scale */
.nav-theme-btn:hover { background: none; opacity: 0.8; }
.nav-theme-label {
    position: absolute;
    top: calc(100% + 5px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-primary);
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    padding: 3px 8px;
    pointer-events: none;
    opacity: 0;
    z-index: 200;
}
.nav-theme-label.show { animation: theme-label-pop 1.5s ease forwards; }
@keyframes theme-label-pop {
    0%   { opacity: 0; transform: translateX(-50%) translateY(-4px); }
    15%  { opacity: 1; transform: translateX(-50%) translateY(0); }
    75%  { opacity: 1; transform: translateX(-50%) translateY(0); }
    100% { opacity: 0; transform: translateX(-50%) translateY(0); }
}

/* ── Video Grid (shared skeleton — page-specific containers position it) ── */
.video-grid {
    position: absolute;
    inset: 0;
    display: grid;
    gap: 2px;
}

.video-grid[data-count="1"] { grid-template-columns: 1fr; }
.video-grid[data-count="2"] { grid-template-columns: 1fr 1fr; }
.video-grid[data-count="3"],
.video-grid[data-count="4"] { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.video-grid[data-count="5"],
.video-grid[data-count="6"],
.video-grid[data-count="7"],
.video-grid[data-count="8"] { grid-template-columns: repeat(3, 1fr); }

.video-tile {
    position: relative;
    background: #0a0c1a;
    overflow: hidden;
}

.video-tile video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.video-tile.local { /* hook for page-specific local-tile styling */ }

.video-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 6px 10px;
    background: linear-gradient(transparent, rgba(0,0,0,0.6));
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
}

.participant-name {
    font-size: 0.78rem;
    color: #fff;
    font-weight: 500;
    text-shadow: 0 1px 3px rgba(0,0,0,0.8);
    max-width: 70%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.video-indicators { display: flex; gap: 4px; }
.indicator        { font-size: 0.75rem; }
.indicator.muted  { color: var(--danger); }

.kick-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(255,71,87,0.85);
    border: none;
    color: #fff;
    font-size: 0.65rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s;
}
.video-tile:hover .kick-btn { opacity: 1; }

/* ── Setup Preview (used by room.html setup gate) ── */
.setup-preview-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #0d0d10;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 16px;
}

.setup-preview {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transform: scaleX(-1);
}

.setup-no-camera {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    font-size: 0.85rem;
    background: rgba(0,0,0,0.6);
}

.setup-muted-row { margin-top: 4px; }

/* ── Pill Toggle (join-muted) ── */
.pill-toggle {
    position: relative;
    display: inline-block;
    width: 34px;
    height: 18px;
}
.pill-toggle input { display: none; }

.pill-track {
    position: absolute;
    inset: 0;
    background: var(--ovl-10);
    border-radius: 9px;
    transition: background 0.2s;
    cursor: pointer;
}
.pill-track::before {
    content: '';
    position: absolute;
    width: 14px;
    height: 14px;
    left: 2px;
    top: 2px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.2s;
}
.pill-toggle input:checked + .pill-track { background: var(--deep-blue); }
.pill-toggle input:checked + .pill-track::before { transform: translateX(16px); }

/* ── Auth Panel (login modal — shared) ── */
.auth-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 16px;
    background: rgba(0, 0, 0, 0.3);
    border-radius: var(--radius-sm);
    padding: 4px;
}

.auth-tab {
    flex: 1;
    padding: 8px;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: var(--transition);
}
.auth-tab.active { background: var(--primary); color: #000; }
.auth-tab:not(.active):hover { color: var(--text-primary); background: var(--ovl-07); }

.auth-tab-content .form-group { margin-bottom: 10px; }
.auth-tab-content .form-group:first-child { margin-top: 0; }

/* Google sign-in button host + or-separator */
.google-signin-host {
    display: flex;
    justify-content: center;
    margin-bottom: 12px;
    min-height: 40px;
}
.google-signin-host:empty { display: none; }
.google-signin-host:empty + .auth-sep { display: none; }

.auth-sep {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 8px 0 12px;
    color: var(--text-secondary);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.auth-sep::before,
.auth-sep::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--ovl-10);
}

.auth-user-info  { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.auth-user-badge { display: flex; align-items: center; gap: 10px; }
.auth-user-icon  { font-size: 1.4rem; }
.auth-user-details { display: flex; flex-direction: column; gap: 2px; }
.auth-username   { font-weight: 600; font-size: 0.95rem; color: var(--text-primary); }
.auth-user-type  { font-size: 0.75rem; font-weight: 500; border-radius: 4px; padding: 1px 6px; display: inline-block; }
.auth-user-type.guest   { color: var(--text-secondary); background: rgba(128,136,153,0.15); }
.auth-user-type.member  { color: var(--primary);        background: rgba(var(--primary-rgb), 0.1); }
.auth-user-type.premium { color: #ffd700;               background: rgba(255,215,0,0.1); }

.auth-offline-notice {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-secondary);
    font-size: 0.82rem;
    padding: 6px 0;
}

/* ── Shared mobile tweaks for nav ── */
@media (max-width: 800px) {
    .main-nav   { padding: 0 10px; }
    .nav-left   { min-width: 0; gap: 6px; }
    .nav-right  { min-width: 0; gap: 7px; }
    .nav-item span { display: none; }
    /* Mobile nav is tighter — a smaller inset than desktop. */
    .nav-logo { width: 42px; height: 28px; }
    /* Whole nav-right cluster a bit smaller on mobile, kept balanced:
       online box + theme icon + hamburger all scale down together. */
    .presence-stat { height: 28px; padding: 0 9px; }
    .presence-dot  { width: 8px; height: 8px; margin-right: 6px; }
    .presence-val  { font-size: 0.82rem; }
    .nav-theme-btn svg { width: 22px; height: 22px; }
    .nav-profile-btn .nav-hamburger { width: 26px; height: 26px; }
}

/* ============================================================
   Shared modal theming — must live in styles.css (loaded by both
   lobby.html and room.html). Both pages have a `class="modal-themed"`
   .modal-content for the profile, gender, room-setup, and in-room
   settings modals. Page-specific layout (widths, grids, scroll mode)
   stays in lobby.css / room.css.
   ============================================================ */
.modal-themed {
    background: linear-gradient(160deg, #14121d 0%, #0a0b12 100%);
    border-color: var(--ovl-08);
    border-radius: 0;
    box-shadow: 0 24px 70px -10px rgba(0, 0, 0, 0.85);
}
/* Peach hairline under the title (brand accent); plain hairline elsewhere. */
.modal-themed .modal-header { border-bottom-color: rgba(var(--primary-rgb), 0.28); }
.modal-themed .modal-footer { border-top-color: var(--ovl-08); }
.modal-themed .modal-header h2 {
    font-family: "Exo 2", sans-serif;
    font-weight: 700;
    letter-spacing: 0.01em;
    text-transform: none;
    font-size: 1.2rem;
}

/* ============================================================
   Shared themed action buttons. Same chassis (1px square box, no
   shadow, no transform on hover) for sign-in/out, save, upgrade,
   gender confirm and the room-join button. Per-button colour fills
   layered below: white for sign-in/out, green for confirm actions,
   amber for upgrade.
   ============================================================ */
#profile-signin-btn,
#profile-signout-btn,
#save-settings-btn,
#profile-donate-btn,
#gender-submit-btn,
#setup-join-btn,
#auth-login-btn,
#auth-register-btn {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.45);
    color: rgba(255, 255, 255, 0.85);
    padding: 12px 22px;
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    border-radius: 0;
    box-shadow: none;
    text-decoration: none;
    overflow: visible;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
#profile-signin-btn:hover,
#profile-signout-btn:hover,
#save-settings-btn:hover,
#profile-donate-btn:hover,
#gender-submit-btn:hover:not(:disabled),
#setup-join-btn:hover:not(:disabled),
#auth-login-btn:hover:not(:disabled),
#auth-register-btn:hover:not(:disabled) {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.7);
    transform: none;
    box-shadow: none;
}
/* Sign-in/out — subtle white wash on hover. */
#profile-signin-btn:hover,
#profile-signout-btn:hover {
    background: var(--ovl-07);
}
#profile-signin-btn:active,
#profile-signout-btn:active,
#save-settings-btn:active,
#profile-donate-btn:active,
#gender-submit-btn:active:not(:disabled),
#setup-join-btn:active:not(:disabled),
#auth-login-btn:active:not(:disabled),
#auth-register-btn:active:not(:disabled) {
    color: #fff;
    border-color: #fff;
    transform: none;
}
#profile-signin-btn:active,
#profile-signout-btn:active {
    background: var(--ovl-12);
}
/* Green-fill confirm — Save, gender Confirm, Join Room, Sign In, Create Account. */
#save-settings-btn,
#gender-submit-btn,
#setup-join-btn,
#auth-login-btn,
#auth-register-btn {
    background: rgba(16, 185, 129, 0.35);
    color: #fff;
}
#save-settings-btn:hover,
#gender-submit-btn:hover:not(:disabled),
#setup-join-btn:hover:not(:disabled),
#auth-login-btn:hover:not(:disabled),
#auth-register-btn:hover:not(:disabled) {
    background: rgba(16, 185, 129, 0.55);
}
#save-settings-btn:active,
#gender-submit-btn:active:not(:disabled),
#setup-join-btn:active:not(:disabled),
#auth-login-btn:active:not(:disabled),
#auth-register-btn:active:not(:disabled) {
    background: rgba(16, 185, 129, 0.85);
}
#gender-submit-btn:disabled,
#setup-join-btn:disabled,
#auth-login-btn:disabled,
#auth-register-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
/* Donate button — amber fill for distinct, slightly-warm affordance. */
#profile-donate-btn {
    background: rgba(245, 158, 11, 0.3);
    color: #fff;
}
#profile-donate-btn:hover {
    background: rgba(245, 158, 11, 0.5);
}
#profile-donate-btn:active {
    background: rgba(245, 158, 11, 0.8);
}

/* ── "New level" takeover — banishment to the cesspool ──────────────── */
.newlevel-takeover {
  position: fixed; inset: 0; z-index: 99999;
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 2rem;
  background: #050505;
  opacity: 0; transition: opacity .8s ease;
  font-family: 'Inter', system-ui, sans-serif;
}
.newlevel-takeover.show { opacity: 1; }
.newlevel-inner { max-width: 32rem; }
.newlevel-kicker {
  font-family: 'JetBrains Mono', monospace;
  font-size: .72rem; letter-spacing: .34em;
  color: #f02070; margin-bottom: 1.4rem;
}
.newlevel-title {
  font-weight: 900; font-size: clamp(2rem, 7vw, 3.4rem);
  letter-spacing: -.03em; line-height: 1; text-transform: uppercase;
  color: #ebebeb; margin: 0 0 1.1rem;
}
.newlevel-sub { color: #888; font-size: 1rem; line-height: 1.6; }

/* ════════════════════════════════════════════════════════════════════════
   THEME PRESETS — set via data-theme on <html> (pre-paint script + profile).
     · "pleasure" (default / attribute absent) = the rounded look. No rules
       here; the base stylesheet IS pleasure.
     · "business" = sharp. Square every rounded RECTANGLE across the chrome,
       then restore the genuinely circular controls (avatars, status dots,
       spinners, radios, round icon-buttons, pill badges) AND the whole
       call-pill cluster — the round call controls stay round, by design.
   Mechanism: a scoped `body *` hammer (important, low-ish specificity) flips
   every corner to 0; each restore rule is a higher-specificity important
   override, so circles/pills/the call pill win the cascade. Pseudo-element
   circles (toggle knob, radio dots) aren't matched by `*`, so they survive
   untouched without a restore.
   ════════════════════════════════════════════════════════════════════════ */
html[data-theme="business"] {
    --radius: 0;
    --radius-sm: 0;
    --radius-lg: 0;
    /* Front-page backdrop: solid near-black + blue upper-left glow. */
    --app-bg: radial-gradient(at 18% 28%, rgba(59,130,246,0.2) 0%, transparent 46%), #080808;
}

/* Square the lot, EXCEPT in-call games. Games live in #game-overlay-body and own
   their corners (pills, circles, custom radii), so the theme must not reach into
   them. The games guard is wrapped in :where() so it adds ZERO specificity — a
   bare :not(#game-overlay-body) contributes ID-level specificity, which pushed
   this blanket above every un-square override below and stuck toggles, radios,
   avatars etc. square. With :where() the blanket stays low-specificity (its
   !important still squares everything non-important) and the overrides win. */
html:is([data-theme="business"], [data-theme="vacation"]) body *:not(:where(#game-overlay-body, #game-overlay-body *)) { border-radius: 0 !important; }

/* Restore perfect circles (avatars, dots, spinners, radios, round buttons). */
html:is([data-theme="business"], [data-theme="vacation"]) .circle-side-btn,
html:is([data-theme="business"], [data-theme="vacation"]) .action-btn:not(.btn-addfriend):not(.btn-history),
html:is([data-theme="business"], [data-theme="vacation"]) .hint-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .game-overlay-close,
html:is([data-theme="business"], [data-theme="vacation"]) .game-share-spinner,
html:is([data-theme="business"], [data-theme="vacation"]) .game-reconnect-spinner,
html:is([data-theme="business"], [data-theme="vacation"]) .game-voice-spinner,
html:is([data-theme="business"], [data-theme="vacation"]) .radio-row input[type="radio"],
html:is([data-theme="business"], [data-theme="vacation"]) .gender-option input[type="radio"],
html:is([data-theme="business"], [data-theme="vacation"]) .fr-close,
html:is([data-theme="business"], [data-theme="vacation"]) .friend-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .sent-card-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .thread-send,
html:is([data-theme="business"], [data-theme="vacation"]) .history-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .call-card-spinner,
html:is([data-theme="business"], [data-theme="vacation"]) .call-card-pulse,
html:is([data-theme="business"], [data-theme="vacation"]) .conn-dot,
html:is([data-theme="business"], [data-theme="vacation"]) .sysav-preview,
html:is([data-theme="business"], [data-theme="vacation"]) .pp-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .pp-avatar-pencil,
html:is([data-theme="business"], [data-theme="vacation"]) .pp-av-preview,
html:is([data-theme="business"], [data-theme="vacation"]) #nav-profile .nav-avatar.has-avatar,
html:is([data-theme="business"], [data-theme="vacation"]) .pp-blocked-av,
html:is([data-theme="business"], [data-theme="vacation"]) .dm-av,
html:is([data-theme="business"], [data-theme="vacation"]) .room-loading-spinner,
html:is([data-theme="business"], [data-theme="vacation"]) .room-ctrl,
html:is([data-theme="business"], [data-theme="vacation"]) .kick-btn { border-radius: 50% !important; }

/* Restore pill-shaped chips, badges, incoming-call buttons + the toggle
   switches (Allow Calls / DMs etc. — switches stay rounded in every theme). */
html:is([data-theme="business"], [data-theme="vacation"]) .pill-track,
html:is([data-theme="business"], [data-theme="vacation"]) .trust-badge,
html:is([data-theme="business"], [data-theme="vacation"]) .game-reconnect-notice,
html:is([data-theme="business"], [data-theme="vacation"]) .game-voice-pill,
html:is([data-theme="business"], [data-theme="vacation"]) .friends-pill,
html:is([data-theme="business"], [data-theme="vacation"]) .friend-unread,
html:is([data-theme="business"], [data-theme="vacation"]) .msg-unread-dot,
html:is([data-theme="business"], [data-theme="vacation"]) .call-btn,
html:is([data-theme="business"], [data-theme="vacation"]) .rate-chip,
html:is([data-theme="business"], [data-theme="vacation"]) .sent-card-status,
html:is([data-theme="business"], [data-theme="vacation"]) .admin-toggle,
html:is([data-theme="business"], [data-theme="vacation"]) .room-controls { border-radius: 999px !important; }

/* ── Business call controls — where business diverges hard from pleasure ──
   The pill is flat on the left, rounded on the right. The Call button is a
   square, flat, front-page-pink button (matches .vh-btn) inset at the flat
   left end; mic/speaker keep their rounding so the right cluster stays soft.
   The status line under the action row becomes a .vh-tag-style chip. */
html:is([data-theme="business"], [data-theme="vacation"]) .call-pill { border-radius: 0 27px 27px 0 !important; }
html:is([data-theme="business"], [data-theme="vacation"]) .pill-seg:not(.pill-call),
html:is([data-theme="business"], [data-theme="vacation"]) .pill-icon,
html:is([data-theme="business"], [data-theme="vacation"]) .pill-mic,
html:is([data-theme="business"], [data-theme="vacation"]) .pill-speaker { border-radius: 22px !important; }
html:is([data-theme="business"], [data-theme="vacation"]) .pill-vu { border-radius: 16px !important; }

/* Vacation is a light/white theme — the drawers' heavy dark slide-in shadow
   (rgba(0,0,0,0.6)) reads as a grubby dark smudge there. Soften it to a faint
   light-theme shadow so the admin / mod / filter panels slide in cleanly. */
html[data-theme="vacation"] .side-drawer.open,
html[data-theme="vacation"] .menu-stack.open { box-shadow: -10px 0 30px rgba(0, 0, 0, 0.12); }


/* Vacation: nav wordmark switches to the front-page logo font (Inter 900),
   dropping the Bungee + blue glow that only suit the dark themes. */
html[data-theme="vacation"] .nav-brand {
    font-family: 'Inter', system-ui, sans-serif;
    font-weight: 900;
    font-size: 1.22rem;   /* Inter 900 reads smaller than Bungee — bump to match */
    letter-spacing: -0.02em;
    text-shadow: none;
}

/* Vacation: lighten the call pill so it isn't a dark island on the white panel
   — light groove + light segments + dark icons. The Call button keeps its
   accent colour (it's a coloured control, fine on light). */
html[data-theme="vacation"] .call-pill {
    background: var(--surface-2);
    box-shadow: inset 0 1px 3px rgba(0,0,0,0.10);
}
html[data-theme="vacation"] .pill-seg {
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 1px 2px rgba(0,0,0,0.18);
}
html[data-theme="vacation"] .pill-icon { color: #16181d; }
html[data-theme="vacation"] .pill-icon:not(.muted):not(.deafened) { background: #ffffff; }
html[data-theme="vacation"] .pill-icon:hover:not(:disabled) { filter: brightness(0.95); }
html[data-theme="vacation"] .pill-vu {
    background: #e3e6ec;
    box-shadow: inset 0 1px 3px rgba(0,0,0,0.12);
}

/* Vacation: interest chips are tuned for dark backgrounds (light pastel text),
   so darken the text/border for the white panel — same hue, just readable. */
html[data-theme="vacation"] .chip-interest {
    background: hsla(var(--chip-hue), 60%, 50%, 0.14);
    border-color: hsla(var(--chip-hue), 55%, 45%, 0.55);
    color: hsl(var(--chip-hue), 65%, 32%);
}
html[data-theme="vacation"] .chip-interest .chip-x { color: hsl(var(--chip-hue), 55%, 40%); }

/* Square pink Call button — keeps the raised, 3D neumorphic shadow from
   .pill-seg, just recoloured to the front-page pink. */
html[data-theme="business"] .pill-call {
    border-radius: 0 !important;
    background: #f02070 !important;
    color: #fff !important;
}
/* Hover stays vivid pink and gains a glow (instead of washing out to white). */
html[data-theme="business"] .pill-call:hover:not(:disabled) {
    background: #f02070 !important;
    filter: none !important;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.3),
        inset 0 -2px 5px rgba(0,0,0,0.4),
        0 2px 6px rgba(0,0,0,0.5),
        0 0 16px rgba(240,32,112,0.6) !important;
}
/* Preserve the searching / in-call state colours. */
html[data-theme="business"] .pill-call.btn-call-searching { background: linear-gradient(180deg, #f7ab1e, #e08c06) !important; }
html[data-theme="business"] .pill-call.btn-call-active    { background: linear-gradient(180deg, #ff5468, #e23a4c) !important; }

/* Status line under the action row → front-page .vh-tag chip (pink border +
   pink text, transparent). Shared by business and vacation. */
html[data-theme="business"] .call-hint,
html[data-theme="vacation"] .call-hint {
    display: inline-block;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.72rem;
    color: #f02070;
    border: 1px solid rgba(240,32,112,.4);
    background: transparent;
    padding: 4px 11px;
    letter-spacing: 0.06em;
    text-shadow: none;
}
/* The emphasised word ("Call") takes the theme's control ink so it stays
   legible on both the dark (business) and light (vacation) backdrop. */
html[data-theme="business"] .call-hint .hint-em,
html[data-theme="vacation"] .call-hint .hint-em { color: var(--ctrl-ink); }

/* Vacation: the pill border/bg adapt via tokens, but the bright green count is
   low-contrast on the light backdrop — darken it (the dot stays green). */
html[data-theme="vacation"] .presence-val { color: #15803d; }
html[data-theme="vacation"] .presence-stat.active .presence-val { color: var(--primary); }

/* Theme picker — segmented two-button control in the profile settings. */
.theme-choice { display: inline-flex; border: 1px solid var(--dark-border); border-radius: var(--radius-sm); overflow: hidden; }
.theme-opt {
    appearance: none; border: none; cursor: pointer;
    padding: 7px 16px; font: inherit; font-size: 0.85rem; font-weight: 600;
    background: transparent; color: var(--text-secondary);
    transition: background 0.15s, color 0.15s;
}
.theme-opt + .theme-opt { border-left: 1px solid var(--dark-border); }
.theme-opt:hover { color: var(--text-primary); background: var(--ovl-05); }
.theme-opt.active { background: var(--primary); color: #04222b; }

/* ════════════════════════════════════════════════════════════════════════
   VACATION theme — a real light theme: white surfaces, dark text. It ONLY
   redefines the theme tokens (no inversion, no per-element overrides) — the
   surfaces read these tokens, so the whole lobby/room flips cleanly. Shape
   stays rounded (this isn't business).
   ════════════════════════════════════════════════════════════════════════ */
html[data-theme="vacation"] {
    --radius: 0;                          /* square, like business */
    --radius-sm: 0;
    --radius-lg: 0;
    --app-bg:         #eef0f4;            /* soft off-white page backdrop */
    --surface:        #ffffff;            /* cards, panels, drawers */
    --surface-2:      #eceef3;            /* inset wells, inputs, avatar bg */
    --surface-raised: #ffffff;            /* nav, modal, toast */
    --border:         rgba(0, 0, 0, 0.10);
    --border-strong:  rgba(0, 0, 0, 0.20);
    --text-primary:   #16181d;
    --text-secondary: #5a6072;
    --dark-border:    #d7dae1;
    --primary:        #f02070;            /* pink reads strong on white */
    --primary-rgb:    240, 32, 112;
    --primary-hover:  #ff4f93;
    --on-accent:      #ffffff;
    --ctrl-ink:       #16181d;            /* dark icons/outlines on the light backdrop */
    /* Overlays flip to black so borders/hovers/wells read on the light surfaces. */
    --ovl-03: rgba(0,0,0,0.03); --ovl-04: rgba(0,0,0,0.04);
    --ovl-05: rgba(0,0,0,0.05); --ovl-06: rgba(0,0,0,0.06);
    --ovl-07: rgba(0,0,0,0.07); --ovl-08: rgba(0,0,0,0.08);
    --ovl-09: rgba(0,0,0,0.09); --ovl-10: rgba(0,0,0,0.10);
    --ovl-12: rgba(0,0,0,0.12); --ovl-14: rgba(0,0,0,0.14);
    --ovl-15: rgba(0,0,0,0.15); --ovl-16: rgba(0,0,0,0.16);
    --ovl-18: rgba(0,0,0,0.18); --ovl-22: rgba(0,0,0,0.22);
}

/* ════════════════════════════════════════════════════════════════════════
   GAMES ARE THEME-AGNOSTIC
   In-call games render inside #game-overlay-body, a top-level child of <body>
   under the themed <html>. They consume the app's design tokens heavily
   (var(--primary) ×73, --text-primary ×65, --primary-rgb, --text-secondary,
   --radius, --dark-border …) and are authored against the DEFAULT theme — so on
   business/vacation they would inherit the wrong text colour (dark on dark),
   accent, surfaces and corners. Reset every themed token here to its :root
   default so the theme only styles the lobby/room chrome, never game content.
   The overlay chrome OUTSIDE this element (close button, title) stays themed.
   Keep these values in sync with the :root defaults at the top of this file.
   ════════════════════════════════════════════════════════════════════════ */
#game-overlay-body {
    --primary: #f02070;
    --primary-rgb: 240, 32, 112;
    --primary-hover: #ff4f93;
    --primary-glow: rgba(var(--primary-rgb), 0.4);
    --dark-border: #2a2d3a;
    --text-primary: #e0e0e0;
    --text-secondary: #808899;
    --app-bg: linear-gradient(125deg, #0a1733 0%, #110a1c 55%, #280a13 100%);
    --surface: rgba(13, 15, 22, 0.92);
    --surface-2: #161a26;
    --surface-raised: #15161d;
    --border: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.18);
    --on-accent: #ffffff;
    --ctrl-ink: #fff;
    /* Not theme-overridden today, but mirrored so games stay immune to ANY
       future theme change — a complete default-token snapshot. */
    --accent: #6c63ff;
    --accent-glow: rgba(108, 99, 255, 0.5);
    --deep-blue: #1c4870;
    --dark-bg: #0d0d0d;
    --dark-panel: #15161d;
    --bg-gradient-start: #0a0e27;
    --bg-gradient-end: #1a1d35;
    --success: #00ff88;
    --warning: #ffa500;
    --danger: #ff4757;
    --spacing: 15px;
    --transition: all 0.3s ease;
    --radius: 10px;
    --radius-sm: 5px;
    --radius-lg: 15px;
    --ovl-03: rgba(255,255,255,0.03); --ovl-04: rgba(255,255,255,0.04);
    --ovl-05: rgba(255,255,255,0.05); --ovl-06: rgba(255,255,255,0.06);
    --ovl-07: rgba(255,255,255,0.07); --ovl-08: rgba(255,255,255,0.08);
    --ovl-09: rgba(255,255,255,0.09); --ovl-10: rgba(255,255,255,0.10);
    --ovl-12: rgba(255,255,255,0.12); --ovl-14: rgba(255,255,255,0.14);
    --ovl-15: rgba(255,255,255,0.15); --ovl-16: rgba(255,255,255,0.16);
    --ovl-18: rgba(255,255,255,0.18); --ovl-22: rgba(255,255,255,0.22);
}
