:root {
    --bg-color: #0d1117;
    --text-color: #e6edf3;
    --card-bg: #ffffff;
    --primary: #58a6ff;
    --accent: #3fb950;
    --error: #f85149;
    --bot-color: #30363d;
    --panel-bg: rgba(22, 27, 34, 0.75);
    --panel-border: rgba(255, 255, 255, 0.08);
    --panel-shadow: rgba(0, 0, 0, 0.6);
    --panel-glow: rgba(88, 166, 255, 0.15);
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    user-select: none;
    -webkit-user-select: none;
}

body {
    background-color: var(--bg-color);
    color: var(--text-color);
    font-family: 'Outfit', sans-serif;
    overflow: hidden;
    touch-action: manipulation;
    height: 100vh;
    display: flex;
    justify-content: center;
    transition: background-color 0.3s ease, background-image 0.5s ease;
}

body.menu-screen,
body.game-screen {
    background-size: cover !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
}

/* ═══════════════════════════════════════════════
   CSS 3D PARALLAX SCENE (Desktop Only)
   Saf CSS/JS ile premium menü animasyonları.
   Sıfır dış bağımlılık, GPU-compositor tabanlı.
   ═══════════════════════════════════════════════ */

/* --- Parallax Sahne Konteyner --- */
#parallax-scene {
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}
#parallax-scene.parallax-hidden {
    display: none;
}

/* --- Arka Plan Katmanı --- */
#parallax-bg {
    position: absolute;
    inset: -20px; /* ±15px parallax + 5px güvenlik payı */
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    will-change: transform;
    transition: transform 0.15s ease-out, filter 0.4s ease;
    filter: brightness(1) saturate(1);
}

/* Tema bazlı arka plan görselleri (#parallax-bg üzerinde) */
body.theme-classic #parallax-bg { background-image: url("assets/menu.jpg"); }
body.theme-green  #parallax-bg  { background-image: url("assets/green_menu.jpg"); }
body.theme-blue   #parallax-bg  { background-image: url("assets/blue_menu.jpg"); }
body.theme-red    #parallax-bg  { background-image: url("assets/red_menu.jpg"); }
body.theme-dark   #parallax-bg  { background-image: url("assets/dark_menu.jpg"); }

/* --- Yüzen Işık Parçacıkları --- */
#parallax-glow {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
}

.glow-orb {
    position: absolute;
    border-radius: 50%;
    background: radial-gradient(circle, var(--primary) 0%, transparent 70%);
    opacity: 0.07;
    filter: blur(40px);
    will-change: transform;
    animation: float-orb 8s ease-in-out infinite;
}

.orb-1 { width: 300px; height: 300px; top: 10%; left: 5%;  animation-delay: 0s; }
.orb-2 { width: 200px; height: 200px; top: 60%; right: 8%; animation-delay: -3s; }
.orb-3 { width: 250px; height: 250px; top: 35%; left: 55%; animation-delay: -5.5s; }

@keyframes float-orb {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    33%      { transform: translate3d(15px, -20px, 0) scale(1.05); }
    66%      { transform: translate3d(-10px, 15px, 0) scale(0.95); }
}

/* --- Hover Brightness Pulse --- */
body.parallax-hover-pulse #parallax-bg {
    filter: brightness(1.12) saturate(1.15);
}

/* --- Buton 3D Hover: Neon Glow --- */
body.menu-screen .menu-buttons {
    perspective: 800px;
}

body.parallax-active .vibrant-play,
body.parallax-active #btn-play-multi {
    transition: transform 0.2s ease-out, box-shadow 0.3s ease;
    will-change: transform;
}

body.parallax-active .vibrant-play:hover,
body.parallax-active #btn-play-multi:hover {
    box-shadow:
        0 0 15px var(--primary),
        0 4px 25px var(--panel-glow),
        inset 0 0 15px rgba(255, 255, 255, 0.08);
}

/* --- Exit Animasyonu (Oyuna Geçiş) --- */
#parallax-bg.parallax-exit {
    transform: scale(1.15) !important;
    filter: blur(8px) brightness(0.5) !important;
    /* v3.9.0: v3.8.0 kisaltmisti (1000ms -> ~340ms); tek gercek his
       kazanimi buydu, lobby.css ile birlikte gitmesin diye buraya tasindi. */
    transition: transform 0.32s ease-in, filter 0.32s ease-in !important;
}

.parallax-exit-ui {
    opacity: 0 !important;
    transform: translateY(-30px) scale(0.97) !important;
    transition: opacity 0.5s ease, transform 0.5s ease !important;
}

/* --- Parallax aktifken body arka planını gizle --- */
@media (min-width: 769px) {
    body.menu-screen.parallax-active {
        background-image: none !important;
    }
    body.menu-screen.parallax-active::before {
        display: none !important;
    }
}

/* --- UI Katmanı Parallax Geçiş Yumuşatma --- */
body.parallax-active #main-menu {
    will-change: transform;
    transition: transform 0.15s ease-out;
}

/* --- Mobilde parallax kesinlikle gizli --- */
@media (max-width: 768px) {
    #parallax-scene {
        display: none !important;
    }
}


/* v3.27.5: the corner (account, coin balance, Ra's Spin) belongs to the menu.
   In a match (every mode), in practice and in the Tomb it is gone at EVERY
   width. It used to be hidden on phones only, to keep it off the table; on a
   desktop it stayed clickable from a live match, and from there it opened the
   wheel over the cards, an account panel with the match still running
   underneath, and a sign-out that took a multiplayer seat's or a scored Daily
   run's identity away mid-play.
   Practice and the Tomb are isolated modes on screens of their own (no match
   event, no body class), so the second rule names their screens. Two rules,
   not one selector list: a browser without :has() drops a whole list that
   contains it, and the match rule would go with it. */
body.game-screen #top-left-corner {
    display: none !important;
}
body:has(#tutorial-screen.active) #top-left-corner,
body:has(#tomb-screen.active) #top-left-corner {
    display: none !important;
}

/* On a phone the score is anchored beneath the Quit button during play */
@media (max-width: 768px) {
    body.game-screen #top-right-score {
        display: flex !important;
        position: absolute !important;
        top: 60px !important;
        right: 15px !important;
        z-index: 105 !important;
    }

    /* Optimize Victory/Defeat Screen for Mobile.
       v3.27.6: the same pieces in less room, so the three buttons are on the
       glass of an ordinary phone without scrolling (the scrolling itself is in
       the #victory-screen block further down). Measured before, at 390x664:
       796px of content in 664px. Nothing here changes a colour or a face.
       - The title is sized from the width it is given: at 2.5rem
         "CONGRATULATIONS!" ran 47px off BOTH edges of a 390px screen.
       - The four stat tiles share one row; they wrapped 3 + 1.
       - The buttons take the column's width, so "Challenge a friend" stays on
         one line, and their gaps are tighter. */
    #victory-screen {
        padding: 0.75rem 0.9rem calc(1.25rem + env(safe-area-inset-bottom, 0px));
    }

    #victory-screen #victory-trophy-3d {
        font-size: 3rem;
        margin-bottom: 4px;
    }

    #victory-screen .victory-title {
        font-size: clamp(1.4rem, 7vw, 2.5rem) !important;
        line-height: 1.08;
        margin-bottom: 0.5rem;
        max-width: 100%;
        text-align: center;
    }

    #victory-screen .victory-message {
        font-size: 1.1rem !important;
        text-align: center;
        padding: 0 20px;
    }

    #victory-screen .stats-panel {
        gap: 6px;
        margin: 0.8rem auto;
    }

    #victory-screen .stat-card {
        flex: 1 1 0;
        min-width: 0;
        max-width: none;
        padding: 8px 4px;
    }

    #victory-screen .stat-title {
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 2.3em;
        font-size: 0.56rem;
        line-height: 1.15;
        letter-spacing: 0.3px;
        white-space: normal;
        overflow-wrap: anywhere;
    }

    #victory-screen .stat-value {
        font-size: 1rem;
    }

    #victory-screen .mvp-moment,
    #victory-screen .coin-result-badge {
        margin-bottom: 0.5rem;
        padding-top: 0.42rem;
        padding-bottom: 0.42rem;
    }

    #victory-screen .share-result-btn {
        margin-top: 0.4rem;
        padding: 0.55rem 1rem;
    }

    #victory-screen .menu-buttons {
        flex-direction: column;
        align-items: center;
        width: 100%;
        max-width: none;
        gap: 12px;
        margin-top: 0.9rem !important;
    }

    #victory-screen .menu-buttons .btn {
        width: 100%;
        max-width: 340px;
        padding: 12px;
        margin-bottom: 0;
    }

    /* Strict Mobile Optimization for Emoji UI */
    .emoji-btn {
        position: fixed !important;
        right: 15px !important;
        bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important;
        width: 48px !important;
        height: 48px !important;
        z-index: 999 !important;
    }

    .emoji-btn svg {
        width: 28px !important;
        height: 28px !important;
    }

    .emoji-menu {
        position: fixed !important;
        right: 15px !important;
        bottom: calc(140px + env(safe-area-inset-bottom, 0px)) !important;
        width: auto !important;
        max-width: 200px !important;
        justify-content: flex-end !important;
        z-index: 1000 !important;
    }

    .emoji-menu span {
        font-size: 1.8rem !important;
        padding: 10px !important;
    }

    /* Strict Mobile Optimization for Action Log */
    #action-log {
        bottom: 12px !important;
        left: 8px !important;
        width: 180px !important;
        max-height: 80px !important;
        font-size: 0.68rem !important;
        padding: 4px 6px !important;
        border-radius: 6px !important;
        mask-image: linear-gradient(to top, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 0) 100%) !important;
        -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 0) 100%) !important;
    }

    .log-entry {
        margin-top: 2px !important;
        gap: 3px !important;
        line-height: 1.25 !important;
    }

    .log-entry .time {
        display: none !important; /* Hide timestamps on mobile to save maximum space */
    }
}

/* Classic Theme Assets */
body.theme-classic.menu-screen {
    background-image: url("assets/menu.jpg") !important;
}

body.theme-classic.game-screen {
    background-image: url("assets/game.jpg") !important;
}

/* Green Theme Assets */
body.theme-green.menu-screen {
    background-image: url("assets/green_menu.jpg") !important;
}

body.theme-green.game-screen {
    background-image: url("assets/green_game.jpg") !important;
}

/* Blue Theme Assets */
body.theme-blue.menu-screen {
    background-image: url("assets/blue_menu.jpg") !important;
}

body.theme-blue.game-screen {
    background-image: url("assets/blue_game.jpg") !important;
}

/* Red Theme Assets */
body.theme-red.menu-screen {
    background-image: url("assets/red_menu.jpg") !important;
}

body.theme-red.game-screen {
    background-image: url("assets/red_game.jpg") !important;
}

/* Dark Theme Assets */
body.theme-dark.menu-screen {
    background-image: url("assets/dark_menu.jpg") !important;
}

body.theme-dark.game-screen {
    background-image: url("assets/dark_game.jpg") !important;
}

body.menu-screen::before,
body.game-screen::before {
    content: '';
    position: absolute;
    inset: 0;
    box-shadow: inset 0 0 150px 40px var(--primary);
    pointer-events: none;
    z-index: 0;
    opacity: 0.3;
    transition: box-shadow 0.5s ease, opacity 0.5s ease;
    mix-blend-mode: overlay;
}

/* Dark Theme Override for High-Contrast Shadow Ambience */
body.theme-dark.menu-screen::before,
body.theme-dark.game-screen::before {
    opacity: 0.2;
    box-shadow: inset 0 0 80px 20px rgba(0, 0, 0, 0.8);
    mix-blend-mode: normal;
}

/* --- THEMES --- */
body.theme-green {
    --bg-color: #0b1a10;
    background-image: radial-gradient(circle at center, #112a1a 0%, #0b1a10 100%);
    --panel-bg: rgba(11, 26, 16, 0.75);
    --panel-border: rgba(63, 185, 80, 0.15);
    --panel-shadow: rgba(0, 0, 0, 0.7);
    --panel-glow: rgba(63, 185, 80, 0.15);
}

body.theme-blue {
    --bg-color: #0b132a;
    background-image: radial-gradient(circle at center, #121f42 0%, #0b132a 100%);
    --panel-bg: rgba(11, 19, 42, 0.75);
    --panel-border: rgba(88, 166, 255, 0.15);
    --panel-shadow: rgba(0, 0, 0, 0.7);
    --panel-glow: rgba(88, 166, 255, 0.15);
}

body.theme-red {
    --bg-color: #2a0b0b;
    background-image: radial-gradient(circle at center, #421212 0%, #2a0b0b 100%);
    --panel-bg: rgba(42, 11, 11, 0.75);
    --panel-border: rgba(248, 81, 73, 0.15);
    --panel-shadow: rgba(0, 0, 0, 0.7);
    --panel-glow: rgba(248, 81, 73, 0.15);
}

body.theme-dark {
    --bg-color: #050505;
    background-image: radial-gradient(circle at center, #111111 0%, #050505 100%);
    --panel-bg: rgba(10, 10, 10, 0.85);
    --panel-border: rgba(255, 255, 255, 0.05);
    --panel-shadow: rgba(0, 0, 0, 0.9);
    --panel-glow: rgba(255, 255, 255, 0.05);
}

/* --- SCREENS --- */
.screen {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 600px;
    margin: 0 auto;
    display: none;
    flex-direction: column;
    padding: 2rem 1rem;
    opacity: 0;
    transform: scale(0.96) translateY(8px);
    transition: opacity 0.35s cubic-bezier(0.22, 1, 0.36, 1),
                transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
    z-index: 5; /* Parallax sahnesinin (z:1) üstünde */
}

.screen.active {
    display: flex;
    opacity: 1;
    transform: scale(1) translateY(0);
}

/* --- MAIN MENU / SETTINGS --- */
#main-menu,
#settings-panel {
    justify-content: center;
    align-items: center;
    text-align: center;
}

/* Settings paneli ekrana sığsın */
#settings-panel {
    padding: 1rem;
}

#settings-panel .lobby-content-container {
    padding: 1.5rem 2rem;
    max-height: 92vh;
    overflow-y: auto;
}

#settings-panel .setting-group {
    margin-bottom: 0.6rem;
    padding: 8px 12px;
}

#settings-panel .panel-title {
    margin-bottom: 1rem;
    font-size: 1.5rem;
}

#main-menu h1 {
    font-size: 3rem;
    font-weight: 900;
    margin-bottom: 3rem;
    color: var(--primary);
    text-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
    line-height: 1.1;
}

#game-version {
    position: absolute;
    bottom: 10px;
    right: 15px;
    color: rgba(255, 255, 255, 0.5);
    font-family: inherit;
    font-size: 0.85rem;
    pointer-events: none;
    z-index: 100;
}

#settings-panel h2,
#account-panel h2,
#rules-panel h2 {
    font-size: 2.5rem;
    margin-bottom: 2rem;
    color: var(--text-color);
}

/* --- PROFILE & ACCOUNT --- */
.profile-btn {
    position: absolute;
    top: calc(20px + env(safe-area-inset-top, 0px));
    left: calc(20px + env(safe-area-inset-left, 0px));
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(22, 27, 34, 0.6);
    padding: 8px 16px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-color);
    cursor: pointer;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: all 0.2s ease;
    z-index: 100;
    font-weight: 600;
}

.profile-btn:hover {
    background: rgba(22, 27, 34, 0.9);
    border-color: var(--primary);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(88, 166, 255, 0.2);
}

.profile-btn svg {
    width: 20px;
    height: 20px;
}

#account-panel {
    /* v3.10.0 — `justify-content: center` on a flex COLUMN that overflows
       pushes the overflow out of BOTH ends, and the top end cannot be
       scrolled back to: scrollTop is already 0 there. Measured before the
       fix, the <h2> sat at top:-21 on a 1920x914 desktop and top:-138 on a
       390x844 phone, so the panel's own title was unreachable. It is the
       only .scrollable-screen that centred, and the only one with the bug.

       Two declarations, deliberately. A browser that does not understand
       `safe center` drops the second and keeps the first, which is the safe
       direction to fail in: content starts at the top and every pixel of it
       can be scrolled to. Where `safe` IS understood, the panel still
       centres whenever it fits. */
    justify-content: flex-start;
    justify-content: safe center;
    align-items: center;
    text-align: center;
    padding-top: 1.5rem;
}

.account-section {
    background: var(--panel-bg);
    padding: 2rem;
    border-radius: 16px;
    border: 1px solid var(--panel-border);
    width: 100%;
    max-width: 400px;
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

.error-msg {
    color: var(--error);
    margin-top: 10px;
    font-size: 0.9rem;
    min-height: 1.2rem;
}

.scrollable-screen {
    justify-content: flex-start;
    overflow-y: auto;
    padding-bottom: 4rem;
}

.rules-content {
    text-align: left;
    background: var(--panel-bg);
    padding: 1.5rem;
    border-radius: 16px;
    border: 1px solid var(--panel-border);
    margin-bottom: 2rem;
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

.rules-content h3 {
    color: var(--primary);
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
    font-size: 1.4rem;
}

.rules-content h3:first-child {
    margin-top: 0;
}

.rules-content p,
.rules-content li {
    color: #c9d1d9;
    font-size: 1.1rem;
    line-height: 1.5;
    margin-bottom: 0.8rem;
}

.rules-content ul {
    list-style-type: none;
    padding-left: 0;
}

.rules-content li {
    background: rgba(0, 0, 0, 0.2);
    padding: 10px;
    border-radius: 8px;
    margin-bottom: 0.5rem;
}

.rules-content li strong {
    color: var(--accent);
}

/* --- VICTORY SCREEN --- */
#victory-screen {
    justify-content: center;
    align-items: center;
    text-align: center;
    background: radial-gradient(circle at center, rgba(63, 185, 80, 0.3) 0%, var(--bg-color) 100%);
    z-index: 50;
    /* Above everything */
}

.victory-title {
    font-size: 4rem;
    font-weight: 900;
    color: gold;
    text-transform: uppercase;
    text-shadow: 0 0 20px rgba(255, 215, 0, 0.6), 0 5px 15px rgba(0, 0, 0, 0.8);
    margin-bottom: 1rem;
    animation: pulseGlow 2s infinite alternate;
}

.victory-message {
    font-size: 1.8rem;
    color: white;
    margin-bottom: 3rem;
    text-shadow: 0 2px 5px rgba(0, 0, 0, 0.8);
}

@keyframes pulseGlow {
    from {
        text-shadow: 0 0 20px rgba(255, 215, 0, 0.6), 0 5px 15px rgba(0, 0, 0, 0.8);
        transform: scale(1);
    }

    to {
        text-shadow: 0 0 40px rgba(255, 215, 0, 0.9), 0 5px 15px rgba(0, 0, 0, 0.8);
        transform: scale(1.05);
    }
}

.confetti-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    overflow: hidden;
}

.confetti-piece {
    position: absolute;
    width: 10px;
    height: 20px;
    background: var(--primary);
    top: -20px;
    animation: fall linear forwards;
}

@keyframes fall {
    to {
        transform: translateY(120vh) rotate(720deg);
    }
}

.menu-buttons {
    display: flex;
    flex-direction: column;
    gap: 1.2rem;
    width: 100%;
    max-width: 300px;
}

.setting-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 1.5rem;
    width: 100%;
    max-width: 300px;
    padding: 10px 14px;
    border: 1px solid transparent;
    border-radius: 10px;
    transition: border-color 0.3s ease, box-shadow 0.3s ease, background 0.3s ease;
}

.setting-group:hover {
    border-color: var(--panel-border);
    box-shadow: 0 0 12px var(--panel-glow);
    background: rgba(255, 255, 255, 0.02);
}

.setting-group label {
    font-size: 1.1rem;
    margin-bottom: 0.5rem;
    color: rgba(255, 255, 255, 0.7);
}

select {
    width: 100%;
    padding: 12px;
    border-radius: 8px;
    background: #161b22;
    color: white;
    border: 2px solid #30363d;
    font-size: 1.1rem;
    font-family: inherit;
    outline: none;
    cursor: pointer;
}

select:focus {
    border-color: var(--primary);
    box-shadow: 0 0 10px var(--panel-glow);
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* --- BUTTONS --- */
.btn {
    padding: 1rem 2rem;
    font-size: 1.4rem;
    font-family: inherit;
    font-weight: 700;
    border: 2px solid transparent;
    border-radius: 12px;
    cursor: pointer;
    transition: all 0.25s cubic-bezier(0.25, 1, 0.5, 1);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}

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

.btn:hover, .btn:focus {
    outline: none;
    border-color: #ffffff !important;
    box-shadow: 0 0 20px var(--panel-glow), 0 4px 15px rgba(0, 0, 0, 0.4) !important;
}

.btn.primary {
    background: var(--primary);
    color: #fff;
}

.btn.primary:hover {
    background: var(--accent);
    transform: translateY(-2px);
}

/* === NEW SLEEK UI STYLES === */
.ui-input.crisp-dark {
    width: 100%;
    padding: 14px 20px;
    border-radius: 6px;
    background: rgba(10, 15, 25, 0.75);
    color: #ffffff;
    border: 1px solid rgba(255, 255, 255, 0.15);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5), inset 0 0 10px rgba(0, 0, 0, 0.5);
    font-size: 1.3rem;
    outline: none;
    text-align: center;
    font-family: inherit;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition: all 0.3s ease;
    z-index: 2;
    position: relative;
}

.ui-input.crisp-dark:focus {
    border-color: var(--primary);
    box-shadow: 0 0 20px var(--primary), inset 0 0 10px rgba(0, 0, 0, 0.5);
    background: rgba(10, 15, 25, 0.9);
}

.sleek-layout {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    width: 100%;
    max-width: 350px;
    margin: 0 auto;
    z-index: 2;
    position: relative;
}

.btn.vibrant-play {
    padding: 16px 40px;
    font-size: 1.8rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    font-weight: 900;
    border-radius: 8px;
    box-shadow: 0 0 30px var(--primary), 0 8px 15px rgba(0, 0, 0, 0.4);
    transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
    background: var(--primary);
    border: 1px solid rgba(255, 255, 255, 0.3);
}

.btn.vibrant-play:hover {
    transform: scale(1.05) translateY(-2px);
    box-shadow: 0 0 50px var(--primary), 0 12px 20px rgba(0, 0, 0, 0.5);
}

.secondary-actions {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

.btn.sleek-sub {
    font-size: 1rem;
    padding: 10px 20px;
    background: rgba(30, 35, 45, 0.6);
    backdrop-filter: blur(5px);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.btn.sleek-sub:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.3);
}

.btn.secondary {
    background: #30363d;
    color: #e6edf3;
    border: 1px solid #484f58;
}

.btn-small {
    position: absolute;
    top: 15px;
    right: 15px;
    background: #30363d;
    border: none;
    color: white;
    padding: 8px 16px;
    border-radius: 8px;
    font-size: 0.9rem;
    cursor: pointer;
    font-family: inherit;
}

/* --- GAME CONTAINER --- */
#game-container {
    justify-content: space-between;
}

.player-zone {
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10;
}

#middle-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex: 1;
    margin: 2rem 0;
}

.deck {
    position: relative;
    width: 80px;
    height: 120px;
    background: linear-gradient(145deg, #21262d, #161b22);
    border: 2px solid #30363d;
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    font-size: 0.9rem;
    font-weight: 700;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4);
    transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    cursor: pointer;
    touch-action: manipulation;
}

.deck.bot-deck {
    width: 70px;
    height: 105px;
    color: #8b949e;
}

.deck.human-deck {
    width: 100px;
    height: 150px;
    color: var(--primary);
    border-color: rgba(88, 166, 255, 0.4);
}

.human-deck small {
    font-size: 0.6rem;
    opacity: 0.6;
    margin-top: 5px;
}

.count {
    font-size: 1.5rem;
    font-weight: 900;
    margin-top: 5px;
}

.human-deck .count {
    font-size: 2rem;
}

.deck.active {
    border-color: var(--accent);
    color: var(--accent);
    animation: activePulse 1.5s infinite ease-in-out;
}

@keyframes activePulse {
    0% { box-shadow: 0 0 15px rgba(63, 185, 80, 0.4); transform: translateY(-10px) scale(1.1); }
    50% { box-shadow: 0 0 30px rgba(63, 185, 80, 0.8); transform: translateY(-10px) scale(1.12); }
    100% { box-shadow: 0 0 15px rgba(63, 185, 80, 0.4); transform: translateY(-10px) scale(1.1); }
}

@keyframes burnShake {
    0% { transform: translateX(0); box-shadow: 0 0 0 var(--error); border-color: inherit; }
    20% { transform: translateX(-8px); box-shadow: 0 0 20px var(--error); border-color: var(--error); background-color: rgba(248,81,73,0.3); }
    40% { transform: translateX(8px); }
    60% { transform: translateX(-4px); box-shadow: 0 0 10px var(--error); }
    80% { transform: translateX(4px); }
    100% { transform: translateX(0); }
}

.deck.burn-shake {
    animation: burnShake 0.3s ease forwards !important;
}

@keyframes slapFlash {
    0% { filter: brightness(1) drop-shadow(0 0 0 rgba(255,255,255,0)); transform: scale(1); }
    30% { filter: brightness(1.5) drop-shadow(0 0 30px rgba(255,255,255,0.8)); transform: scale(1.05); }
    100% { filter: brightness(1) drop-shadow(0 0 0 rgba(255,255,255,0)); transform: scale(1); }
}

.slap-impact {
    animation: slapFlash 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards !important;
}

/* --- EMOJI REACTIONS --- */
.emoji-btn {
    position: absolute;
    right: -45px;
    bottom: 0px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid rgba(255,255,255,0.1);
    color: white;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    box-shadow: 0 4px 10px rgba(0,0,0,0.5);
    transition: all 0.2s ease;
    backdrop-filter: blur(5px);
    z-index: 100;
}

.emoji-btn:hover {
    transform: scale(1.1);
    border-color: var(--primary);
    background: rgba(40,45,55, 0.9);
}

.emoji-menu {
    position: absolute;
    right: -10px;
    bottom: 50px;
    background: rgba(22, 27, 34, 0.95);
    border: 1px solid rgba(88, 166, 255, 0.3);
    border-radius: 12px;
    padding: 8px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    width: 150px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.8);
    opacity: 0;
    pointer-events: none;
    transform: translateY(10px) scale(0.9);
    transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    z-index: 110;
    backdrop-filter: blur(10px);
}

.emoji-menu.active {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0) scale(1);
}

.emoji-menu span {
    font-size: 1.5rem;
    cursor: pointer;
    transition: transform 0.2s, filter 0.2s;
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5));
}

.emoji-menu span:hover {
    transform: scale(1.3);
    filter: drop-shadow(0 0 10px rgba(255,255,255,0.8));
}

.floating-emoji {
    position: absolute;
    font-size: 2.5rem;
    pointer-events: none;
    z-index: 200;
    left: 50%;
    transform: translateX(-50%);
    bottom: 50%;
    filter: drop-shadow(0 4px 10px rgba(0,0,0,0.6));
    animation: floatEmoji 1.5s ease-out forwards;
}

@keyframes floatEmoji {
    0% { transform: translate(-50%, 0) scale(0.5); opacity: 0; }
    20% { transform: translate(-50%, -20px) scale(1.2); opacity: 1; }
    50% { transform: translate(calc(-50% + 10px), -40px) scale(1); opacity: 0.9; }
    80% { transform: translate(calc(-50% - 10px), -60px) scale(1); opacity: 0.7; }
    100% { transform: translate(-50%, -80px) scale(0.8); opacity: 0; }
}

.pile-zone {
    width: 130px;
    height: 195px;
    background: rgba(48, 54, 61, 0.3);
    border: 3px dashed #30363d;
    border-radius: 16px;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.5);
    transition: all 0.1s;
    touch-action: manipulation;
}

.pile-zone:active {
    transform: scale(0.95);
    background: rgba(248, 81, 73, 0.2);
    border-color: var(--error);
}

.pile-label {
    position: absolute;
    color: #484f58;
    font-weight: 900;
    font-size: 1.2rem;
    text-align: center;
    pointer-events: none;
    opacity: 0.5;
}

#pile-cards {
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.card {
    position: absolute;
    width: 100%;
    height: 100%;
    background: var(--card-bg);
    border-radius: 12px;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: -2px 5px 10px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
    transition: transform 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.25s ease-out;
}

/* Card fly-in animation — plays when a card is placed on the pile */
@keyframes cardFlyIn {
    0% {
        opacity: 0;
        transform: scale(0.55) translateY(-30px);
        box-shadow: 0 0 0 rgba(0, 0, 0, 0);
    }

    60% {
        opacity: 1;
        transform: scale(1.12) translateY(4px);
        box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5);
    }

    80% {
        transform: scale(0.97) translateY(-2px);
    }

    100% {
        opacity: 1;
        transform: scale(1) translateY(0px);
        box-shadow: -2px 5px 10px rgba(0, 0, 0, 0.4);
    }
}

.card.fly-in {
    animation: cardFlyIn 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

.card.red {
    color: #f85149;
}

.card.black {
    color: #0d1117;
}

.card-top {
    position: absolute;
    top: 8px;
    left: 8px;
    font-size: 1rem;
    font-weight: 900;
    line-height: 1;
}

.card-bottom {
    position: absolute;
    bottom: 8px;
    right: 8px;
    font-size: 1rem;
    font-weight: 900;
    line-height: 1;
    transform: rotate(180deg);
}

.card-center {
    font-size: 3.2rem;
    text-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
}

/* v3.7.0: body-level, so a toast raised from ANY screen is visible. Was
   position:absolute inside #game-container (display:none unless active), which
   silently swallowed every lobby/menu/reconnect message. The geometry is
   unchanged — top/left 50% with a -50%/-50% translate reads the viewport under
   `fixed` exactly as it read the full-bleed container under `absolute`.
   z-index 9998 sits above every .screen (max 1000) and below #loading-overlay
   (9999) and the modals (10000+), so a toast can never cover a spinner or a
   dialog. pointer-events:none keeps it from eating clicks on any screen. */
#notifications {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 90%;
    max-width: 400px;
    word-wrap: break-word;
    line-height: 1.1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    font-size: 2.8rem;
    font-weight: 900;
    text-transform: uppercase;
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.6));
    text-align: center;
    z-index: 9998;
    opacity: 0;
    transition: opacity 0.2s ease-out, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    letter-spacing: 1px;
}

#action-log {
    position: absolute;
    bottom: 20px;
    left: 12px;
    width: 280px;
    max-height: 220px;
    overflow-y: hidden;
    display: flex;
    flex-direction: column;
    font-size: 0.95rem;
    color: rgba(255, 255, 255, 0.95);
    pointer-events: none;
    z-index: 999;
    background: rgba(10, 15, 25, 0.45);
    border-radius: 8px;
    padding: 8px 12px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: left 0.3s ease, background-color 0.3s ease;
    /* Ensure it is above the background and players */
    mask-image: linear-gradient(to top, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
    -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
}

/* Widescreen Responsive Shift for Action Log - Shifts it leftward out of center game column */
@media (min-width: 768px) {
    #action-log {
        left: -30px;
    }
}

@media (min-width: 1024px) {
    #action-log {
        left: -75px;
    }
}

@media (min-width: 1280px) {
    #action-log {
        left: -110px;
    }
}

.log-entry {
    margin-top: 4px;
    opacity: 0;
    line-height: 1.3;
    animation: fadeInSlideUp 0.4s ease-out forwards;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8);
    display: flex;
    gap: 6px;
    align-items: flex-start;
}

.log-entry .time {
    color: rgba(255, 255, 255, 0.4);
    font-size: 0.85rem;
    font-family: monospace;
    white-space: nowrap;
}

.log-entry strong {
    color: var(--primary);
}

.log-highlight {
    color: gold;
    text-shadow: 0 0 5px rgba(255, 215, 0, 0.4);
}

.log-highlight strong {
    color: inherit;
}

.log-warning {
    color: var(--error);
}

.log-warning strong {
    color: inherit;
}

.log-slap {
    color: #3fb950;
    /* Strict Green */
}

.log-slap strong {
    color: inherit;
}

.log-challenge {
    color: gold;
    /* Strict Yellow */
}

.log-challenge strong {
    color: inherit;
}

@keyframes fadeInSlideUp {
    from {
        opacity: 0;
        transform: translateX(-10px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Floating Score Animation */
@keyframes floatUpFade {
    0% {
        opacity: 0;
        transform: translate(-50%, 0) scale(0.5);
    }

    20% {
        opacity: 1;
        transform: translate(-50%, -20px) scale(1.2);
    }

    80% {
        opacity: 1;
        transform: translate(-50%, -60px) scale(1);
    }

    100% {
        opacity: 0;
        transform: translate(-50%, -80px) scale(0.8);
    }
}

/* Modern Separator */
.lobby-divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: rgba(255, 255, 255, 0.4);
    margin: 1.5rem 0;
}

.lobby-divider::before,
.lobby-divider::after {
    content: '';
    flex: 1;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.lobby-divider span {
    padding: 0 15px;
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 1px;
}

/* Polished Lobby Panels */
#lobby-panel,
#waiting-room-panel {
    align-items: center;
    justify-content: center;
}

.lobby-content-container {
    background: var(--panel-bg);
    padding: 2.5rem;
    border-radius: 16px;
    border: 1px solid var(--panel-border);
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    width: 100%;
    max-width: 400px;
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

@keyframes slideInRight {
    from {
        opacity: 0;
        transform: translateX(40px) scale(0.95);
    }

    to {
        opacity: 1;
        transform: translateX(0) scale(1);
    }
}

/* ============================================
   VICTORY / DEFEAT SCREENS
   ============================================ */

#victory-screen {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    max-width: none !important;
    z-index: 1000 !important;
    background: rgba(15, 15, 20, 0.85) !important;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    justify-content: center;
    align-items: center;
}

#victory-screen.active {
    display: flex !important;
}

/* v3.27.6: the end screen has to END, on any screen. Reported by the owner:
   on a phone the Main Menu button could not be seen. Measured: the screen is a
   fixed box that CENTRED its content and could not scroll, so content taller
   than the box was cut off at both ends: at 390x664 (a phone with its browser
   bars up) the trophy was 136px above the glass and Main Menu 120px below it,
   and on five of six phone sizes no gesture could reach the button.
   - It scrolls when its content is taller than it is.
   - It is the VISIBLE height: 100vh is the height with the browser's bars
     hidden, so a 100vh box ends underneath them.
   - Two flex spacers centre the content while it fits and collapse to nothing
     when it does not, so the top is never cut off. (`justify-content: center`
     cuts both ends; `safe center` is not in every browser yet.) */
#victory-screen {
    justify-content: flex-start;
    overflow-y: auto;
    overscroll-behavior: contain;
}
#victory-screen::before,
#victory-screen::after {
    content: '';
    flex: 1 0 0px;
}
@supports (height: 100dvh) {
    #victory-screen { height: 100dvh !important; }
}
@media (max-width: 768px) and (max-height: 700px) {
    #victory-screen #victory-trophy-3d { font-size: 2.2rem; margin-bottom: 0; }
}

/* A laptop window is short too. At full size a win needs 906px of height; the
   owner's own window is about 740px tall, and there the old centred box hid the
   top of the trophy and most of Main Menu (content 28..874 of 740). The same
   pieces step down as the window gets shorter, three steps, and below the last
   one the screen scrolls. Sizes only: no colour, face or order changes. */
@media (min-width: 769px) and (max-height: 920px) {
    #victory-screen { padding-top: 1.25rem; padding-bottom: 1.25rem; }
    #victory-screen #victory-trophy-3d { font-size: 3.6rem; margin-bottom: 6px; }
    #victory-screen .victory-title { font-size: 3.2rem; margin-bottom: 0.6rem; }
    #victory-screen .stats-panel { margin: 1rem auto; }
    #victory-screen .menu-buttons { margin-top: 1.2rem !important; }
}
@media (min-width: 769px) and (max-height: 810px) {
    #victory-screen { padding-top: 1rem; padding-bottom: 1rem; }
    #victory-screen #victory-trophy-3d { font-size: 3rem; margin-bottom: 2px; }
    #victory-screen .victory-title { font-size: 2.7rem; margin-bottom: 0.4rem; }
    #victory-screen .victory-message { font-size: 1.35rem; }
    #victory-screen .mvp-moment,
    #victory-screen .coin-result-badge { margin-bottom: 0.5rem; padding-top: 0.42rem; padding-bottom: 0.42rem; }
    #victory-screen .stats-panel { margin: 0.7rem auto; }
    #victory-screen .share-result-btn { margin-top: 0.4rem; padding: 0.5rem 1rem; }
    #victory-screen .menu-buttons { margin-top: 0.8rem !important; gap: 10px; }
    #victory-screen .menu-buttons .btn { padding-top: 0.72rem; padding-bottom: 0.72rem; }
}
@media (min-width: 769px) and (max-height: 675px) {
    #victory-screen #victory-trophy-3d { font-size: 2.2rem; margin-bottom: 0; }
    #victory-screen .victory-title { font-size: 2.2rem; }
    #victory-screen .victory-message { font-size: 1.15rem; }
    #victory-screen .stats-panel { margin: 0.5rem auto; }
    #victory-screen .menu-buttons .btn { padding-top: 0.55rem; padding-bottom: 0.55rem; font-size: 1.25rem; }
}

#victory-screen.defeat-mode {
    background: linear-gradient(to bottom, rgba(80, 0, 0, 0.65) 0%, rgba(20, 0, 0, 0.9) 100%) !important;
}

#victory-screen.defeat-mode .btn.primary {
    background: #6e0a0a;
    box-shadow: 0 0 20px rgba(248, 81, 73, 0.4);
}

#victory-screen.defeat-mode .btn.primary:hover {
    background: var(--error);
    box-shadow: 0 0 30px rgba(248, 81, 73, 0.6);
}

/* Ember rising particle */
/* v3.27.6: `absolute`, not `fixed`. The screen's backdrop-filter makes it the
   containing block either way, but a fixed box is not clipped by the
   .confetti-container it is appended to: each ember started 20px below the
   screen and, now that the screen can scroll, gave a defeat 20px of nothing
   to scroll to. Absolute, it starts in the same place and is clipped. */
.ember-piece {
    position: absolute;
    bottom: -20px;
    border-radius: 50%;
    background: radial-gradient(circle, #ffcc00 0%, #f85149 40%, rgba(248, 81, 73, 0) 100%);
    animation: riseEmber linear forwards;
    pointer-events: none;
    filter: blur(1px);
}

@keyframes riseEmber {
    0% {
        transform: translateY(0) scale(1);
        opacity: 0.8;
    }

    60% {
        opacity: 0.6;
        transform: translateY(-50vh) scale(0.7) translateX(20px);
    }

    100% {
        transform: translateY(-110vh) scale(0.3) translateX(-15px);
        opacity: 0;
    }
}

@keyframes defeatShake {
    0% {
        transform: translateX(0);
    }

    15% {
        transform: translateX(-10px) rotate(-1deg);
    }

    30% {
        transform: translateX(10px) rotate(1deg);
    }

    45% {
        transform: translateX(-7px);
    }

    60% {
        transform: translateX(7px);
    }

    75% {
        transform: translateX(-4px);
    }

    90% {
        transform: translateX(4px);
    }

    100% {
        transform: translateX(0);
    }
}

/* ============================================
   UNIFIED PANEL TITLE (inside glass container)
   ============================================ */

.panel-title {
    font-size: 1.6rem;
    font-weight: 900;
    letter-spacing: 1.5px;
    text-align: center;
    margin: 0 0 1.5rem 0;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    color: #e6edf3;
    text-transform: uppercase;
}

/* ============================================
   RULES PANEL — scrollable glass container
   ============================================ */

.rules-container {
    max-width: 480px;
    max-height: 80vh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}

.rules-container::-webkit-scrollbar {
    width: 5px;
}

.rules-container::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
}

.rules-section {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 10px;
}

.rules-section h3 {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--primary);
    margin: 0 0 6px 0;
    letter-spacing: 0.5px;
}

.rules-section p,
.rules-section li {
    font-size: 0.85rem;
    color: #aab;
    line-height: 1.5;
    margin: 0 0 4px 0;
}

.rules-section ul {
    padding-left: 1.2rem;
    margin: 6px 0 0;
}

.rules-section strong {
    color: #e6edf3;
}

.rules-section em {
    color: rgba(255, 255, 255, 0.4);
    font-style: normal;
    font-size: 0.8rem;
}

/* --- RECONNECTION UI --- */
.reconnect-popup-frosted {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 10000;
    width: 320px;
    background: var(--panel-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--panel-border);
    border-radius: 16px;
    padding: 24px;
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow);
    font-family: 'Outfit', sans-serif;
    animation: slideInUp 0.4s cubic-bezier(0.22, 1, 0.36, 1);
    color: white;
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

@keyframes slideInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.reconnect-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.reconnect-header .icon {
    font-size: 1.5rem;
}

.reconnect-header strong {
    color: var(--error);
    font-size: 1.1rem;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.reconnect-body {
    color: #cbd5e1;
    font-size: 0.95rem;
    line-height: 1.5;
    margin-bottom: 20px;
}

.reconnect-timer-container {
    background: rgba(0, 0, 0, 0.3);
    border-radius: 12px;
    padding: 12px;
    margin-bottom: 24px;
    text-align: center;
}

.reconnect-countdown {
    font-size: 2rem;
    font-weight: 800;
    color: white;
    display: block;
}

.reconnect-footer {
    display: flex;
    gap: 12px;
}

/* SLOT TIMER */
.slot-timer {
    position: absolute;
    top: -25px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--error);
    color: white;
    padding: 2px 10px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: bold;
    box-shadow: 0 0 10px rgba(248, 81, 73, 0.4);
    animation: pulseRed 1s infinite alternate;
    white-space: nowrap;
    z-index: 20;
}

@keyframes pulseRed {
    from {
        opacity: 0.8;
        transform: translateX(-50%) scale(0.95);
    }

    to {
        opacity: 1;
        transform: translateX(-50%) scale(1.05);
    }
}

/* --- ELIMINATION UI --- */
.eliminated-badge {
    position: absolute;
    top: -15px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--error);
    color: white;
    padding: 2px 10px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: bold;
    box-shadow: 0 0 10px rgba(248, 81, 73, 0.4);
    animation: pulseRedSimple 1s infinite alternate;
    white-space: nowrap;
    z-index: 20;
    text-transform: uppercase;
}

@keyframes pulseRedSimple {
    from {
        opacity: 0.8;
        transform: translateX(-50%) scale(0.95);
    }

    to {
        opacity: 1;
        transform: translateX(-50%) scale(1.05);
    }
}

.eliminated-seat {
    filter: grayscale(1) opacity(0.5) !important;
    pointer-events: none !important;
    transition: all 0.5s ease;
}
/* --- QoL NEW FEATURES --- */
.highlight-slap {
    box-shadow: 0 0 25px 10px gold !important;
    border-color: gold !important;
    transform: scale(1.1) !important;
    z-index: 100 !important;
    transition: all 0.2s ease-out !important;
}

.turn-progress {
    position: absolute;
    bottom: -8px;
    left: 50%;
    transform: translateX(-50%);
    height: 4px;
    background: var(--accent);
    border-radius: 2px;
    width: 0%;
    transition: width 0.1s linear;
    box-shadow: 0 0 8px var(--accent);
}

.deck.active .turn-progress {
    animation: turnCountdown linear forwards;
}

@keyframes turnCountdown {
    0% { width: 100%; background: var(--accent); box-shadow: 0 0 8px var(--accent); }
    50% { background: gold; box-shadow: 0 0 8px gold; }
    100% { width: 0%; background: var(--error); box-shadow: 0 0 8px var(--error); }
}

/* --- FAST ANIMATIONS --- */
body.fast-animations .card,
body.fast-animations .fly-in {
    transition-duration: 0.15s !important;
    animation-duration: 0.15s !important;
}

/* style.css en altina ekle */
.deck:not(.active) .turn-progress {
    display: none !important;
}

/* --- PREMIUM CONFIRM MODAL (v2.8.0 Enhanced) --- */
.modal-overlay {
    background: rgba(2, 4, 10, 0.65) !important;
    backdrop-filter: blur(20px) saturate(1.3);
    -webkit-backdrop-filter: blur(20px) saturate(1.3);
    align-items: center;
    justify-content: center;
    z-index: 10000;
    max-width: 100%;
    width: 100%;
}

.modal-content {
    background: linear-gradient(145deg, rgba(15, 20, 30, 0.92), rgba(10, 14, 22, 0.96));
    padding: 2.5rem 2.2rem;
    border-radius: 20px;
    border: 1px solid rgba(231, 76, 60, 0.15);
    box-shadow:
        0 24px 60px rgba(0, 0, 0, 0.6),
        0 0 40px rgba(231, 76, 60, 0.08),
        0 0 80px rgba(231, 76, 60, 0.04),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    text-align: center;
    max-width: 90%;
    width: 440px;
    transform: scale(0.85) translateY(20px);
    opacity: 0;
    transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* The reveal for EVERY modal, not one of them.
 *
 * .modal-content ships at opacity:0 and scale(0.85) so it can animate in. For a
 * long time exactly one rule lifted it again and it was scoped to
 * #confirm-modal. The invite modal reused the .modal-content class for its
 * styling and inherited the opacity:0 with no rule to undo it — so from v3.5.0
 * it was laid out, hit-testable, and completely transparent. Clicking "Invite"
 * dimmed the screen and showed nothing.
 *
 * Scoped to .modal-overlay.active instead, so the next modal is revealed by
 * existing under the same class rather than by someone remembering to add a
 * second rule. Specificity (0,3,0) still beats .modal-content (0,1,0). */
.modal-overlay.active .modal-content {
    transform: scale(1) translateY(0);
    opacity: 1;
}

.modal-content h3 {
    color: #fff;
    font-size: 1.5rem;
    margin-bottom: 0.5rem;
    font-weight: 800;
    letter-spacing: 0.3px;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
    line-height: 1.3;
}

.warning-icon-wrapper {
    width: 76px;
    height: 76px;
    background: radial-gradient(circle, rgba(231, 76, 60, 0.15), rgba(231, 76, 60, 0.03));
    border: 2px solid rgba(231, 76, 60, 0.35);
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0 auto 1.2rem auto;
    box-shadow:
        0 0 20px rgba(231, 76, 60, 0.2),
        0 0 50px rgba(231, 76, 60, 0.08);
    animation: warningGlowPulse 2s ease-in-out infinite alternate;
    position: relative;
}

.warning-icon-wrapper::after {
    content: '';
    position: absolute;
    inset: -8px;
    border-radius: 50%;
    border: 1px solid rgba(231, 76, 60, 0.1);
    animation: warningRingPulse 2s ease-in-out infinite alternate;
}

@keyframes warningGlowPulse {
    from {
        box-shadow: 0 0 15px rgba(231, 76, 60, 0.15), 0 0 40px rgba(231, 76, 60, 0.05);
        border-color: rgba(231, 76, 60, 0.3);
        transform: scale(1);
    }
    to {
        box-shadow: 0 0 30px rgba(231, 76, 60, 0.4), 0 0 60px rgba(231, 76, 60, 0.12);
        border-color: rgba(231, 76, 60, 0.6);
        transform: scale(1.05);
    }
}

@keyframes warningRingPulse {
    from { opacity: 0.3; transform: scale(1); }
    to   { opacity: 0.7; transform: scale(1.08); }
}

.warning-icon {
    width: 34px;
    height: 34px;
    color: #e74c3c;
    filter: drop-shadow(0 0 8px rgba(231, 76, 60, 0.6));
}

.modal-subtext {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.82rem;
    line-height: 1.5;
    margin: 0.3rem 0 2rem 0;
    padding: 0 0.5rem;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.modal-buttons {
    display: flex;
    gap: 0.8rem;
    justify-content: center;
}

.modal-buttons .btn {
    flex: 1;
    padding: 14px 22px !important;
    border-radius: 12px !important;
    font-weight: 700 !important;
    letter-spacing: 0.5px !important;
    font-size: 0.92rem !important;
    transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
    cursor: pointer !important;
    position: relative;
    overflow: hidden;
}

/* Buton shimmer efekti */
.modal-buttons .btn::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
    transition: left 0.5s ease;
}

.modal-buttons .btn:hover::before {
    left: 100%;
}

.modal-buttons .cancel-btn {
    background: rgba(255, 255, 255, 0.06) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: rgba(255, 255, 255, 0.75) !important;
}

.modal-buttons .cancel-btn:hover {
    background: rgba(255, 255, 255, 0.12) !important;
    color: #fff !important;
    box-shadow: 0 4px 16px rgba(255, 255, 255, 0.06) !important;
    transform: translateY(-2px) scale(1.02);
    border-color: rgba(255, 255, 255, 0.2) !important;
}

.modal-buttons .cancel-btn:active {
    transform: translateY(0) scale(0.97);
}

.danger-btn {
    background: linear-gradient(135deg, #e74c3c, #c0392b) !important;
    border: 1px solid rgba(231, 76, 60, 0.5) !important;
    color: #fff !important;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    box-shadow: 0 4px 15px rgba(231, 76, 60, 0.25) !important;
}

.danger-btn:hover {
    background: linear-gradient(135deg, #ff5c4d, #e74c3c) !important;
    box-shadow:
        0 6px 25px rgba(231, 76, 60, 0.45),
        0 0 15px rgba(231, 76, 60, 0.2) !important;
    border-color: rgba(231, 76, 60, 0.7) !important;
    transform: translateY(-2px) scale(1.02);
}

.danger-btn:active {
    transform: translateY(0) scale(0.97);
}

/* --- QUICK CHAT --- */
.chat-btn {
    position: absolute;
    right: -90px;
    bottom: 0px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid rgba(255,255,255,0.1);
    color: white;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    box-shadow: 0 4px 10px rgba(0,0,0,0.5);
    transition: all 0.2s ease;
    backdrop-filter: blur(5px);
    z-index: 100;
}

.chat-btn:hover {
    transform: scale(1.1);
    border-color: var(--primary);
    background: rgba(40,45,55, 0.9);
}

/* v3.27.5: the emoji and quick-chat buttons sit on the bottom edge of the
   table: `bottom: 0` of #game-container, which on a desktop IS the bottom of
   the window. Scaled from their centre, the hover pushed them 2px past that
   edge, the page became scrollable, a scrollbar opened on the right and the
   whole table narrowed while the pointer rested on them. Scaled from their
   bottom edge they grow upward and sideways only. Clipping the page instead
   is not an option: a short landscape phone scrolls it to reach its own deck. */
.emoji-btn,
.chat-btn {
    transform-origin: 50% 100%;
}

.chat-menu {
    position: absolute;
    right: -90px;
    bottom: 50px;
    background: rgba(22, 27, 34, 0.95);
    border: 1px solid rgba(88, 166, 255, 0.3);
    border-radius: 12px;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 140px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.8);
    opacity: 0;
    pointer-events: none;
    transform: translateY(10px) scale(0.9);
    transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    z-index: 110;
    backdrop-filter: blur(10px);
}

.chat-menu.active {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0) scale(1);
}

.chat-menu span {
    font-size: 0.8rem;
    font-weight: 700;
    color: #e6edf3;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: 6px;
    transition: background 0.2s, transform 0.1s;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chat-menu span:hover {
    background: rgba(88, 166, 255, 0.15);
    color: var(--primary);
    transform: translateX(3px);
}

.floating-chat {
    position: absolute;
    background: rgba(22, 27, 34, 0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: white;
    padding: 6px 12px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: 700;
    max-width: 160px;
    white-space: normal;
    text-align: center;
    word-wrap: break-word;
    pointer-events: none;
    z-index: 200;
    left: 50%;
    transform: translateX(-50%);
    bottom: 60%;
    box-shadow: 0 8px 16px rgba(0,0,0,0.5);
    animation: floatChat 1.8s ease-out forwards;
}

@keyframes floatChat {
    0% { transform: translate(-50%, 0) scale(0.6); opacity: 0; }
    15% { transform: translate(-50%, -20px) scale(1.05); opacity: 1; }
    50% { transform: translate(calc(-50% + 5px), -40px) scale(1); opacity: 0.95; }
    80% { transform: translate(calc(-50% - 5px), -65px) scale(0.95); opacity: 0.75; }
    100% { transform: translate(-50%, -90px) scale(0.85); opacity: 0; }
}

/* === REFORM STYLES: VISUAL RULES, GAME STATS, SINEMATIC VIGNETTES & 3D TROPHY === */

/* Mini Card Rules styles */
.mini-card-row {
    display: flex;
    gap: 8px;
    margin-top: 4px;
    margin-bottom: 4px;
}

.mini-card {
    width: 32px;
    height: 48px;
    background: #ffffff;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    font-family: 'Outfit', sans-serif;
    font-weight: 900;
    line-height: 1;
    user-select: none;
    pointer-events: none;
}

.mini-card .val {
    font-size: 0.8rem;
}

.mini-card .suit {
    font-size: 0.95rem;
    margin-top: -2px;
}

.mini-card.red {
    color: #f85149;
}

.mini-card.black {
    color: #0d1117;
}

/* Stats Panel styles inside Winscreen/Losescreen */
.stats-panel {
    display: flex;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
    width: 100%;
    max-width: 480px;
    margin: 1.5rem auto 1.5rem auto;
    animation: statsFadeInUp 0.6s cubic-bezier(0.25, 1, 0.5, 1) forwards;
    opacity: 0;
    transform: translateY(20px);
}

@keyframes statsFadeInUp {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.stat-card {
    flex: 1;
    min-width: 100px;
    max-width: 110px;
    background: rgba(22, 27, 34, 0.5);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 12px;
    padding: 10px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.stat-card:hover {
    transform: translateY(-4px);
    border-color: var(--primary);
}

.stat-title {
    font-size: 0.65rem;
    color: rgba(255, 255, 255, 0.5);
    text-transform: uppercase;
    font-weight: 700;
    margin-bottom: 6px;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

.stat-value {
    font-size: 1.15rem;
    font-weight: 900;
    text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}

/* Sinematic Vignette Overlays */
.victory-effect-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    pointer-events: none;
    z-index: 998; /* Right below victory screen text content but above background */
    opacity: 0;
    animation: vignetteFadeIn 1s ease-out forwards;
}

@keyframes vignetteFadeIn {
    to {
        opacity: 0.85;
    }
}

.golden-vignette {
    box-shadow: inset 0 0 120px 30px rgba(255, 215, 0, 0.25), inset 0 0 300px 100px rgba(255, 200, 0, 0.1);
}

.blood-vignette {
    box-shadow: inset 0 0 120px 40px rgba(248, 81, 73, 0.35), inset 0 0 300px 100px rgba(100, 0, 0, 0.2);
}

/* 3D Rotating Trophy */
#victory-trophy-3d {
    font-size: 5rem;
    display: inline-block;
    filter: drop-shadow(0 0 20px rgba(255, 215, 0, 0.6));
    animation: rotateTrophy3D 3s linear infinite;
    transform-style: preserve-3d;
    margin-bottom: 10px;
}

@keyframes rotateTrophy3D {
    0% {
        transform: rotateY(0deg) scale(1);
    }
    50% {
        transform: rotateY(180deg) scale(1.1);
    }
    100% {
        transform: rotateY(360deg) scale(1);
    }
}

/* --- CHALLENGE BANNER MECHANICS --- */
.challenge-banner-glass {
    position: absolute;
    top: 130px;
    left: 50%;
    transform: translateX(-50%) translateY(0);
    width: 90%;
    max-width: 320px;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 12px;
    padding: 10px 14px;
    text-align: center;
    box-shadow: 0 8px 32px var(--panel-shadow), 0 0 15px var(--panel-glow);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    z-index: 105;
    pointer-events: none;
    animation: challengeSlideDown 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

@keyframes challengeSlideDown {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

.challenge-active-title {
    font-size: 0.65rem;
    text-transform: uppercase;
    font-weight: 900;
    letter-spacing: 1.5px;
    color: var(--primary);
    margin-bottom: 4px;
    text-shadow: 0 0 6px var(--panel-glow);
}

.challenge-competitors {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
}

.challenge-competitors .name {
    font-size: 0.95rem;
    font-weight: 800;
    color: white;
}

.challenge-competitors .name.attacker {
    color: var(--primary);
    text-shadow: 0 0 8px var(--panel-glow);
}

.challenge-competitors .name.defender {
    color: #ffaa00;
    text-shadow: 0 0 8px rgba(255, 170, 0, 0.3);
}

.challenge-competitors .vs {
    font-size: 0.75rem;
    font-weight: 900;
    color: rgba(255, 255, 255, 0.4);
}

.challenge-chances {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 4px;
}

.chance-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    box-shadow: inset 0 0 2px rgba(0,0,0,0.5);
}

.chance-dot.active {
    background: #ffaa00;
    box-shadow: 0 0 8px #ffaa00, inset 0 0 2px rgba(255,255,255,0.6);
    transform: scale(1.15);
}

.chance-dot.spent {
    background: rgba(248, 81, 73, 0.15);
    border-color: rgba(248, 81, 73, 0.3);
    transform: scale(0.9);
}

/* --- BURN PILE VISUAL STACK MECHANICS --- */
.burn-indicator-pill {
    position: absolute;
    top: -32px;
    right: -8px;
    background: rgba(248, 81, 73, 0.85);
    border: 1px solid rgba(248, 81, 73, 0.4);
    box-shadow: 0 0 12px rgba(248, 81, 73, 0.6);
    border-radius: 20px;
    padding: 2px 8px;
    color: white;
    font-weight: 900;
    font-size: 0.75rem;
    display: flex;
    align-items: center;
    gap: 4px;
    z-index: 105;
    pointer-events: none;
    animation: burnPillPulse 1s infinite alternate;
}

@keyframes burnPillPulse {
    from { transform: scale(1); box-shadow: 0 0 8px rgba(248, 81, 73, 0.5); }
    to { transform: scale(1.06); box-shadow: 0 0 16px rgba(248, 81, 73, 0.8); }
}

/* --- SHOCKWAVE PARTICLE EFFECT --- */
.slap-shockwave,
.burn-shockwave {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 10px;
    height: 10px;
    border-radius: 50%;
    pointer-events: none;
    z-index: 99;
}

.slap-shockwave {
    border: 4px solid gold;
    animation: slapWaveAnim 0.4s cubic-bezier(0.1, 0.8, 0.3, 1) forwards;
}

.burn-shockwave {
    border: 4px solid var(--error);
    animation: burnWaveAnim 0.4s cubic-bezier(0.1, 0.8, 0.3, 1) forwards;
}

@keyframes slapWaveAnim {
    0% { width: 20px; height: 20px; opacity: 1; border-width: 8px; }
    100% { width: 220px; height: 330px; opacity: 0; border-width: 1px; filter: blur(2px); }
}

@keyframes burnWaveAnim {
    0% { width: 20px; height: 20px; opacity: 1; border-width: 8px; }
    100% { width: 220px; height: 330px; opacity: 0; border-width: 1px; filter: blur(3px); }
}

/* Glassmorphism unification rules override */
.lobby-content-container,
.rules-content,
.account-section,
.modal-content,
.reconnect-popup-frosted {
    background: var(--panel-bg) !important;
    border: 1px solid var(--panel-border) !important;
    border-radius: 16px !important;
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow) !important;
    backdrop-filter: blur(12px) !important;
    -webkit-backdrop-filter: blur(12px) !important;
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1) !important;
}

/* === v2.5 PREMIUM REFLEX ESPOR STYLES === */

/* 1. Reflex Speedometer HUD */
.reflex-speedometer {
    position: absolute;
    top: 35%;
    left: 50%;
    transform: translateX(-50%);
    z-index: 150;
    pointer-events: none;
    padding: 6px 14px;
    border-radius: 20px;
    font-size: 0.82rem;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    text-align: center;
    white-space: nowrap;
    animation: reflexFadeInUp 1.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

@keyframes reflexFadeInUp {
    0% { transform: translate(-50%, 20px) scale(0.6); opacity: 0; }
    15% { transform: translate(-50%, 0) scale(1.05); opacity: 1; }
    80% { transform: translate(-50%, -8px) scale(1); opacity: 0.95; }
    100% { transform: translate(-50%, -30px) scale(0.85); opacity: 0; }
}

.reflex-godlike {
    background: rgba(255, 215, 0, 0.2) !important;
    border: 1px solid rgba(255, 215, 0, 0.6) !important;
    color: #ffd700 !important;
    text-shadow: 0 0 8px rgba(255, 215, 0, 0.7);
}

.reflex-fast {
    background: rgba(46, 204, 113, 0.2) !important;
    border: 1px solid rgba(46, 204, 113, 0.6) !important;
    color: #2ecc71 !important;
    text-shadow: 0 0 8px rgba(46, 204, 113, 0.7);
}

.reflex-good {
    background: rgba(52, 152, 219, 0.2) !important;
    border: 1px solid rgba(52, 152, 219, 0.6) !important;
    color: #3498db !important;
    text-shadow: 0 0 8px rgba(52, 152, 219, 0.7);
}

.reflex-lucky {
    background: rgba(255, 255, 255, 0.1) !important;
    border: 1px solid rgba(255, 255, 255, 0.3) !important;
    color: #ecf0f1 !important;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);
}

.reflex-speedometer .badge {
    background: rgba(255, 255, 255, 0.15);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.65rem;
    margin-left: 6px;
    vertical-align: middle;
}

/* Reflex Vignette Flash Overlay */
.reflex-vignette {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    pointer-events: none;
    z-index: 1;
    animation: vignettePulse 1.2s ease-out forwards;
}

@keyframes vignettePulse {
    0% { opacity: 0; }
    15% { opacity: 1; }
    100% { opacity: 0; }
}

/* 2. Combustion Slap Streak glow */
.combustion-glow {
    position: relative;
    border-color: #ff5722 !important;
    box-shadow: 0 0 15px rgba(255, 87, 34, 0.6), inset 0 0 10px rgba(255, 87, 34, 0.3) !important;
    animation: combustionPulse 1.5s infinite alternate !important;
}

@keyframes combustionPulse {
    from { box-shadow: 0 0 12px rgba(255, 87, 34, 0.4), inset 0 0 8px rgba(255, 87, 34, 0.2); border-color: #ff5722; }
    to { box-shadow: 0 0 22px rgba(255, 87, 34, 0.8), inset 0 0 16px rgba(255, 87, 34, 0.4); border-color: #ff9800; }
}

/* Ember floating particles */
.ember-particle {
    position: absolute;
    background: radial-gradient(circle, #ffeb3b 20%, #ff5722 80%);
    border-radius: 50%;
    pointer-events: none;
    z-index: 10;
    opacity: 0;
    filter: blur(0.5px);
    box-shadow: 0 0 6px #ff5722;
    animation: floatEmberUp 1.2s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}

@keyframes floatEmberUp {
    0% { transform: translateY(0) scale(0.6) rotate(0deg); opacity: 0; }
    20% { opacity: 1; }
    80% { opacity: 0.8; }
    100% { transform: translateY(-70px) scale(0.2) rotate(180deg); opacity: 0; }
}

/* Streak flame badge for names */
.streak-tag {
    display: inline-block;
    color: #ff5722;
    font-weight: 900;
    font-size: 0.72rem;
    padding: 1px 5px;
    background: rgba(255, 87, 34, 0.15);
    border: 1px solid rgba(255, 87, 34, 0.3);
    border-radius: 4px;
    margin-left: 5px;
    vertical-align: middle;
    text-shadow: 0 0 4px rgba(255, 87, 34, 0.4);
    animation: pulse 1s infinite alternate;
}

@keyframes pulse {
    from { transform: scale(1); }
    to { transform: scale(1.08); }
}

/* Combustion Shield Styles */
.deck-shield {
    position: absolute;
    top: -15px;
    right: -15px;
    font-size: 2.2rem;
    background: rgba(15, 23, 42, 0.9);
    border: 2px solid #58a6ff;
    border-radius: 50%;
    width: 48px;
    height: 48px;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 0 0 15px rgba(88, 166, 255, 0.8), inset 0 0 8px rgba(88, 166, 255, 0.3);
    animation: shieldFloat 2s ease-in-out infinite alternate, shieldGlow 1.5s infinite alternate;
    z-index: 15;
    pointer-events: none; /* Make sure it doesn't block tap clicks */
}

.deck-shield .shield-timer-text {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -35%); /* Perfect absolute alignment in the middle of the shield emoji body */
    font-size: 0.75rem;
    font-weight: 900;
    color: #ffffff;
    text-shadow: 0 0 3px #000, 0 0 5px #000, 0 0 5px #000;
    pointer-events: none;
    font-family: 'Outfit', sans-serif;
    z-index: 16;
}

@keyframes shieldFloat {
    0% { transform: translateY(0) scale(1); }
    100% { transform: translateY(-5px) scale(1.05); }
}

@keyframes shieldGlow {
    from {
        box-shadow: 0 0 10px rgba(88, 166, 255, 0.5), inset 0 0 5px rgba(88, 166, 255, 0.3);
        border-color: #58a6ff;
    }
    to {
        box-shadow: 0 0 20px rgba(255, 87, 34, 0.8), inset 0 0 10px rgba(255, 87, 34, 0.5);
        border-color: #ff5722;
    }
}


/* ═══════════════════════════════════════════════════════
   v2.8.0 PREMIUM UI BEAUTIFICATION
   Saf CSS güzelleştirmeler — sıfır HTML/JS değişikliği
   ═══════════════════════════════════════════════════════ */

/* --- 1. Panel Başlık Neon Alt Çizgi --- */
.panel-title,
#rules-panel h2,
#leaderboard-panel h2,
#account-panel h2 {
    position: relative;
    padding-bottom: 14px;
    margin-bottom: 1.5rem;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}

.panel-title::after,
#rules-panel h2::after,
#leaderboard-panel h2::after,
#account-panel h2::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 60%;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--primary), transparent);
    box-shadow: 0 0 10px var(--panel-glow);
}

/* --- 2. Checkbox Toggle Efekti --- */
.setting-group input[type="checkbox"] {
    accent-color: var(--primary);
    transition: transform 0.15s ease, box-shadow 0.2s ease;
    cursor: pointer;
}

.setting-group input[type="checkbox"]:hover {
    transform: scale(1.2);
    box-shadow: 0 0 8px var(--panel-glow);
}

.setting-group input[type="checkbox"]:checked {
    box-shadow: 0 0 12px var(--panel-glow);
}

/* --- 3. Rules Section Hover Slide --- */
.rules-section {
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

.rules-section:hover {
    transform: translateX(4px);
    box-shadow: -4px 0 15px var(--panel-glow);
}

/* --- 4. Mini Kart Hover Animasyonu --- */
.mini-card {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease;
}

.mini-card:hover {
    transform: rotate(-5deg) scale(1.12) translateY(-4px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}

/* --- 5. Tema Renkli Özel Scrollbar --- */
.scrollable-screen::-webkit-scrollbar {
    width: 5px;
}

.scrollable-screen::-webkit-scrollbar-track {
    background: transparent;
    margin: 10px 0;
}

.scrollable-screen::-webkit-scrollbar-thumb {
    background: var(--primary);
    border-radius: 4px;
    opacity: 0.6;
}

.scrollable-screen::-webkit-scrollbar-thumb:hover {
    background: var(--accent);
}

/* Firefox scrollbar */
.scrollable-screen {
    scrollbar-width: thin;
    scrollbar-color: var(--primary) transparent;
}

/* Match history scrollbar */
#match-history-container::-webkit-scrollbar {
    width: 4px;
}

#match-history-container::-webkit-scrollbar-track {
    background: transparent;
}

#match-history-container::-webkit-scrollbar-thumb {
    background: var(--primary);
    border-radius: 3px;
}

#match-history-container {
    scrollbar-width: thin;
    scrollbar-color: var(--primary) transparent;
}

/* --- 6. Leaderboard Girişleri Premium Stil --- */
#leaderboard-content > div {
    transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
    border-radius: 10px;
    border-left: 3px solid transparent;
}

#leaderboard-content > div:hover {
    transform: translateX(4px);
    background: rgba(255, 255, 255, 0.03);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

/* Top 3: Altın / Gümüş / Bronz */
#leaderboard-content > div:nth-child(1) {
    border-left-color: #ffd700;
}

#leaderboard-content > div:nth-child(2) {
    border-left-color: #c0c0c0;
}

#leaderboard-content > div:nth-child(3) {
    border-left-color: #cd7f32;
}

/* --- 7. Btn Secondary Hover Lift --- */
.btn.secondary {
    transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1);
}

.btn.secondary:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35), 0 0 10px var(--panel-glow);
}

.btn.secondary:active {
    transform: translateY(0) scale(0.97);
}

/* --- 8. Modal Overlay Fade-In (animasyon) --- */
.modal-overlay.active {
    animation: modalFadeIn 0.3s ease-out;
}

@keyframes modalFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* --- 9. Lobby Divider Efekti --- */
.lobby-divider {
    position: relative;
    text-align: center;
    margin: 0.5rem 0;
}

.lobby-divider span {
    background: var(--panel-bg);
    padding: 0 12px;
    color: rgba(255, 255, 255, 0.35);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 2px;
    font-weight: 600;
    position: relative;
    z-index: 1;
}

.lobby-divider::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--panel-border), transparent);
}

/* --- 10. Account Panel — Fullscreen Blur Overlay --- */
#account-panel {
    z-index: 50;
    max-width: 100%;
    width: 100%;
    background: rgba(2, 4, 10, 0.6);
    backdrop-filter: blur(20px) saturate(1.3);
    -webkit-backdrop-filter: blur(20px) saturate(1.3);
}

#account-panel h2 {
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.6);
}

/* v3.10.0 — a positional hover written when this slot held a different
   element. `.profile-identity` now carries its own hover, by name. */

/* --- 11. Rules Panel Kompakt & Zengin Animasyonlar --- */
#rules-panel {
    padding: 0.8rem 0.5rem;
}

#rules-panel .lobby-content-container {
    padding: 1.5rem 1.2rem;
    max-height: 94vh;
}

#rules-panel .panel-title {
    margin-bottom: 1rem;
}

/* Kural bölümleri sıralı giriş animasyonu */
.rules-section {
    opacity: 0;
    transform: translateY(12px);
    animation: ruleFadeIn 0.5s ease forwards;
}

.rules-section:nth-child(1)  { animation-delay: 0.05s; }
.rules-section:nth-child(2)  { animation-delay: 0.1s; }
.rules-section:nth-child(3)  { animation-delay: 0.15s; }
.rules-section:nth-child(4)  { animation-delay: 0.2s; }
.rules-section:nth-child(5)  { animation-delay: 0.25s; }
.rules-section:nth-child(6)  { animation-delay: 0.3s; }
.rules-section:nth-child(7)  { animation-delay: 0.35s; }
.rules-section:nth-child(8)  { animation-delay: 0.4s; }
.rules-section:nth-child(9)  { animation-delay: 0.45s; }
.rules-section:nth-child(10) { animation-delay: 0.5s; }
.rules-section:nth-child(11) { animation-delay: 0.55s; }
.rules-section:nth-child(12) { animation-delay: 0.6s; }

@keyframes ruleFadeIn {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Kural bölümü iç glowing border hover */
.rules-section:hover {
    border-color: var(--panel-border) !important;
}

/* Rules h3 başlık emoji bounce */
.rules-section h3 {
    transition: transform 0.2s ease;
}

.rules-section:hover h3 {
    transform: translateX(3px);
}

/* Mini kart satırı hover — tüm kartlar hafifçe yayılsın */
.mini-card-row {
    transition: gap 0.3s ease;
}

.mini-card-row:hover {
    gap: 10px;
}

/* --- 12. Leaderboard Panel Kompakt & Animasyonlar --- */
#leaderboard-panel {
    padding: 0.8rem 0.5rem;
}

#leaderboard-panel .rules-content {
    max-height: 75vh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--primary) transparent;
}

#leaderboard-panel .rules-content::-webkit-scrollbar {
    width: 4px;
}

#leaderboard-panel .rules-content::-webkit-scrollbar-thumb {
    background: var(--primary);
    border-radius: 3px;
}

/* Leaderboard sıralı giriş animasyonu */
#leaderboard-content > div {
    opacity: 0;
    transform: translateX(-10px);
    animation: leaderSlideIn 0.4s ease forwards;
}

#leaderboard-content > div:nth-child(1)  { animation-delay: 0.05s; }
#leaderboard-content > div:nth-child(2)  { animation-delay: 0.1s; }
#leaderboard-content > div:nth-child(3)  { animation-delay: 0.15s; }
#leaderboard-content > div:nth-child(4)  { animation-delay: 0.2s; }
#leaderboard-content > div:nth-child(5)  { animation-delay: 0.25s; }
#leaderboard-content > div:nth-child(6)  { animation-delay: 0.3s; }
#leaderboard-content > div:nth-child(7)  { animation-delay: 0.35s; }
#leaderboard-content > div:nth-child(8)  { animation-delay: 0.4s; }
#leaderboard-content > div:nth-child(9)  { animation-delay: 0.45s; }
#leaderboard-content > div:nth-child(10) { animation-delay: 0.5s; }

@keyframes leaderSlideIn {
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Top 3 özel parlama efektleri */
#leaderboard-content > div:nth-child(1) {
    background: linear-gradient(135deg, rgba(255, 215, 0, 0.06), transparent) !important;
}

#leaderboard-content > div:nth-child(2) {
    background: linear-gradient(135deg, rgba(192, 192, 192, 0.05), transparent) !important;
}

#leaderboard-content > div:nth-child(3) {
    background: linear-gradient(135deg, rgba(205, 127, 50, 0.05), transparent) !important;
}

/* --- 13. Panel Title Neon Glow Pulse --- */
.panel-title::after,
#rules-panel h2::after,
#leaderboard-panel h2::after,
#account-panel h2::after {
    animation: titleGlowPulse 3s ease-in-out infinite alternate;
}

@keyframes titleGlowPulse {
    from { box-shadow: 0 0 8px var(--panel-glow); opacity: 0.7; }
    to   { box-shadow: 0 0 18px var(--panel-glow); opacity: 1; }
}

/* --- 14. Select Dropdown Hover Glow --- */
select {
    transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

select:hover {
    border-color: rgba(255, 255, 255, 0.15);
    background: rgba(22, 27, 34, 0.9);
}

/* --- 15. Comfort & Accessibility Settings (v2.9.0) --- */

/* Reduced Motion: near-instantly resolve all animations/transitions instead of
   fully removing them, so elements still land on their correct final visual
   state (opacity, position) instead of getting stuck mid-animation. Also turns
   off the mouse-driven menu parallax (see parallax3d.js). */
body.reduced-motion *,
body.reduced-motion *::before,
body.reduced-motion *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
    scroll-behavior: auto !important;
}

/* High Legibility: plain system sans-serif, wider letter/line spacing, no
   decorative text-shadow. A real readability boost with no external font file. */
body.high-legibility,
body.high-legibility input,
body.high-legibility select,
body.high-legibility button {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif !important;
    letter-spacing: 0.02em;
}
body.high-legibility p,
body.high-legibility label,
body.high-legibility .stat-title,
body.high-legibility .rules-section p {
    line-height: 1.7 !important;
}
body.high-legibility h1,
body.high-legibility h2,
body.high-legibility h3,
body.high-legibility .victory-title,
body.high-legibility .stat-value {
    text-shadow: none !important;
}

/* Larger Text scales the html root font-size directly via JS (settings.js) since
   rem units are relative to <html>, not <body> — no CSS class needed here. */


/* --- 16. Session Win-Streak Banner (v2.9.0) --- */
.streak-banner {
    display: inline-block;
    margin: 0.6rem auto 0;
    padding: 0.5rem 1.4rem;
    border-radius: 999px;
    font-weight: 700;
    font-size: 1rem;
    color: #ffb347;
    background: rgba(255, 140, 0, 0.12);
    border: 1px solid rgba(255, 159, 10, 0.4);
    box-shadow: 0 0 18px rgba(255, 140, 0, 0.25);
    animation: streakPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.streak-banner-best {
    color: #ffd700;
    background: rgba(255, 215, 0, 0.14);
    border-color: rgba(255, 215, 0, 0.5);
    box-shadow: 0 0 22px rgba(255, 215, 0, 0.35);
}
.streak-banner-milestone {
    font-size: 1.15rem;
    padding: 0.7rem 1.7rem;
    color: #ff6b6b;
    background: rgba(255, 87, 87, 0.16);
    border-color: rgba(255, 107, 107, 0.6);
    box-shadow: 0 0 28px rgba(255, 87, 87, 0.45);
    animation: streakPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), streakMilestonePulse 1.4s ease-in-out 0.5s infinite;
}
@keyframes streakMilestonePulse {
    0%, 100% { box-shadow: 0 0 28px rgba(255, 87, 87, 0.45); }
    50%      { box-shadow: 0 0 40px rgba(255, 87, 87, 0.7); }
}
@keyframes streakPop {
    0%   { transform: scale(0.7); opacity: 0; }
    60%  { transform: scale(1.08); opacity: 1; }
    100% { transform: scale(1); }
}


/* --- 17. Share Result Button (v2.9.0) --- */
.share-result-btn {
    flex-basis: 100%;
    margin-top: 0.6rem;
    padding: 0.65rem 1rem;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    background: rgba(255, 255, 255, 0.06);
    color: #e6edf3;
    font-family: inherit;
    font-weight: 600;
    font-size: 0.95rem;
    cursor: pointer;
    transition: background 0.2s ease, transform 0.15s ease, border-color 0.2s ease;
}
.share-result-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.3);
    transform: translateY(-1px);
}
.share-result-btn:active {
    transform: translateY(0);
}
.share-result-btn:disabled {
    cursor: wait;
}
.share-result-btn:focus-visible {
    outline: 2px solid #58a6ff;
    outline-offset: 2px;
}

/* --- 18. Perfect Slap Precision Bonus (v2.9.0) --- */
/* Implements what the rules panel has always promised (rPerfectTitle/rPerfectDesc):
   slapping within 15px of the pile's visual center on a winning slap triggers a
   neon star-burst + a bright ascending chime (see ui.js / audioManager.js). */
.perfect-slap-burst {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    pointer-events: none;
    z-index: 100;
}
.perfect-slap-star {
    position: absolute;
    top: 0;
    left: 0;
    width: 6px;
    height: 6px;
    transform: rotate(var(--angle)) translateY(0) scale(0.3);
    animation: perfectSlapStarFly 0.7s ease-out forwards;
}
.perfect-slap-star::before {
    content: '✦';
    position: absolute;
    color: #e0aaff;
    text-shadow: 0 0 8px #b967ff, 0 0 16px #7c3aed;
    font-size: 18px;
    transform: translate(-50%, -50%);
}
@keyframes perfectSlapStarFly {
    0%   { transform: rotate(var(--angle)) translateY(0) scale(0.3); opacity: 1; }
    100% { transform: rotate(var(--angle)) translateY(-90px) scale(1); opacity: 0; }
}

.perfect-slap-toast {
    position: absolute;
    top: -50px;
    left: 50%;
    white-space: nowrap;
    font-weight: 900;
    font-size: 1.3rem;
    color: #e0aaff;
    text-shadow: 0 0 10px #b967ff, 0 0 24px #7c3aed;
    pointer-events: none;
    z-index: 101;
    animation: perfectSlapToastPop 1.1s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}
@keyframes perfectSlapToastPop {
    0%   { transform: translateX(-50%) translateY(10px) scale(0.6); opacity: 0; }
    15%  { transform: translateX(-50%) translateY(-10px) scale(1.15); opacity: 1; }
    30%  { transform: translateX(-50%) translateY(-15px) scale(1); opacity: 1; }
    80%  { opacity: 1; }
    100% { transform: translateX(-50%) translateY(-40px) scale(1); opacity: 0; }
}

/* --- 19. Practice / Tutorial Mode (v2.9.0) --- */
#tutorial-screen {
    background: rgba(10, 14, 20, 0.55);
    backdrop-filter: blur(18px) saturate(1.3);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
}
.tutorial-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
    position: relative;
    text-align: center;
    background: linear-gradient(160deg, rgba(22, 27, 34, 0.45), rgba(30, 40, 55, 0.3));
    border: 1px solid rgba(167, 139, 250, 0.12);
    border-radius: 24px;
    padding: 2.5rem 2rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

.tutorial-exit-btn {
    position: absolute;
    top: 0;
    right: 0;
    background: rgba(167, 139, 250, 0.12);
    border: 1px solid rgba(167, 139, 250, 0.4);
    color: #d6bbfb;
    padding: 0.5rem 1.1rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}
.tutorial-exit-btn:hover {
    background: rgba(167, 139, 250, 0.22);
    border-color: rgba(214, 187, 251, 0.7);
    box-shadow: 0 0 14px rgba(167, 139, 250, 0.35);
    transform: translateY(-1px);
}
.tutorial-exit-btn:active {
    transform: translateY(0);
}
.tutorial-exit-btn:focus-visible {
    outline: 2px solid #d6bbfb;
    outline-offset: 2px;
}

.tutorial-intro h2,
.tutorial-done h2 {
    font-size: 1.6rem;
    margin-bottom: 1rem;
    color: #d6bbfb;
    text-shadow: 0 0 20px rgba(167, 139, 250, 0.4);
}
.tutorial-intro p,
.tutorial-done p {
    font-size: 1rem;
    line-height: 1.6;
    opacity: 0.85;
    max-width: 420px;
    margin: 0 auto 2rem;
}

.tutorial-table {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
}

.tutorial-pile {
    position: relative;
    width: 90px;
    height: 130px;
    margin-bottom: 2.5rem;
}

.tutorial-progress {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
}
.tutorial-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.2);
    transition: background 0.3s ease, transform 0.3s ease, border-color 0.3s ease;
}
.tutorial-dot.active {
    background: #a78bfa;
    border-color: #d6bbfb;
    box-shadow: 0 0 10px rgba(167, 139, 250, 0.6);
    transform: scale(1.3);
}
.tutorial-dot.done {
    background: #2ecc71;
    border-color: #2ecc71;
}

.bot-personality-icon {
    display: inline-block;
    font-size: 0.9em;
    filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.4));
}

.tutorial-coach {
    max-width: 340px;
    min-height: 3rem;
    font-size: 1.05rem;
    font-weight: 600;
    color: #fff;
    background: rgba(167, 139, 250, 0.12);
    border: 1px solid rgba(167, 139, 250, 0.4);
    border-radius: 14px;
    padding: 1rem 1.2rem;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.35s ease, transform 0.35s ease;
}
.tutorial-coach.visible {
    opacity: 1;
    transform: translateY(0);
}

@keyframes tutorialFlashCorrect {
    0%   { filter: brightness(1); }
    40%  { filter: brightness(1.6) drop-shadow(0 0 20px #2ecc71); }
    100% { filter: brightness(1); }
}
.tutorial-flash-correct {
    animation: tutorialFlashCorrect 0.5s ease;
}

@keyframes tutorialFlashMiss {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-6px); }
    75% { transform: translateX(6px); }
}
.tutorial-flash-miss {
    animation: tutorialFlashMiss 0.3s ease;
}

/* --- 20. Danger Zone Tension System (v2.9.0) --- */
/* Uses ::after + outline (not box-shadow/border) deliberately, so this never
   collides with .combustion-glow's box-shadow/border !important rules — a
   player can be on a shield streak AND down to their last card at once, and
   both visuals need to render without one clobbering the other. */
.danger-warning::after,
.danger-critical::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 14px;
    pointer-events: none;
    z-index: 1;
}
.danger-warning::after {
    outline: 2px solid rgba(251, 146, 60, 0.7);
    animation: dangerWarningPulse 2s ease-in-out infinite;
}
.danger-critical::after {
    outline: 3px solid rgba(239, 68, 68, 0.85);
    animation: dangerCriticalPulse 1s ease-in-out infinite;
}
@keyframes dangerWarningPulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 0.9; }
}
@keyframes dangerCriticalPulse {
    0%, 100% { opacity: 0.5; transform: scale(1); }
    50%      { opacity: 1; transform: scale(1.04); }
}

.deck-lastcard {
    position: absolute;
    bottom: -14px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.58rem;
    font-weight: 900;
    letter-spacing: 0.02em;
    color: #fff;
    background: rgba(239, 68, 68, 0.92);
    border: 1px solid #ff9d9d;
    border-radius: 6px;
    padding: 2px 6px;
    white-space: nowrap;
    box-shadow: 0 0 10px rgba(239, 68, 68, 0.6);
    animation: lastCardPulse 1s ease-in-out infinite;
    z-index: 16;
    pointer-events: none;
}
@keyframes lastCardPulse {
    0%, 100% { transform: translateX(-50%) scale(1); }
    50%      { transform: translateX(-50%) scale(1.12); }
}

/* --- 21. MVP Moment (v2.9.0) --- */
.mvp-moment {
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
    color: #ffd166;
    background: rgba(255, 209, 102, 0.1);
    border: 1px solid rgba(255, 209, 102, 0.35);
    border-radius: 12px;
    padding: 0.6rem 1rem;
    margin: 0 auto 0.8rem;
    max-width: 420px;
    animation: mvpMomentFadeIn 0.5s ease;
}
@keyframes mvpMomentFadeIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* --- 22. Quick Match Timer / Blitz Mode (v2.9.0) --- */
#match-timer-display {
    position: absolute;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(22, 27, 34, 0.75);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 10px;
    padding: 4px 14px;
    font-weight: 800;
    font-size: 0.95rem;
    color: #e6edf3;
    z-index: 50;
    backdrop-filter: blur(4px);
}
.match-timer-critical {
    color: #ef4444;
    animation: matchTimerCriticalPulse 1s ease-in-out infinite;
}
@keyframes matchTimerCriticalPulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.5; }
}

/* --- 23. Account Panel Visual Upgrade (v2.9.0) --- */
.auth-card {
    width: 100%;
    max-width: 380px;
    margin: 0 auto;
    padding: 2rem 1.6rem;
    background: linear-gradient(160deg, rgba(88, 166, 255, 0.08), rgba(22, 27, 34, 0.55));
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 18px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.auth-input-wrap {
    position: relative;
    width: 100%;
}
.auth-input-icon {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.1rem;
    opacity: 0.75;
    pointer-events: none;
    z-index: 3;
}
.auth-input.crisp-dark {
    text-align: left;
    padding-left: 46px;
}

/* --- 24. Card Skins (v2.9.0 — Enhanced, 12 Skins) --- */
/* Each skin overrides background/border/box-shadow. The index colours are NOT
   left to .card.red/.card.black: eleven of these faces are near-black, and the
   engine's #0d1117 on them measured 1.0 : 1 — black on black (council ERS-26).
   Every dark skin sets its own two index colours below ("Readable indices"),
   each >= 4.5 : 1 against every stop of its gradient; the suite checks it. */

/* ═══ GOLDEN ═══ — Luxurious gold metallic */
.card.card-skin-golden {
    background: linear-gradient(145deg, #3d2e00 0%, #1a1300 40%, #5a4400 70%, #1a1300 100%);
    border: 2px solid #ffd700;
    box-shadow: 0 0 18px rgba(255, 215, 0, 0.6), 0 0 40px rgba(255, 215, 0, 0.2), inset 0 0 20px rgba(255, 215, 0, 0.15);
    overflow: hidden;
}
.card.card-skin-golden .card-top,
.card.card-skin-golden .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(255, 215, 0, 0.7)); }
.card.card-skin-golden .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(255, 215, 0, 0.5)); }

/* ═══ NEON ═══ — Electric cyan glow */
.card.card-skin-neon {
    background: linear-gradient(145deg, #0a1628 0%, #060d14 50%, #0d2035 100%);
    border: 2px solid #00e5ff;
    box-shadow: 0 0 18px rgba(0, 229, 255, 0.6), 0 0 40px rgba(0, 229, 255, 0.2), inset 0 0 20px rgba(0, 229, 255, 0.12);
    overflow: hidden;
}
.card.card-skin-neon .card-top,
.card.card-skin-neon .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(0, 229, 255, 0.8)); }
.card.card-skin-neon .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 12px rgba(0, 229, 255, 0.6)); }

/* ═══ SHADOW ═══ — Matte black with crimson accents (inspired by black playing cards) */
.card.card-skin-shadow {
    background: linear-gradient(145deg, #1a1a1a 0%, #0a0a0a 40%, #1f1f1f 70%, #0d0d0d 100%);
    border: 2px solid #e53e3e;
    box-shadow: 0 0 18px rgba(229, 62, 62, 0.5), 0 0 35px rgba(229, 62, 62, 0.15), inset 0 0 18px rgba(229, 62, 62, 0.1);
    overflow: hidden;
}
.card.card-skin-shadow .card-top,
.card.card-skin-shadow .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 5px rgba(229, 62, 62, 0.6)); }
.card.card-skin-shadow .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 8px rgba(229, 62, 62, 0.4)); }

/* ═══ INFERNO ═══ — Volcanic fire and molten lava */
.card.card-skin-inferno {
    background: linear-gradient(145deg, #3d0c00 0%, #1a0500 35%, #5a1a00 60%, #2d0800 100%);
    border: 2px solid #ff6b35;
    box-shadow: 0 0 18px rgba(255, 107, 53, 0.6), 0 0 40px rgba(255, 60, 0, 0.2), inset 0 0 20px rgba(255, 107, 53, 0.15);
    overflow: hidden;
}
.card.card-skin-inferno .card-top,
.card.card-skin-inferno .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(255, 107, 53, 0.7)); }
.card.card-skin-inferno .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(255, 60, 0, 0.5)); }

/* ═══ FROST ═══ — Icy blue and crystalline white */
.card.card-skin-frost {
    background: linear-gradient(145deg, #0d1f3c 0%, #081428 40%, #1a3050 70%, #0a1a30 100%);
    border: 2px solid #7dd3fc;
    box-shadow: 0 0 18px rgba(125, 211, 252, 0.5), 0 0 35px rgba(186, 230, 253, 0.2), inset 0 0 18px rgba(125, 211, 252, 0.12);
    overflow: hidden;
}
.card.card-skin-frost .card-top,
.card.card-skin-frost .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 5px rgba(125, 211, 252, 0.7)); }
.card.card-skin-frost .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(186, 230, 253, 0.5)); }

/* ═══ EMERALD ═══ — Deep green gem with jade glow */
.card.card-skin-emerald {
    background: linear-gradient(145deg, #0a2e1a 0%, #051a0e 40%, #1a4d2e 70%, #071f12 100%);
    border: 2px solid #34d399;
    box-shadow: 0 0 18px rgba(52, 211, 153, 0.5), 0 0 35px rgba(52, 211, 153, 0.2), inset 0 0 18px rgba(52, 211, 153, 0.12);
    overflow: hidden;
}
.card.card-skin-emerald .card-top,
.card.card-skin-emerald .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 5px rgba(52, 211, 153, 0.7)); }
.card.card-skin-emerald .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(52, 211, 153, 0.5)); }

/* ═══ ROYAL ═══ — Regal purple with amethyst glow */
.card.card-skin-royal {
    background: linear-gradient(145deg, #2a0d3d 0%, #150620 40%, #3d1560 70%, #150620 100%);
    border: 2px solid #a78bfa;
    box-shadow: 0 0 18px rgba(167, 139, 250, 0.6), 0 0 40px rgba(167, 139, 250, 0.2), inset 0 0 20px rgba(167, 139, 250, 0.15);
    overflow: hidden;
}
.card.card-skin-royal .card-top,
.card.card-skin-royal .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(167, 139, 250, 0.7)); }
.card.card-skin-royal .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(167, 139, 250, 0.5)); }

/* ═══ SAKURA ═══ — Cherry blossom pink, soft and elegant */
.card.card-skin-sakura {
    background: linear-gradient(145deg, #3d1a2e 0%, #2a0e1f 40%, #4d2040 70%, #1f0a18 100%);
    border: 2px solid #f9a8d4;
    box-shadow: 0 0 18px rgba(249, 168, 212, 0.5), 0 0 35px rgba(249, 168, 212, 0.2), inset 0 0 18px rgba(249, 168, 212, 0.12);
    overflow: hidden;
}
.card.card-skin-sakura .card-top,
.card.card-skin-sakura .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 5px rgba(249, 168, 212, 0.7)); }
.card.card-skin-sakura .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(249, 168, 212, 0.5)); }

/* ═══ PHANTOM ═══ — Ghostly dark with eerie teal shimmer */
.card.card-skin-phantom {
    background: linear-gradient(145deg, #0d1117 0%, #050608 40%, #161b22 70%, #0d1117 100%);
    border: 2px solid #4fd1c5;
    box-shadow: 0 0 20px rgba(79, 209, 197, 0.4), 0 0 45px rgba(79, 209, 197, 0.15), inset 0 0 22px rgba(79, 209, 197, 0.1);
    overflow: hidden;
}
.card.card-skin-phantom .card-top,
.card.card-skin-phantom .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(79, 209, 197, 0.7)); }
.card.card-skin-phantom .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 12px rgba(79, 209, 197, 0.5)); }

/* ═══ HOLOGRAPHIC ═══ — Rainbow prismatic, shifts through hues */
.card.card-skin-holographic {
    background: linear-gradient(145deg, #1a0a2e 0%, #0a1628 30%, #0d2e1a 60%, #2e1a0a 100%);
    border: 2px solid;
    border-image: linear-gradient(135deg, #ff6b6b, #ffd93d, #6bcf7f, #4ecdc4, #a78bfa, #ff6b9d) 1;
    box-shadow:
        0 0 20px rgba(167, 139, 250, 0.4),
        0 0 20px rgba(78, 205, 196, 0.3),
        0 0 20px rgba(255, 107, 107, 0.2),
        inset 0 0 18px rgba(167, 139, 250, 0.1);
    overflow: hidden;
}
.card.card-skin-holographic .card-top,
.card.card-skin-holographic .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 6px rgba(167, 139, 250, 0.6)); }
.card.card-skin-holographic .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 10px rgba(78, 205, 196, 0.5)); }

/* ═══ OBSIDIAN ═══ — Pure volcanic black glass, minimal and deadly */
.card.card-skin-obsidian {
    background: linear-gradient(145deg, #111111 0%, #050505 40%, #1a1a1a 60%, #080808 100%);
    border: 2px solid #555;
    box-shadow: 0 0 15px rgba(100, 100, 100, 0.3), 0 0 40px rgba(50, 50, 50, 0.15), inset 0 0 25px rgba(255, 255, 255, 0.04);
    overflow: hidden;
}
.card.card-skin-obsidian .card-top,
.card.card-skin-obsidian .card-bottom { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 4px rgba(200, 200, 200, 0.5)); }
.card.card-skin-obsidian .card-center { filter: drop-shadow(0 0 0.8px rgba(0, 0, 0, 0.95)) drop-shadow(0 0 1.6px rgba(0, 0, 0, 0.85)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 8px rgba(200, 200, 200, 0.3)); }

/* --- Readable indices on the dark skins (v3.21.1, council ERS-26) ---
   ♠♣ near-white with a trace of the skin's accent, ♥♦ a saturated red — each
   >= 4.5 : 1 against the LIGHTEST stop of that skin's background (worst case).
   The pair is also kept APART (ERS-26 review): CIEDE2000 >= 30 between the
   two, and >= 15 under simulated protanopia and deuteranopia, so red and black
   still read as two suits for colour-blind players. The red is as deep as the
   face allows; lightness carries the difference where hue cannot.
   test_gameLogic.mjs section 88 recomputes all of it from this file. */
.card.card-skin-golden.black      { color: #fff1b8; }
.card.card-skin-golden.red        { color: #f5a3b4; }
.card.card-skin-neon.black        { color: #e0fbff; }
.card.card-skin-neon.red          { color: #ff6f70; }
.card.card-skin-shadow.black      { color: #fbfbfb; }
.card.card-skin-shadow.red        { color: #ff5752; }
.card.card-skin-inferno.black     { color: #fff7ee; }
.card.card-skin-inferno.red       { color: #ff6675; }
.card.card-skin-frost.black       { color: #e6f6ff; }
.card.card-skin-frost.red         { color: #ff7a7a; }
.card.card-skin-emerald.black     { color: #f4fffa; }
.card.card-skin-emerald.red       { color: #ff968f; }
.card.card-skin-royal.black       { color: #faf8ff; }
.card.card-skin-royal.red         { color: #ff5d52; }
.card.card-skin-sakura.black      { color: #fff9fc; }
.card.card-skin-sakura.red        { color: #ff7a88; }
.card.card-skin-phantom.black     { color: #dffcf8; }
.card.card-skin-phantom.red       { color: #ff4e47; }
.card.card-skin-holographic.black { color: #fcfaff; }
.card.card-skin-holographic.red   { color: #ff6b66; }
.card.card-skin-obsidian.black    { color: #f9f9f9; }
.card.card-skin-obsidian.red      { color: #ff4e47; }

/* The characters sit ABOVE the skin's overlay (v3.21.2, council ERS-27): the
   shimmer (z-index 2–3) used to pass over the index and tint glyph and ground
   alike, dropping a red index to 2.7 : 1 at its peak. Each index and pip also
   carries a tight near-black halo before its coloured glow (the filters
   above), so the pixels next to a glyph are dark whatever the glow does. */
.card.card-skin-golden .card-top, .card.card-skin-golden .card-bottom,
.card.card-skin-neon .card-top, .card.card-skin-neon .card-bottom,
.card.card-skin-shadow .card-top, .card.card-skin-shadow .card-bottom,
.card.card-skin-inferno .card-top, .card.card-skin-inferno .card-bottom,
.card.card-skin-frost .card-top, .card.card-skin-frost .card-bottom,
.card.card-skin-emerald .card-top, .card.card-skin-emerald .card-bottom,
.card.card-skin-royal .card-top, .card.card-skin-royal .card-bottom,
.card.card-skin-sakura .card-top, .card.card-skin-sakura .card-bottom,
.card.card-skin-phantom .card-top, .card.card-skin-phantom .card-bottom,
.card.card-skin-holographic .card-top, .card.card-skin-holographic .card-bottom,
.card.card-skin-obsidian .card-top, .card.card-skin-obsidian .card-bottom { z-index: 4; }
.card.card-skin-golden .card-center,
.card.card-skin-neon .card-center,
.card.card-skin-shadow .card-center,
.card.card-skin-inferno .card-center,
.card.card-skin-frost .card-center,
.card.card-skin-emerald .card-center,
.card.card-skin-royal .card-center,
.card.card-skin-sakura .card-center,
.card.card-skin-phantom .card-center,
.card.card-skin-holographic .card-center,
.card.card-skin-obsidian .card-center { position: relative; z-index: 4; }

/* --- Shared skin overlay layer (shimmer + particles injected by JS) --- */
.card-skin-overlay {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 2;
    overflow: hidden;
}

/* Animated diagonal shimmer sweep */
.card-skin-shimmer {
    position: absolute;
    inset: -50%;
    width: 200%;
    height: 200%;
    pointer-events: none;
    z-index: 3;
}

/* Shimmer per skin — each has a unique color and speed */
.card.card-skin-golden .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(255,215,0,0.18) 45%, rgba(255,245,180,0.25) 50%, rgba(255,215,0,0.18) 55%, transparent 70%);
    animation: skinShimmer 3s ease-in-out infinite;
}
.card.card-skin-neon .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(0,229,255,0.15) 45%, rgba(180,255,255,0.22) 50%, rgba(0,229,255,0.15) 55%, transparent 70%);
    animation: skinShimmer 2.5s ease-in-out infinite;
}
.card.card-skin-shadow .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(229,62,62,0.12) 45%, rgba(255,120,120,0.18) 50%, rgba(229,62,62,0.12) 55%, transparent 70%);
    animation: skinShimmer 3.5s ease-in-out infinite;
}
.card.card-skin-inferno .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 25%, rgba(255,107,53,0.18) 42%, rgba(255,200,50,0.28) 50%, rgba(255,107,53,0.18) 58%, transparent 75%);
    animation: skinShimmer 2s ease-in-out infinite;
}
.card.card-skin-frost .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(125,211,252,0.15) 45%, rgba(220,245,255,0.25) 50%, rgba(125,211,252,0.15) 55%, transparent 70%);
    animation: skinShimmer 4s ease-in-out infinite;
}
.card.card-skin-emerald .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(52,211,153,0.15) 45%, rgba(150,255,200,0.22) 50%, rgba(52,211,153,0.15) 55%, transparent 70%);
    animation: skinShimmer 3s ease-in-out infinite;
}
.card.card-skin-royal .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(167,139,250,0.15) 45%, rgba(220,200,255,0.22) 50%, rgba(167,139,250,0.15) 55%, transparent 70%);
    animation: skinShimmer 3.5s ease-in-out infinite;
}
.card.card-skin-sakura .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 30%, rgba(249,168,212,0.15) 45%, rgba(255,220,240,0.22) 50%, rgba(249,168,212,0.15) 55%, transparent 70%);
    animation: skinShimmer 3.5s ease-in-out infinite;
}
.card.card-skin-phantom .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 25%, rgba(79,209,197,0.12) 42%, rgba(150,255,240,0.18) 50%, rgba(79,209,197,0.12) 58%, transparent 75%);
    animation: skinShimmer 4s ease-in-out infinite;
}
.card.card-skin-holographic .card-skin-shimmer {
    background: linear-gradient(120deg,
        transparent 20%,
        rgba(255,107,107,0.12) 32%,
        rgba(255,217,61,0.15) 40%,
        rgba(107,207,127,0.18) 48%,
        rgba(78,205,196,0.18) 52%,
        rgba(167,139,250,0.15) 60%,
        rgba(255,107,157,0.12) 68%,
        transparent 80%
    );
    animation: skinShimmer 2s linear infinite;
}
.card.card-skin-obsidian .card-skin-shimmer {
    background: linear-gradient(120deg, transparent 35%, rgba(200,200,200,0.06) 46%, rgba(255,255,255,0.1) 50%, rgba(200,200,200,0.06) 54%, transparent 65%);
    animation: skinShimmer 5s ease-in-out infinite;
}

@keyframes skinShimmer {
    0%   { transform: translateX(-60%) translateY(-20%) rotate(-25deg); }
    100% { transform: translateX(60%) translateY(20%) rotate(-25deg); }
}

/* Floating micro-particles */
.card-skin-particle {
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
    z-index: 4;
    opacity: 0;
    animation: skinParticleFloat 3s ease-in-out infinite;
}
@keyframes skinParticleFloat {
    0%   { opacity: 0; transform: translateY(0) scale(0.5); }
    30%  { opacity: 0.9; }
    70%  { opacity: 0.6; }
    100% { opacity: 0; transform: translateY(-30px) scale(0.2); }
}

/* Edge glow pulse — per skin color */
.card-skin-edge-glow {
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    pointer-events: none;
    z-index: 1;
}
.card.card-skin-golden .card-skin-edge-glow      { box-shadow: 0 0 12px rgba(255,215,0,0.5);     animation: edgeGlowPulse 2s ease-in-out infinite; }
.card.card-skin-neon .card-skin-edge-glow         { box-shadow: 0 0 12px rgba(0,229,255,0.5);     animation: edgeGlowPulse 1.5s ease-in-out infinite; }
.card.card-skin-shadow .card-skin-edge-glow       { box-shadow: 0 0 12px rgba(229,62,62,0.4);     animation: edgeGlowPulse 2.5s ease-in-out infinite; }
.card.card-skin-inferno .card-skin-edge-glow      { box-shadow: 0 0 14px rgba(255,107,53,0.5);    animation: edgeGlowPulse 1.5s ease-in-out infinite; }
.card.card-skin-frost .card-skin-edge-glow        { box-shadow: 0 0 12px rgba(125,211,252,0.4);   animation: edgeGlowPulse 3s ease-in-out infinite; }
.card.card-skin-emerald .card-skin-edge-glow      { box-shadow: 0 0 12px rgba(52,211,153,0.5);    animation: edgeGlowPulse 2.5s ease-in-out infinite; }
.card.card-skin-royal .card-skin-edge-glow        { box-shadow: 0 0 12px rgba(167,139,250,0.5);   animation: edgeGlowPulse 2.5s ease-in-out infinite; }
.card.card-skin-sakura .card-skin-edge-glow       { box-shadow: 0 0 12px rgba(249,168,212,0.4);   animation: edgeGlowPulse 3s ease-in-out infinite; }
.card.card-skin-phantom .card-skin-edge-glow      { box-shadow: 0 0 14px rgba(79,209,197,0.4);    animation: edgeGlowPulse 2s ease-in-out infinite; }
.card.card-skin-holographic .card-skin-edge-glow  { box-shadow: 0 0 12px rgba(167,139,250,0.3), 0 0 12px rgba(78,205,196,0.3); animation: edgeGlowPulse 1.5s ease-in-out infinite; }
.card.card-skin-obsidian .card-skin-edge-glow     { box-shadow: 0 0 10px rgba(150,150,150,0.25);  animation: edgeGlowPulse 4s ease-in-out infinite; }

@keyframes edgeGlowPulse {
    0%, 100% { opacity: 0.4; }
    50%      { opacity: 1; }
}

/* --- 25. Shop UI (v2.9.0 — Enhanced) --- */
.shop-coin-balance {
    text-align: center;
    font-size: 1.4rem;
    font-weight: 800;
    color: #ffd700;
    margin-bottom: 1.2rem;
    text-shadow: 0 0 14px rgba(255, 215, 0, 0.5);
    animation: coinBalancePulse 3s ease-in-out infinite;
}
@keyframes coinBalancePulse {
    0%, 100% { text-shadow: 0 0 14px rgba(255, 215, 0, 0.3); }
    50%      { text-shadow: 0 0 22px rgba(255, 215, 0, 0.65); }
}

.shop-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    width: 100%;
    max-width: 680px;
    margin: 0 auto 1.5rem;
}
@media (max-width: 480px) {
    .shop-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 0.7rem;
    }
}

.shop-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    background: linear-gradient(160deg, rgba(22, 27, 34, 0.7), rgba(30, 40, 55, 0.5));
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    padding: 1rem 0.6rem 0.8rem;
    transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275),
                border-color 0.3s ease,
                box-shadow 0.3s ease;
    position: relative;
    overflow: hidden;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.shop-item::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(ellipse at 50% 0%, rgba(255,255,255,0.04), transparent 70%);
    pointer-events: none;
}
.shop-item:hover {
    transform: translateY(-4px) scale(1.02);
    border-color: rgba(255, 255, 255, 0.2);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
}
.shop-item-active {
    border-color: rgba(255, 215, 0, 0.5);
    box-shadow: 0 0 20px rgba(255, 215, 0, 0.2), 0 8px 24px rgba(0, 0, 0, 0.3);
}
.shop-item-active::after {
    content: '★';
    position: absolute;
    top: 8px;
    right: 10px;
    font-size: 1rem;
    color: #ffd700;
    text-shadow: 0 0 8px rgba(255, 215, 0, 0.6);
    animation: starSpin 4s linear infinite;
}
@keyframes starSpin {
    0%   { transform: rotate(0deg) scale(1); }
    50%  { transform: rotate(180deg) scale(1.2); }
    100% { transform: rotate(360deg) scale(1); }
}

/* Skin-specific shop item hover glow */
.shop-item[data-skin="golden"]:hover       { border-color: rgba(255,215,0,0.4);     box-shadow: 0 0 25px rgba(255,215,0,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="neon"]:hover          { border-color: rgba(0,229,255,0.4);     box-shadow: 0 0 25px rgba(0,229,255,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="shadow"]:hover        { border-color: rgba(229,62,62,0.4);     box-shadow: 0 0 25px rgba(229,62,62,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="inferno"]:hover       { border-color: rgba(255,107,53,0.4);    box-shadow: 0 0 25px rgba(255,107,53,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="frost"]:hover         { border-color: rgba(125,211,252,0.4);   box-shadow: 0 0 25px rgba(125,211,252,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="emerald"]:hover       { border-color: rgba(52,211,153,0.4);    box-shadow: 0 0 25px rgba(52,211,153,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="royal"]:hover         { border-color: rgba(167,139,250,0.4);   box-shadow: 0 0 25px rgba(167,139,250,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="sakura"]:hover        { border-color: rgba(249,168,212,0.4);   box-shadow: 0 0 25px rgba(249,168,212,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="phantom"]:hover       { border-color: rgba(79,209,197,0.4);    box-shadow: 0 0 25px rgba(79,209,197,0.2), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="holographic"]:hover   { border-color: rgba(167,139,250,0.4);   box-shadow: 0 0 15px rgba(255,107,107,0.15), 0 0 15px rgba(78,205,196,0.15), 0 0 15px rgba(167,139,250,0.15), 0 12px 30px rgba(0,0,0,0.4); }
.shop-item[data-skin="obsidian"]:hover      { border-color: rgba(150,150,150,0.3);   box-shadow: 0 0 20px rgba(100,100,100,0.15), 0 12px 30px rgba(0,0,0,0.4); }

.shop-item-preview {
    position: relative;
    width: 68px;
    height: 96px;
    margin-bottom: 0.7rem;
    perspective: 600px;
}
.shop-item-preview .card {
    transition: transform 0.4s ease;
    border-radius: 8px;
}
/* Scale down card elements for small shop preview */
.shop-item-preview .card-top {
    top: 4px;
    left: 5px;
    font-size: 0.55rem;
}
.shop-item-preview .card-center {
    font-size: 1.4rem;
    text-shadow: none;
}
.shop-item-preview .card-bottom {
    bottom: 4px;
    right: 5px;
    font-size: 0.55rem;
}
.shop-item:hover .shop-item-preview .card {
    transform: rotateY(8deg) rotateX(-3deg) scale(1.08);
}

.shop-item-name {
    font-weight: 700;
    font-size: 0.95rem;
    margin-bottom: 0.6rem;
    letter-spacing: 0.3px;
}

.shop-item-btn {
    font-size: 0.8rem;
    padding: 0.55rem 0.8rem;
    width: 100%;
    border-radius: 10px;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.shop-item-btn:hover:not(:disabled) {
    transform: scale(1.04);
}
.shop-item-btn.shop-equipped {
    background: linear-gradient(135deg, rgba(255, 215, 0, 0.15), rgba(255, 215, 0, 0.08));
    color: #ffd700;
    border: 1px solid rgba(255, 215, 0, 0.4);
    cursor: default;
    text-shadow: 0 0 6px rgba(255, 215, 0, 0.3);
}
.shop-item-btn.shop-locked {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Purchase success flash */
@keyframes shopPurchaseFlash {
    0%   { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.6); }
    50%  { box-shadow: 0 0 30px 8px rgba(255, 215, 0, 0.4); }
    100% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0); }
}
.shop-item-purchased {
    animation: shopPurchaseFlash 0.6s ease-out;
}

/* --- 26. Shop Notification (v2.9.0) --- */
/* The shared #notifications element lives inside #game-container, so it's
   invisible while the shop panel (a separate .screen) is open — this is a
   scoped equivalent, same show/hide feel, sized for a calmer utility panel
   rather than a big dramatic gameplay callout. */
.shop-notification {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 85%;
    max-width: 320px;
    transform: translate(-50%, -50%) scale(0);
    pointer-events: none;
    font-size: 1.05rem;
    font-weight: 800;
    text-align: center;
    z-index: 200;
    opacity: 0;
    padding: 0.9rem 1.3rem;
    border-radius: 14px;
    background: rgba(20, 8, 8, 0.92);
    border: 1px solid rgba(239, 68, 68, 0.5);
    color: #ff9a9a;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    transition: opacity 0.2s ease-out, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

/* --- 27. Victory Screen Coin Result Badge (v2.9.0) --- */
.coin-result-badge {
    font-size: 1rem;
    font-weight: 800;
    text-align: center;
    border-radius: 999px;
    padding: 0.5rem 1.2rem;
    margin: 0 auto 0.8rem;
    max-width: 220px;
    animation: coinBadgePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.coin-result-badge.coin-gain {
    color: #ffd700;
    background: rgba(255, 215, 0, 0.12);
    border: 1px solid rgba(255, 215, 0, 0.4);
    box-shadow: 0 0 14px rgba(255, 215, 0, 0.3);
}
.coin-result-badge.coin-loss {
    color: #ff9a9a;
    background: rgba(239, 68, 68, 0.1);
    border: 1px solid rgba(239, 68, 68, 0.35);
}
@keyframes coinBadgePop {
    0%   { transform: scale(0.7); opacity: 0; }
    60%  { transform: scale(1.08); opacity: 1; }
    100% { transform: scale(1); }
}

/* v3.22.0 — the coin ledger is the server's.
   A guest's result line explains how to earn; a full day explains why a win
   paid nothing. Neither is a gain or a loss, so neither borrows those colours. */
.coin-result-badge.coin-note {
    color: var(--text-color);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    font-size: 0.85rem;
    max-width: 320px;
}

/* The shop's sign-in prompt for guests (and "loading" while the wallet arrives).
   `hidden` must win over any display a class sets. */
.shop-signin {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    max-width: 460px;
    margin: 0 auto 1rem;
    padding: 0.9rem 1.1rem;
    text-align: center;
    border-radius: 12px;
    background: var(--panel-bg);
    border: 1px solid rgba(255, 215, 0, 0.35);
}
.shop-signin p { margin: 0; line-height: 1.45; }
.shop-signin[hidden], #btn-shop-signin[hidden], .admin-panel[hidden] { display: none !important; }

/* Admin: send coins. Only admin accounts ever see it (adminPanel.js). */
.admin-panel { border-color: rgba(255, 215, 0, 0.45); }
.admin-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.5rem 0;
}
.admin-input { flex: 1 1 160px; min-width: 0; text-align: left; }
.admin-btn { flex: 0 0 auto; }
.admin-results { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.admin-result { font-size: 0.85rem; padding: 0.35rem 0.7rem; }
.admin-result.is-picked { border-color: var(--accent); color: var(--accent); }
.admin-send { width: 100%; margin-top: 0.3rem; }
.admin-open-link { display: block; text-align: center; margin: 0.4rem 0 0.6rem; text-decoration: none; }
.admin-status { min-height: 1.4em; margin-top: 0.5rem; font-size: 0.9rem; line-height: 1.4; }
.admin-status.is-ok { color: #3fb950; }
.admin-status.is-error { color: #ff7b72; }

/* =====================================================================
   v3.0.0 — House Rules, Slap Coach, Fair-Slap HUD, Daily Challenge
   ===================================================================== */

/* ---------- Slap Coach chip (slapForensics.js) ----------------------- */
/* Anchored above the pile: close enough to the cards that the player's eyes
   are already there, far enough not to cover the pattern being explained. */
.slap-coach {
    position: absolute;
    left: 50%;
    bottom: calc(100% + 14px);
    transform: translate(-50%, 8px);
    z-index: 60;
    max-width: min(78vw, 420px);
    padding: 8px 16px;
    border-radius: 999px;
    font-size: 0.92rem;
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: center;
    pointer-events: none;
    opacity: 0;
    backdrop-filter: blur(10px);
    border: 1px solid var(--panel-border);
    background: rgba(22, 27, 34, 0.88);
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.45);
    transition: opacity 0.18s ease, transform 0.18s ease;
}

.slap-coach.visible {
    opacity: 1;
    transform: translate(-50%, 0);
}

.slap-coach.good {
    color: #7ee2a8;
    border-color: rgba(63, 185, 80, 0.55);
    box-shadow: 0 8px 26px rgba(63, 185, 80, 0.25);
}

.slap-coach.bad {
    color: #ffb4ad;
    border-color: rgba(248, 81, 73, 0.5);
    box-shadow: 0 8px 26px rgba(248, 81, 73, 0.22);
}

.reduced-motion .slap-coach {
    transition: opacity 0.12s linear;
    transform: translate(-50%, 0);
}

@media (max-width: 560px) {
    .slap-coach {
        font-size: 0.8rem;
        padding: 6px 12px;
        bottom: calc(100% + 8px);
    }
}

/* ---------- Connection quality HUD (netQuality.js) ------------------- */
/* Bottom-right corner. Deliberately NOT top-right: that is `#btn-quit`
   (.btn-small) on every screen size and `#top-right-score` on mobile. The
   bottom-left is `#action-log`, so this corner is the only free one. */
.net-hud {
    position: absolute;
    bottom: 18px;
    right: 15px;
    z-index: 90;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    color: rgba(255, 255, 255, 0.85);
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid var(--panel-border);
    backdrop-filter: blur(10px);
}

.net-hud-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #6e7681;
    box-shadow: 0 0 8px currentColor;
}

.net-hud.tier-excellent .net-hud-dot { background: #3fb950; }
.net-hud.tier-good      .net-hud-dot { background: #58a6ff; }
.net-hud.tier-fair      .net-hud-dot { background: #d29922; }
.net-hud.tier-poor      .net-hud-dot { background: #f85149; }

.net-hud.tier-poor {
    border-color: rgba(248, 81, 73, 0.45);
}

/* ---------- House Rules badge (rulesBadge.js) ------------------------ */
.rules-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.76rem;
    font-weight: 700;
    padding: 6px 14px;
    border-radius: 999px;
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid rgba(210, 153, 34, 0.45);
    backdrop-filter: blur(10px);
    /* Stacked directly above the connection HUD in the free bottom-right
       corner — see the note on .net-hud. */
    position: absolute;
    bottom: 52px;
    right: 15px;
    z-index: 85;
    max-width: min(90vw, 320px);
}

.rules-badge.lobby {
    position: static;
    transform: none;
    width: 100%;
    font-size: 0.85rem;
    padding: 10px 14px;
}

.rules-badge .rb-title { color: #e3b341; }
.rules-badge .rb-on    { color: #7ee2a8; }
.rules-badge .rb-off   { color: #ffb4ad; }

/* ---------- House Rules settings grid -------------------------------- */
.house-rules-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 8px;
    width: 100%;
    margin-bottom: 0.9rem;
}

.rule-row {
    display: grid;
    grid-template-columns: 20px 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--panel-border);
    cursor: pointer;
    font-size: 0.92rem;
    transition: border-color 0.15s ease, background 0.15s ease, opacity 0.15s ease;
}

.rule-row:hover { border-color: rgba(88, 166, 255, 0.4); }
.rule-row:focus-within { border-color: var(--primary); }

.rule-row input {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

.rule-row .rule-name { font-weight: 600; }

/* A switched-off rule reads as switched off at a glance — the whole row dims
   and its pattern desaturates, so the panel can be scanned rather than read. */
.rule-row:has(input:not(:checked)) { opacity: 0.44; }
.rule-row:has(input:not(:checked)) .rule-preview { filter: grayscale(1); }

/* Opt-in rules read as additions to the game, not as defaults someone removed.
   Dashed edge + a star, so the two tiers are distinguishable at a glance
   without colour alone carrying the meaning. */
.rule-row.optional {
    border-style: dashed;
}

.rule-row.optional .rule-name::after {
    content: ' ★';
    color: #e3b341;
    font-size: 0.75em;
}

/* --- miniature pattern cards ------------------------------------------- */
.rule-preview {
    display: flex;
    align-items: center;
    gap: 3px;
}

.mini-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 34px;
    border-radius: 4px;
    background: #fdfdfb;
    color: #16202c;
    border: 1px solid rgba(0, 0, 0, 0.35);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
    line-height: 1;
    font-family: inherit;
}

.mini-card b { font-size: 0.72rem; font-weight: 800; }
.mini-card i { font-size: 0.66rem; font-style: normal; }
.mini-card.red { color: #c0202a; }

/* The filling in a Sandwich: present in the pattern, not part of the match. */
.mini-card.filler {
    opacity: 0.42;
    transform: scale(0.86);
}

/* ---------- Daily Challenge panel ------------------------------------ */
.daily-head {
    width: 100%;
    max-width: 560px;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 16px;
    padding: 1.4rem;
    margin-bottom: 1.4rem;
    text-align: center;
}

.daily-sigil {
    display: flex;
    justify-content: center;
    margin-bottom: 14px;
}

.daily-sigil svg {
    border-radius: 10px;
    padding: 7px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--panel-border);
}

.daily-meta {
    display: flex;
    justify-content: center;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 0.6rem;
}

.daily-date {
    font-size: 1.5rem;
    font-weight: 900;
    letter-spacing: 1px;
}

.daily-seed {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--primary);
    opacity: 0.85;
}

.daily-blurb {
    font-size: 0.85rem;
    opacity: 0.65;
    line-height: 1.5;
    margin-bottom: 1rem;
}

.daily-best {
    font-size: 1rem;
    margin-bottom: 1.1rem;
    padding: 10px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
}

.daily-sub {
    font-size: 1.05rem;
    opacity: 0.85;
    margin-bottom: 0.7rem;
}

/* Honest-board notice. Deliberately not styled as a dismissible toast: it is a
   property of the board, not an event, so it stays as long as the board is
   unverified. Amber rather than red — the score is real, the ranking is not
   trustworthy, and that is a caution, not an error. */
.daily-board-trust {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    margin-bottom: 0.8rem;
    border-radius: 10px;
    border: 1px solid rgba(255, 186, 8, 0.4);
    border-left: 3px solid rgba(255, 186, 8, 0.85);
    background: rgba(255, 186, 8, 0.09);
    text-align: left;
}

.daily-board-trust .dbt-badge {
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #ffba08;
}

.daily-board-trust .dbt-body {
    font-size: 0.82rem;
    line-height: 1.5;
    opacity: 0.78;
}

.daily-board {
    list-style: none;
    padding: 0;
    margin: 0;
}

.daily-board li {
    display: grid;
    grid-template-columns: 2.4rem 1fr auto auto;
    align-items: center;
    gap: 10px;
    padding: 10px 6px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.daily-board li.me {
    background: rgba(88, 166, 255, 0.12);
    border-radius: 8px;
}

.daily-board .rk { font-weight: 900; }
.daily-board .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.daily-board .rx { font-size: 0.82rem; opacity: 0.6; }
.daily-board .sc { font-weight: 900; color: gold; min-width: 3.5rem; text-align: right; }

/* House Rules lock — shown while the Daily Challenge owns the rule set.
   Same amber language as the unverified-board notice: not an error, a state. */
.house-rules-lock {
    font-size: 0.8rem;
    line-height: 1.5;
    padding: 9px 12px;
    margin-bottom: 0.8rem;
    border-radius: 10px;
    border-left: 3px solid rgba(255, 186, 8, 0.85);
    background: rgba(255, 186, 8, 0.09);
    text-align: left;
    opacity: 0.9;
}

.house-rules-grid.locked {
    opacity: 0.45;
    /* Clicks still reach the disabled inputs and do nothing; this just stops
       the rows from inviting one. */
    cursor: not-allowed;
}

.house-rules-grid.locked .rule-row {
    pointer-events: none;
}

/* ---------- Slap IQ panel -------------------------------------------- */
.iq-gauge {
    position: relative;
    width: 160px;
    height: 160px;
    margin: 0 auto 0.6rem;
    color: rgba(255, 255, 255, 0.45);
}

.iq-gauge svg { width: 100%; height: 100%; display: block; }

.iq-gauge .iq-track {
    fill: none;
    stroke: rgba(255, 255, 255, 0.09);
    stroke-width: 10;
}

.iq-gauge .iq-arc {
    fill: none;
    stroke: currentColor;
    stroke-width: 10;
    stroke-linecap: round;
    filter: drop-shadow(0 0 6px currentColor);
    animation: iqSweep 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes iqSweep {
    from { stroke-dasharray: 0 999; }
}

.iq-readout {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    pointer-events: none;
}

.iq-readout .iq-num {
    font-size: 3rem;
    font-weight: 900;
    line-height: 1;
    color: var(--text-color);
    font-variant-numeric: tabular-nums;
}

.iq-readout .iq-grade {
    font-size: 1.05rem;
    font-weight: 900;
    letter-spacing: 1px;
}

.iq-gauge.grade-S { color: #e3b341; }
.iq-gauge.grade-A { color: #3fb950; }
.iq-gauge.grade-B { color: #58a6ff; }
.iq-gauge.grade-C { color: #d29922; }
.iq-gauge.grade-D { color: #f85149; }

.iq-gauge.calibrating .iq-arc { filter: none; opacity: 0.5; }
.iq-gauge.calibrating .iq-readout .iq-grade {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.6px;
    opacity: 0.75;
}

.reduced-motion .iq-gauge .iq-arc { animation: none; }

.iq-subtitle {
    text-align: center;
    font-size: 0.85rem;
    opacity: 0.6;
    margin-bottom: 1.2rem;
}

.iq-metrics {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-bottom: 1rem;
}

.iq-metrics div {
    text-align: center;
    padding: 12px 6px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--panel-border);
}

.iq-metrics span {
    display: block;
    font-size: 0.72rem;
    opacity: 0.55;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: 4px;
}

.iq-metrics strong { font-size: 1.25rem; font-weight: 900; }

.iq-totals, .iq-advice, .iq-note {
    font-size: 0.85rem;
    opacity: 0.75;
    line-height: 1.5;
    margin-bottom: 0.8rem;
}

.iq-note { opacity: 0.45; font-size: 0.78rem; }

.iq-h3 {
    font-size: 1rem;
    margin: 1.2rem 0 0.6rem;
    opacity: 0.85;
}

.iq-rules { list-style: none; padding: 0; margin: 0; }

.iq-rule {
    display: grid;
    grid-template-columns: minmax(84px, 1fr) 2fr 3rem 3.4rem;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    font-size: 0.86rem;
}

.iq-rule .bar {
    height: 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.iq-rule .bar i {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--primary), var(--accent));
}

.iq-rule .vl { font-weight: 800; text-align: right; }
.iq-rule .ct { opacity: 0.45; font-size: 0.78rem; text-align: right; }

/* v3.17.0 — pattern mastery (council ERS-16). Same row rhythm as .iq-rule
   above, same panel, no palette of its own: the three marks borrow the metal
   names the game already uses, in muted tones that sit on --panel-bg. */
.iq-mastery { list-style: none; padding: 0; margin: 0; }
.iq-mastery-row {
    display: grid;
    /* Fixed note track: every row is its own grid, so an auto track would
       let the marks drift with the note's length. */
    grid-template-columns: minmax(84px, 1fr) auto 8.5rem;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    font-size: 0.86rem;
}
.iq-mastery-row .ct { opacity: 0.55; font-size: 0.78rem; text-align: right; }
.iq-marks { display: inline-flex; gap: 6px; }
.iq-mark {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.05);
}
.iq-mark.mark-bronze.on { background: #b87333; border-color: #e8b06a; }
.iq-mark.mark-silver.on { background: #b9b9c2; border-color: #f4f4f6; }
.iq-mark.mark-gold.on { background: #d4af37; border-color: #fff0a6; }

.slapiq-actions {
    display: flex;
    gap: 10px;
    width: 100%;
    max-width: 560px;
}

.slapiq-actions .btn { flex: 1; }

/* Both corner HUDs step aside for the action log on short screens. */
@media (max-height: 620px) {
    .net-hud { bottom: 12px; padding: 3px 9px; font-size: 0.72rem; }
    .rules-badge { bottom: 42px; font-size: 0.7rem; padding: 4px 10px; }
}

/* ---------- Daily Challenge: the inherited position ------------------- */
/* Names the day's shape and your own starting hand — and nothing about the
   bots', which is the information the scenario is actually built around. */
.daily-scenario {
    width: 100%;
    text-align: left;
    padding: 12px 14px;
    margin-bottom: 12px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--panel-border);
}

.daily-scenario .ds-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
}

.daily-scenario .ds-tag {
    font-size: 0.82rem;
    font-weight: 900;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    padding: 4px 11px;
    border-radius: 999px;
    border: 1px solid currentColor;
    white-space: nowrap;
}

/* Each profile gets its own colour so the day is recognisable at a glance,
   and so two comeback days in a row are visibly the same kind of day. */
.daily-scenario .ds-comeback  { color: #f87171; }
.daily-scenario .ds-knifeEdge { color: #fbbf24; }
.daily-scenario .ds-finisher  { color: #34d399; }

.daily-scenario .ds-cards {
    font-size: 0.85rem;
    opacity: 0.7;
    white-space: nowrap;
}

.daily-scenario .ds-cards strong {
    font-size: 1.05rem;
    opacity: 1;
    color: var(--text-color);
}

.daily-scenario .ds-desc {
    font-size: 0.83rem;
    line-height: 1.5;
    opacity: 0.7;
    margin: 0;
}

/* Today's tier and the fixed rule set. Quieter than the profile tag — these are
   facts about the table, not the hook. */
.daily-scenario .ds-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 0.7rem;
    padding-top: 0.6rem;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 0.76rem;
}

.daily-scenario .ds-diff {
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid currentColor;
    opacity: 0.9;
}

.daily-scenario .ds-diff-medium { color: #58a6ff; }
.daily-scenario .ds-diff-hard { color: #ff9f43; }

.daily-scenario .ds-rules { opacity: 0.55; }

@media (max-width: 420px) {
    .daily-scenario .ds-head { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* ---------- Rules page: opt-in patterns (v3.2.0) ---------------------- */
/* Generated by rulesPanel.js from RULE_DEFS. Sits INSIDE the Slap Rules
   section — a quieter, inset block, so it reads as "and these three are
   optional" rather than as a new topic competing with the core four. */

.optional-rules {
    margin-top: 18px;
    padding: 14px 16px;
    border: 1px dashed rgba(227, 179, 65, 0.45);
    border-radius: 10px;
    background: rgba(227, 179, 65, 0.05);
}

.optional-rules .opt-rules-title {
    margin: 0 0 6px 0;
    font-size: 0.92rem;
    font-weight: 800;
    color: #e3b341;
    letter-spacing: 0.01em;
}

.optional-rules .opt-rules-intro,
.optional-rules .opt-rules-note {
    margin: 0;
    font-size: 0.82rem;
    opacity: 0.72;
    line-height: 1.5;
}

.optional-rules .opt-rules-note {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    opacity: 0.55;
}

.optional-rules .opt-rules-list {
    list-style: none;
    margin: 12px 0 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.optional-rules .opt-rule {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.optional-rules .opt-rule-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.optional-rules .opt-rule-head strong {
    font-size: 0.88rem;
}

/* The star marks the same thing it marks in Settings → House Rules: a pattern
   that is added to the game rather than one someone removed. */
.optional-rules .opt-rule-head strong::after {
    content: ' ★';
    color: #e3b341;
    font-size: 0.75em;
}

.optional-rules .opt-rule-desc {
    font-size: 0.82rem;
    opacity: 0.78;
    line-height: 1.5;
}

/* ---------- Reflex speedometer: personal comparison (v3.2.0) ---------- */
/* Sits beside the absolute grade (GODLIKE/FAST/GOOD), never replaces it. The
   grade answers "was that fast"; this answers "was that fast for you", and the
   two disagree often. Absent entirely below reflexDelta.js's sample floor. */

.reflex-speedometer .reflex-personal {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 4px;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.3px;
    vertical-align: middle;
    text-transform: none;
    text-shadow: none;
    background: rgba(0, 0, 0, 0.28);
    border: 1px solid currentColor;
}

.reflex-speedometer .rp-faster { color: #7ee787; }
.reflex-speedometer .rp-slower { color: #ffa657; }

@media (max-width: 480px) {
    /* The toast is white-space: nowrap; on a narrow phone the personal chip is
       the part that can go without losing the reading. */
    .reflex-speedometer .reflex-personal { display: none; }
}

/* ---------- Bot personality tell (v3.2.0) ---------------------------- */
/* An idle halo whose tempo and travel come ONLY from BotPersonalities — a fixed
   per-seat archetype, identical in every match at every difficulty on every
   date. See botTell.js for why it must never be driven by anything that varies
   within a match: a tell fed by the bots' actual slap scheduling would be a
   perfect oracle for a scored leaderboard, which council ERS-04 rejected.

   Applied once on gameStarted, removed on gameOver, and touched by nothing else.

   On a pseudo-element on purpose: .deck.active and .deck.burn-shake both animate
   the deck's own transform, so the tell would fight them for it.
   body.reduced-motion already disables all animations globally, so the
   accessibility case needs nothing here. */

.deck.bot-tell {
    --tell-period: 2800ms;
    --tell-sway: 1;
}

.deck.bot-tell::after {
    content: '';
    position: absolute;
    inset: -7px;
    border-radius: inherit;
    border: 1px solid currentColor;
    opacity: 0.16;
    pointer-events: none;
    z-index: -1;
    animation: botTellBreathe var(--tell-period) infinite;
}

@keyframes botTellBreathe {
    0%   { transform: scale(1);                                        opacity: 0.10; }
    50%  { transform: scale(calc(1 + 0.055 * var(--tell-sway, 1)));    opacity: 0.30; }
    100% { transform: scale(1);                                        opacity: 0.10; }
}

/* Same movement, three temperaments — the easing is the character. Blitz snaps
   out and settles; Chaos lurches; Viper glides. */
.deck.bot-tell-blitz::after { animation-timing-function: cubic-bezier(0.2, 0.9, 0.3, 1); }
.deck.bot-tell-chaos::after { animation-timing-function: cubic-bezier(0.9, 0.05, 0.1, 0.95); }
.deck.bot-tell-viper::after { animation-timing-function: ease-in-out; }

/* ---------- Practice mode: which tier a step belongs to (v3.3.0) -------- */
/* The classic four and the three opt-in patterns are never shown as one list.
   Gold + a star for opt-in, matching Settings → House Rules and the Rules page,
   so the same visual language means the same thing in all three places. */

.tutorial-tier {
    align-self: center;
    margin: 2px 0 10px;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-align: center;
    max-width: 30rem;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.05);
    opacity: 0.7;
}

.tutorial-tier.optional {
    color: #e3b341;
    border-color: rgba(227, 179, 65, 0.5);
    background: rgba(227, 179, 65, 0.08);
    opacity: 1;
}

/* An opt-in step is marked in the progress row too, so the shape of the lesson
   is visible before reaching it: four plain dots, then three starred ones. */
.tutorial-dot.optional {
    border: 1px solid #e3b341;
}

.tutorial-dot.optional.done,
.tutorial-dot.optional.active {
    background: #e3b341;
}

/* ---------- Ad slots (v3.4.0) ------------------------------------------ */
/* Reserved space, so a filled slot never SHIFTS the layout under a click.
   The reservation is why min-height is set on the empty container too: an ad
   that arrives late and pushes a button down is the same defect as an ad that
   janks a slap, just cheaper. An unconfigured build has empty containers with
   no border and no background — invisible, but still holding their ground. */

.ad-slot {
    width: 100%;
    max-width: 728px;
    margin: 0 auto;             /* an unfilled slot takes no room at all */
    min-height: 0;              /* nothing reserved until a slot is actually filled */
    /* AdSense can set height:auto!important and min-height:0!important.
       Keep the actual creative's natural height in the flex column rather
       than shrinking its host into the space left by the panel content. */
    flex: 0 0 auto;
    overflow: visible;
}

/* v3.24.1 (council ERS-37). Every slot sits between a panel's title and its
   content, never beside a control, and a filled one is marked as an ad: the
   label is the word AdSense permits ("Advertisements"), which ads.js writes
   into data-ad-label in the player's language. The bottom margin keeps the
   unit clear of the first line of the content it precedes.

   v3.27.1 (council ERS-41): `.filled` means only that the unit was REQUESTED.
   The frame, the label and the reserved height wait until Google answers with
   an ad (data-ad-status="filled"). Until then — always, while the account is
   in review — the box is laid out at the column's width (AdSense refuses a
   zero-width slot for good) and is otherwise nothing: no empty labelled frame
   for a reviewer to find. */
.ad-slot.filled:has(> ins.adsbygoogle[data-ad-status="filled"]) {
    min-height: 100px;
    margin: 4px auto 22px;
    padding: 6px 8px 8px;
    border-radius: 8px;
    /* Its own surface, so the label reads over the artwork behind it. */
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
}

.ad-slot.filled:has(> ins.adsbygoogle[data-ad-status="filled"])::before {
    content: attr(data-ad-label);
    display: block;
    margin: 0 0 6px;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    color: var(--text-color);
    opacity: 0.55;
}

.ad-slot .adsbygoogle { display: block; width: 100%; }

/* A request that came back empty leaves no labelled blank box behind. AdSense
   marks the unit `data-ad-status="unfilled"`; hiding the HOST (not just the
   unit, which is Google's own suggestion) takes the label and the reserved
   height with it. Browsers without :has() keep the box, which is untidy and
   nothing worse. */
.ad-slot.filled:has(> ins.adsbygoogle[data-ad-status="unfilled"]) { display: none; }

/* The other case with nothing to show: Google's tag never loaded (an ad
   blocker, a network that refuses it). ads.js marks the document and stops
   requesting; a box filled before the failure was noticed goes too. These two
   are the only rules that may hide an ad container. */
.ads-blocked .ad-slot { display: none; }

@media (max-width: 480px) {
    .ad-slot.filled:has(> ins.adsbygoogle[data-ad-status="filled"]) { min-height: 60px; }
}

/* ---------- Lobby side rails (v3.14.0) --------------------------------- */
/* Two 160x600 boxes in the gutter either side of the 600px content column.
   Three rules do all the work, and each is answering something a review found:

   1. HIDDEN BY DEFAULT, at every width, on every screen. The only thing that
      turns a rail on is `#main-menu.active ~ .ad-rail` inside the min-width
      query below. So the failure mode of ANY mistake — a screen switch that
      forgets something, a breakpoint that stops matching, markup moved to the
      wrong place — is "no rail", never "rail over the pile". It is also why no
      script touches these: v3.12.0 shipped a match-scoped banner with no owner
      to retire it, and this rail has no owner because it needs none.

   2. NOT INSIDE THE COLUMN. #main-menu is `overflow-y: auto`, which clips on
      both axes; the rails are body-level siblings and `position: fixed`, so no
      ancestor of theirs carries a transform (`.screen` does) that would turn
      `fixed` into `absolute` under their feet.

   3. THE CLEARANCE IS MEASURED, NOT GUESSED. v3.14.0 pinned each rail to the
      COLUMN — `50% - 484px`, i.e. 300 (half the column) + 24 (gap) + 160 (rail).
      That held a constant 24px gap and let the rails drift inward as the window
      grew: at 1920px each sat 476px from the window edge with the whole outer
      half of the screen empty. Reported from the live site.

      v3.16.4 pins them to the WINDOW instead: 24px from each edge. The
      arithmetic that matters is now the other one. The worst case is the
      NARROWEST window that shows a rail — 1200px — where a rail occupies
      24…184px and the column starts at 300px: 116px of clearance, and it only
      grows from there, so a rail can never reach the column. Both invariants
      this was always about are unchanged and still measured by smoke at
      several widths: a rail never overlaps the column, and a rail never hangs
      off the window (which would bring back the horizontal scrollbar v3.10.0
      spent a release removing).

   1200px is also written in adsConfig.js as RAIL_MIN_WIDTH, and a test asserts
   the two agree. */

.ad-rail {
    display: none;
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    width: 160px;
    z-index: 4;              /* under .screen (z:5): a rail can never cover the menu */
    pointer-events: none;    /* only a filled unit takes clicks; see .ad-rail-slot */
}

.ad-rail-left  { left: 24px; }
.ad-rail-right { right: 24px; }

.ad-rail-slot {
    width: 160px;
    min-height: 0;           /* nothing reserved until a rail is actually filled */
    overflow: hidden;
    pointer-events: auto;
}

/* A filled rail sits on the game's own panel surface rather than punching a
   rectangle out of the painting. Same tokens the other panels use, so it
   follows the five themes instead of fighting them — the note that closed
   v3.12.0's account card applies here too: an ad frame in its own private
   palette is the thing that looks bolted on. */
.ad-rail-slot.filled {
    min-height: 600px;
    border-radius: 10px;
    background: var(--panel-bg);
    box-shadow: 0 10px 30px var(--panel-shadow);
}

/* `vertical-align: top` is load-bearing, not tidiness. ads.js gives the unit
   `display: inline-block` (the fixed-size tag), and an inline-block sits on the
   text baseline — which left 4px of descender space under it and made a 600px
   rail measure 604. Measured, not guessed: the smoke walk caught it. Width and
   height here are a fallback for the case where the tag's inline style is
   stripped; RAIL_SIZE in adsConfig.js is the source of both numbers. */
.ad-rail-slot .adsbygoogle { vertical-align: top; width: 160px; height: 600px; }

@media (min-width: 1200px) {
    /* Since v3.24.1 this reveals two EMPTY boxes: the lobby is on the deny
       list and the rail slot id is blank (adsConfig.js), so no rail is ever
       filled and each one measures 160 x 0. The lobby's in-column banner that
       used to step aside here is gone from the markup. */
    #main-menu.active ~ .ad-rail { display: block; }
}

/* ---------- Shared Daily board offer (v3.16.5) -------------------------- */
/* Shown only when a ?daily= link armed a PAST day. It is the quieter of the two
   controls on purpose: the scored run is what the player came for, and this one
   cannot be scored at all. The divider says "separate thing" without a second
   card — the panel already has enough surfaces. */
.daily-replay-offer {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--panel-border);
}
.daily-replay-offer .daily-blurb { margin-bottom: 10px; }
.daily-replay-offer strong { color: var(--primary); }

/* ---------- Privacy policy link and panel ------------------------------ */

#game-version .link-btn {
    /* #game-version is pointer-events: none so the version text never eats a
       click meant for the menu behind it. That also disabled this button, which
       is the one element in there that IS meant to be clicked — caught by the
       smoke test, not by any structural check. Re-enable it for the button
       only, so the label stays click-through and the link works. */
    pointer-events: auto;
    background: none;
    border: none;
    padding: 0 0 0 10px;
    margin: 0;
    font: inherit;
    color: inherit;
    opacity: 0.75;
    text-decoration: underline;
    cursor: pointer;
}

#game-version .link-btn:hover,
#game-version .link-btn:focus-visible { opacity: 1; }

/* v3.27.1 (council ERS-41): About, Guides, Privacy move as ONE unit. In German
   and Russian the three no longer fit beside the version on a 360px phone; as
   a group the line breaks after "v3.27.1" and the links stay together on the
   second, instead of one of them dropping alone. */
#game-version .version-links { display: inline-block; }

.privacy-updated {
    opacity: 0.55;
    font-size: 0.8rem;
    margin: 0 0 14px;
}

/* v3.24.1 — reopens Google's consent message. Its own line above Back, and a
   size down from it: it is a setting, not the way out of the page. ads.js keeps
   it `hidden` unless Google's consent API says the regulation applies, and
   `hidden` alone loses to any display rule, hence the !important. */
#btn-cookie-settings {
    display: block;
    margin: 0 auto 12px;
    padding: 0.7rem 1.4rem;
    font-size: 1rem;
}
#btn-cookie-settings[hidden] { display: none !important; }

/* --- INVITE MODAL & SHARE STYLES (v3.4.2) --- */
#invite-modal {
    display: none;
}

#invite-modal.active {
    display: flex !important;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    animation: modalFadeIn 0.25s ease-out;
}

.invite-card {
    max-width: 380px;
    width: 90%;
    padding: 24px;
    border-radius: 16px;
    border: 1px solid rgba(16, 185, 129, 0.3);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6), 0 0 25px rgba(16, 185, 129, 0.15);
    text-align: center;
    position: relative;
}

.invite-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}

.invite-title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    color: #fff;
}

.invite-close-btn {
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.6);
    font-size: 1.6rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px 8px;
    border-radius: 6px;
    transition: color 0.15s, background 0.15s;
}

.invite-close-btn:hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.1);
}

.qr-wrapper {
    background: #ffffff;
    padding: 12px;
    border-radius: 12px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    margin: 14px auto 16px;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}

#invite-qr-canvas {
    display: block;
    width: 170px;
    height: 170px;
    border-radius: 4px;
}

.invite-link-box {
    display: flex;
    gap: 8px;
    margin-top: 6px;
}

.invite-input {
    flex: 1;
    font-size: 0.85rem;
    padding: 8px 10px;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 8px;
    color: #e2e8f0;
    text-overflow: ellipsis;
}

.btn-copy-link {
    padding: 8px 14px;
    font-size: 0.85rem;
    white-space: nowrap;
    border-radius: 8px;
}

/* The two table actions sit side by side under the code.
 *
 * .btn-small is position:absolute / top-right — right for a lone close button,
 * wrong the moment there are two of them: they stacked in the same corner and
 * Copy ID was unreachable underneath Share Invite. Scoped override, so every
 * other .btn-small on the site keeps its corner. */
.table-id-actions {
    display: flex;
    justify-content: center;
    align-items: stretch;
    gap: 10px;
    margin-top: 14px;
    flex-wrap: wrap;
}

.table-id-actions .btn-small {
    position: static;
    top: auto;
    right: auto;
    font-size: 0.9rem;
    padding: 8px 14px;
    border-radius: 8px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 0 1 auto;
}

.table-id-actions .btn-invite-share {
    background: linear-gradient(135deg, #10b981, #059669);
    color: #fff;
    border: none;
}

.btn-invite-share {
    transition: transform 0.15s ease, box-shadow 0.2s ease;
}

.btn-invite-share:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(16, 185, 129, 0.4);
}


/* --- 34. Error Screen + Connection Banner (v3.7.0) ---------------------------
   DELIBERATELY OUTSIDE the .screen / .modal-overlay system. See errorScreen.js
   for the full reasoning; the short version is that .modal-overlay supplies no
   display and no position (those come from .screen), and .screen is bulk-cleared
   by four unrelated files. This overlay owns its own layout and its own toggle
   so neither trapdoor applies. tools/check-error-modal.mjs enforces it. */
.ers-error-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: none;               /* .open flips this to flex */
    align-items: center;
    justify-content: center;
    padding: 1.2rem;
    background: rgba(2, 4, 10, 0.72);
    backdrop-filter: blur(18px) saturate(1.25);
    -webkit-backdrop-filter: blur(18px) saturate(1.25);
    z-index: 10001;              /* ABOVE #loading-overlay (9999): the error
                                    screen must be able to rescue a stuck spinner */
}

.ers-error-overlay.open {
    display: flex;
}

.ers-error-card {
    background: linear-gradient(145deg, rgba(15, 20, 30, 0.95), rgba(10, 14, 22, 0.97));
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 20px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    padding: 2rem 1.8rem 1.6rem;
    width: 100%;
    max-width: 420px;
    text-align: center;
    color: #fff;
    /* No opacity/transform animation here on purpose. The invite modal shipped
       invisible for two versions because its reveal rule was scoped to another
       modal's id. This card is opaque the moment it is displayed. */
}

.ers-error-icon {
    width: 54px;
    height: 54px;
    margin: 0 auto 1rem;
    color: var(--error, #ef4444);
}

.ers-error-icon svg {
    width: 100%;
    height: 100%;
}

.ers-error-title {
    font-family: 'Outfit', sans-serif;
    font-size: 1.35rem;
    font-weight: 800;
    margin: 0 0 0.6rem;
    line-height: 1.25;
}

.ers-error-reason {
    font-size: 1rem;
    line-height: 1.5;
    margin: 0 0 1.1rem;
    color: rgba(255, 255, 255, 0.82);
}

.ers-error-tech {
    text-align: left;
    margin: 0 0 1.2rem;
    font-size: 0.82rem;
    color: rgba(255, 255, 255, 0.5);
}

.ers-error-tech > summary {
    cursor: pointer;
    user-select: none;
    padding: 4px 0;
}

.ers-error-tech-body {
    display: block;
    margin-top: 6px;
    padding: 8px 10px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.05);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.76rem;
    word-break: break-word;
    color: rgba(255, 255, 255, 0.62);
}

.ers-error-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

.ers-error-actions .btn {
    flex: 1 1 140px;
    min-width: 130px;
    padding: 12px 16px;
    font-size: 0.95rem;
}

/* Connection banner: non-blocking, because a dropped connection during play
   must be reported without taking the board away from the player. Body-level
   for the same reason as #notifications — mounting it inside #game-container
   would make it invisible everywhere else. */
#connection-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    display: none;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 14px;
    background: linear-gradient(90deg, rgba(180, 40, 40, 0.96), rgba(140, 28, 28, 0.96));
    color: #fff;
    font-size: 0.92rem;
    font-weight: 700;
    letter-spacing: 0.3px;
    text-align: center;
    z-index: 10002;              /* above the error screen: connectivity is
                                    context for whatever else is on screen */
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

#connection-banner.open {
    display: flex;
}

/* v3.24.0 — the admin's announcement and the suspension notice. Inside
   #main-menu only (a .screen is position: absolute, so this column is the
   containing block), floated over the artwork so the menu layout does not
   move. Never shown over a match. */
#main-menu .menu-notices {
    position: absolute;
    top: max(10px, env(safe-area-inset-top));
    left: 50%;
    transform: translateX(-50%);
    width: min(94%, 560px);
    display: grid;
    gap: 8px;
    z-index: 6;
    pointer-events: none;
}
#main-menu .site-notice,
#main-menu .ban-notice {
    pointer-events: auto;
    margin: 0;
    padding: 10px 14px;
    border-radius: 12px;
    font-size: 0.92rem;
    line-height: 1.4;
    color: #fff;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
    overflow-wrap: anywhere;
}
#main-menu .site-notice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: rgba(20, 28, 48, 0.94);
    border: 1px solid rgba(212, 175, 55, 0.7);
}
#main-menu .site-notice[data-level="warn"] {
    background: rgba(70, 44, 8, 0.95);
    border-color: #f0b429;
}
#main-menu .site-notice[hidden],
#main-menu .ban-notice[hidden] { display: none; }
#main-menu #site-notice-text { flex: 1 1 auto; }
#main-menu .site-notice-close {
    flex: 0 0 auto;
    min-height: 32px;
    padding: 4px 10px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: transparent;
    color: #fff;
    font: inherit;
    font-size: 0.82rem;
    cursor: pointer;
}
#main-menu .site-notice-close:focus-visible { outline: 2px solid #d4af37; outline-offset: 2px; }
#main-menu .ban-notice {
    background: rgba(90, 16, 16, 0.95);
    border: 1px solid #ff7b72;
}

#connection-banner .cb-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #fff;
    animation: cbPulse 1.1s ease-in-out infinite;
    flex: 0 0 auto;
}

@keyframes cbPulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}

/* Pre-boot failure notice. Lives in index.html as static markup and is revealed
   by an inline script, so it works even when the module graph never evaluates. */
#boot-error {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 2rem 1.4rem;
    background: #0b0f18;
    color: #fff;
    font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
    text-align: center;
    z-index: 10003;
}


/* --- v3.9.0: assistive-only heading ---------------------------------------
   The lobby had no heading element at all, which is a real gap for screen
   readers and for search. The title itself is painted into assets/menu.jpg
   (and the four themed variants), so a VISIBLE h1 would duplicate it — that
   duplication is what v3.8.0 shipped and what the screen was judged worst for.
   This is the standard clip-path recipe: read aloud, never drawn, and it stays
   focusable-safe because nothing here is interactive. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --- v3.9.0: focus rings --------------------------------------------------
   Kept from v3.8.0. Keyboard users could not see where they were before it. */
.btn:focus-visible,
.link-btn:focus-visible,
.ui-input:focus-visible {
    outline: 3px solid var(--primary);
    outline-offset: 4px;
}


/* --- v3.9.0: the name field must clear the painted logo -------------------
   The v3.7.x lobby pushed its interface down with a bare `flex: 1` spacer, and
   at common desktop ratios that put "ENTER YOUR NAME" and its input directly
   across the wordmark's second line — "THE ULTIMATE CARD BATTLE" reads through
   the input box. It is the one thing every review of this screen agreed on.

   The layout is otherwise unchanged: same spacers, same centring, same order.
   The top one simply claims more of the free space, with a floor in `vh` so it
   still clears the artwork on very wide viewports and a cap so short laptops
   do not push the buttons off the bottom. Verified by rendering at 1440x900
   and 390x844. */
.lobby-spacer-top { flex: 1 1 auto; height: clamp(96px, 26vh, 260px); min-height: 0; }
.lobby-spacer-bottom { flex: 0.5 1 auto; }

@media (max-height: 760px) {
    .lobby-spacer-top { height: clamp(40px, 12vh, 110px); min-height: 0; }
}
@media (max-width: 768px) {
    .lobby-spacer-top { height: clamp(56px, 16vh, 150px); min-height: 0; }
}


/* --- v3.9.0: phones need a floor of contrast ------------------------------
   Desktop gets its depth from #parallax-scene and from body.menu-screen::before.
   Phones get neither: the parallax layer is `display: none` below 769px, so the
   artwork is the body's own background and white interface text lands directly
   on lit sand. Legible in a screenshot only if you already know what it says.

   This scrim rides INSIDE #main-menu at z-index -1 — with the interface, never
   over a separate artwork layer — so it cannot repeat v3.8.0's mistake of
   flattening the five themed backgrounds. Bottom-weighted: the painting keeps
   the top of the screen, the buttons get a readable ground under them. */
@media (max-width: 768px) {
    #main-menu { position: relative; }
    #main-menu::before {
        content: '';
        position: absolute;
        inset: 0;
        z-index: -1;
        pointer-events: none;
        background: linear-gradient(180deg,
            rgba(6, 10, 17, .30) 0%,
            rgba(6, 10, 17, .58) 26%,
            rgba(6, 10, 17, .74) 62%,
            rgba(6, 10, 17, .84) 100%);
    }
    /* Clear the artwork's own lettering before the first label. */
    .lobby-spacer-top { height: clamp(150px, 33vh, 300px); min-height: 0; }
}


/* --- v3.9.0: motion is opt-out ---------------------------------------------
   v3.8.0 introduced this guard and it was the release's clearest accessibility
   win. It lived in lobby.css, so removing that file would have quietly taken it
   with it — the parallax scene, the card animations and the screen transitions
   would all have come back for people who ask their system for less motion.
   Kept here, where it applies to the whole app rather than one screen.

   Not `* { animation: none }`: transitions that only change colour are
   harmless and keep the interface feeling responsive. What goes is movement —
   transforms, the parallax scene, and the ambient loops. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    #parallax-scene,
    #parallax-glow {
        display: none !important;
    }

    .screen {
        transform: none !important;
    }
}


/* --- v3.9.0: the lobby must be reachable on a short phone -----------------
   `.screen` is `position: absolute; inset: 0` with no overflow rule, so on a
   viewport shorter than the content the bottom of the menu is CLIPPED, not
   scrollable — on a small phone the Settings button simply cannot be reached.
   v3.8.0 fixed this with `overflow-y: auto` in lobby.css; that fix left with
   the file and is restored here.

   The padding is the second half of the same problem: `#game-version` is
   `position: absolute; bottom: 10px`, so it sits OUTSIDE the flow and the last
   button lands on top of it. Reserving its height is what stops "Settings"
   from printing over "Berk Elmalı · v3.9.0". Verified by rendering at
   390x844. */
#main-menu {
    overflow-y: auto;
    overscroll-behavior: contain;
    /* v3.10.0 — the footer's own strip, reserved so the last button row can
       never reach it. #game-version is absolutely positioned at the bottom
       right of THIS 600px column, so at 1366x768 it landed inside the Settings
       button (measured: button 736-776, footer 743-758) and its About and
       Privacy links are pointer-events: auto — a click aimed at Settings could
       open About. 15px label + its 10px offset + air.
       This must stay ABOVE the max-width:768px block below, which raises the
       same property for the safe-area inset; equal specificity, so source
       order is the whole argument. */
    padding-bottom: 44px;
}

@media (max-width: 768px) {
    #main-menu { padding-bottom: calc(58px + env(safe-area-inset-bottom)); }
    #game-version {
        left: 0;
        right: 0;
        text-align: center;
        bottom: calc(8px + env(safe-area-inset-bottom));
    }
    .lobby-spacer-top { height: clamp(120px, 26vh, 240px); min-height: 0; }
}


/* ═════════════════════════════════════════════════════════════════════════
   v3.10.0 — THE PLAYER CARD
   ═════════════════════════════════════════════════════════════════════════
   The account panel's logged-in view shipped in v3.8.0 as markup with NO
   STYLESHEET AT ALL. Seven classes — .profile-identity, .profile-emblem,
   .profile-eyebrow, .profile-stats, .profile-stat, .profile-intro,
   .profile-history-note — were named in index.html and defined nowhere, so
   the browser drew them as bare inline text: the ♠ avatar was a 12px glyph,
   and every statistic ran its label into its value ("Skor1", "Oynanan maç0").
   The win-rate line was clipped by the card beneath it.

   This is the mirror image of the defect `check-lobby` was written for.
   That gate catches CSS that names nothing; nothing caught markup that names
   no CSS. `tools/check-orphan-classes.mjs` now closes that direction, and it
   is what keeps this file honest from here on.

   ── Why gold, and why only gold ──────────────────────────────────────────
   Surfaces come from the theme (`--panel-bg`, `--panel-border`,
   `--panel-glow`), so the card is blue in the blue theme and red in the red
   one, like every other panel. The ACCENT is gold in all five, on purpose:
   gold is the game's identity, not a theme's. Note that `--primary` is
   defined once at :root and no theme overrides it — so a `var(--primary)`
   accent here would have been the same blue everywhere, which is exactly
   the flatness this card exists to avoid.
   ═════════════════════════════════════════════════════════════════════════ */

:root {
    --gold-bright: #ffd700;
    --gold:        #f59e0b;
    --gold-deep:   #b45309;
}

/* The logged-in card carries a 2x2 stat grid; 400px squeezes it to one
   column on desktop for no reason. The sign-in form keeps the old width. */
#account-logged-in.account-section {
    max-width: 460px;
    padding: 1.6rem 1.4rem;
}

/* --- The banner: avatar, who you are, and the card's gold edge ----------- */
.profile-identity {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 1rem;
    text-align: left;
    padding: 1rem 1.1rem;
    margin-bottom: 1rem;
    border-radius: 14px;
    border: 1px solid color-mix(in srgb, var(--gold) 26%, transparent);
    background:
        linear-gradient(135deg,
            color-mix(in srgb, var(--gold) 13%, transparent) 0%,
            transparent 58%),
        var(--panel-bg);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--gold-bright) 22%, transparent);
    transition: box-shadow 0.3s ease, border-color 0.3s ease;
}
.profile-identity:hover {
    border-color: color-mix(in srgb, var(--gold) 45%, transparent);
    box-shadow:
        inset 0 1px 0 color-mix(in srgb, var(--gold-bright) 30%, transparent),
        0 0 18px color-mix(in srgb, var(--gold) 18%, transparent);
}

/* The avatar. In the logged-OUT card the same class is a standalone crest
   above the intro line, so the block-level centring below is not optional. */
.profile-emblem {
    display: grid;
    place-items: center;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    font-size: 1.9rem;
    line-height: 1;
    color: var(--gold-bright);
    background:
        radial-gradient(circle at 32% 28%,
            color-mix(in srgb, var(--gold-bright) 34%, transparent) 0%,
            transparent 62%),
        linear-gradient(160deg, #2a2110 0%, #120d05 100%);
    border: 2px solid color-mix(in srgb, var(--gold) 55%, transparent);
    box-shadow:
        0 4px 14px rgba(0, 0, 0, 0.45),
        inset 0 0 12px color-mix(in srgb, var(--gold-deep) 45%, transparent);
    text-shadow: 0 0 12px color-mix(in srgb, var(--gold-bright) 60%, transparent);
}
/* Logged out: no grid parent to sit in, so it centres itself. */
.auth-card > .profile-emblem {
    margin: 0 auto 0.9rem;
}

.profile-identity-text { min-width: 0; }

.profile-eyebrow {
    margin: 0 0 0.15rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--gold);
}
.profile-identity h3 {
    margin: 0;
    font-size: 1.32rem;
    font-weight: 800;
    line-height: 1.15;
    overflow-wrap: anywhere;
}
.profile-identity p:not(.profile-eyebrow) {
    margin: 0.12rem 0 0;
    font-size: 0.78rem;
    opacity: 0.62;
    overflow-wrap: anywhere;
}

/* --- The statistics ------------------------------------------------------
   A grid, and each cell a COLUMN. That column is the whole fix for "Skor1":
   the label and the value were inline siblings with nothing between them. */
.profile-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    margin-bottom: 1rem;
}
.profile-stat {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    align-items: flex-start;
    padding: 0.7rem 0.8rem;
    border-radius: 11px;
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid var(--panel-border);
    border-left: 2px solid color-mix(in srgb, var(--gold) 55%, transparent);
}
.profile-stat span {
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.6;
    line-height: 1.2;
}
.profile-stat strong {
    font-size: 1.24rem;
    font-weight: 800;
    line-height: 1.1;
    color: var(--gold-bright);
    font-variant-numeric: tabular-nums;
}

/* --- Supporting copy ----------------------------------------------------- */
.profile-intro {
    margin-bottom: 1.2rem;
    font-size: 0.86rem;
    line-height: 1.5;
    opacity: 0.72;
}
.profile-history-note {
    margin: 0 0 0.7rem;
    font-size: 0.72rem;
    line-height: 1.45;
    opacity: 0.55;
}

/* --- The two panels under the banner -------------------------------------
   These were two hand-written inline `rgba(22,27,34,.45)` boxes: the same
   grey in all five themes, and 14 inline declarations between them. As
   classes they follow the theme like everything else on the screen. */
.profile-panel {
    text-align: left;
    padding: 0.95rem 1rem;
    margin-bottom: 1rem;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.035);
    border: 1px solid var(--panel-border);
}
.profile-panel--scroll {
    /* 250px was the inline value this class replaced, and at that height the
       panel headed "Last 5 Matches" showed one and a half of them — a nested
       scroller inside a panel that already scrolls. 420px holds the curve plus
       all five rows, and still bounds the panel on a long history. */
    max-height: 420px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.profile-panel-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin: 0 0 0.6rem;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--gold);
}
.profile-panel-title .profile-panel-meta {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.4);
    text-transform: uppercase;
}
.profile-graph {
    width: 100%;
    height: 100px;
    margin-bottom: 0.7rem;
    position: relative;
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.22);
    border: 1px solid rgba(255, 255, 255, 0.05);
    overflow: hidden;
}
.profile-match-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.profile-nemesis-body { font-size: 0.85rem; }
.profile-empty {
    margin: 0;
    padding: 0.6rem 0;
    text-align: center;
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.4);
}
.profile-graph .profile-empty { padding-top: 38px; }

/* --- One match in the history list --------------------------------------
   Built by profileUI.js, which used to write eleven inline declarations per
   card on every render. The win/loss hue is the only thing that still
   varies per row, so it is the only thing left to a modifier class. */
.profile-match {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 8px 10px;
    border-radius: 8px;
    font-size: 0.78rem;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--panel-border);
}
.profile-match--win {
    background: rgba(46, 204, 113, 0.12);
    border-color: rgba(46, 204, 113, 0.25);
}
.profile-match--loss {
    background: rgba(231, 76, 60, 0.12);
    border-color: rgba(231, 76, 60, 0.25);
}
.profile-match-result {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
}
.profile-match--win  .profile-match-result { color: #2ecc71; }
.profile-match--loss .profile-match-result { color: #e74c3c; }
.profile-match-mode {
    font-size: 0.65rem;
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.6);
}
.profile-match-vs {
    margin-top: 3px;
    max-width: 140px;
    font-size: 0.68rem;
    color: rgba(255, 255, 255, 0.4);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.profile-match-right { text-align: right; }
.profile-match-reflex {
    font-weight: 700;
    color: var(--gold-bright);
    font-variant-numeric: tabular-nums;
}
.profile-match-cards {
    margin-top: 3px;
    font-size: 0.68rem;
    color: rgba(255, 255, 255, 0.4);
}

/* Narrow phones: one stat per row beats two clipped ones. */
@media (max-width: 420px) {
    .profile-stats { grid-template-columns: minmax(0, 1fr); }
    .profile-identity { gap: 0.8rem; padding: 0.85rem 0.9rem; }
    .profile-emblem { width: 52px; height: 52px; font-size: 1.6rem; }
    .profile-identity h3 { font-size: 1.15rem; }
}

/* Bot rivalry rows — built by botNemesis.js. */
.profile-nemesis-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.6rem;
    padding: 4px 0;
}
.profile-nemesis-count {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.profile-nemesis-count.is-nemesis { color: #ef4444; }
.profile-nemesis-callout {
    margin: 0 0 8px;
    font-size: 0.8rem;
    color: #ef4444;
}


/* ═════════════════════════════════════════════════════════════════════════
   v3.10.0 — THREE MEASURED LOBBY DEFECTS
   ═════════════════════════════════════════════════════════════════════════
   All three were found by rendering the lobby at real viewport sizes and
   reading the geometry back, not by reading the CSS. Numbers below are from
   that run, on the blue theme, before these rules existed.

   1. THE WORDMARK WAS CROPPED. Every menu image is 1280x713 (aspect 1.795).
      A 1920x914 window is aspect 2.10, so `cover` scales by WIDTH: the image
      becomes 1920x1070 and 156px fall outside. `background-position: center`
      splits that loss between top and bottom — and the wordmark lives in the
      top third, so "EGYPTIAN" lost its top edge. Sliding the crop to 15%
      spends nearly all of the loss on the floor tiles at the bottom, which
      carry nothing. `center top` was tried first and clears the wordmark
      too, but it pushes the artwork's own subtitle a further 78px down into
      the name field; 15% was chosen by rendering all three and looking.
      On a portrait phone `cover` scales by HEIGHT instead, the
      vertical axis has no slack to slide, and this rule changes nothing —
      which is why it is safe to apply to both.

   2. THE FOOTER SAT ON THE SETTINGS BUTTON. `#game-version` is absolutely
      positioned at the bottom-right of #main-menu — a 600px column, so its
      corner is exactly where the last button row ends up. Measured at
      1366x768: Settings occupied 736-776 and the footer 743-758, i.e. fully
      INSIDE the button. The footer is `pointer-events: none`, but the About
      and Privacy links inside it are `pointer-events: auto` (v3.7.x fixed
      that on purpose), so on that very common laptop size a click aimed at
      Settings could open About instead. Reserving the footer's own strip at
      the bottom of the column is what stops the two from ever meeting.

   3. A PERMANENT SCROLLBAR BOUGHT BY 4 PIXELS. v3.9.0 gave #main-menu
      `overflow-y: auto` so that Settings stays reachable on short phones —
      a real fix. But the top spacer's `min-height` made the column
      unshrinkable, so at 1920x914 the content came to 918px: four pixels
      over, and a scrollbar drawn down the middle of the artwork for them.
      (1440x900 was 9px over; 390x844, 43px.) `min-height` is what blocks
      flex-shrink, so the floor moves to `height` and `min-height` goes to 0:
      the spacer still GROWS to hold the interface clear of the wordmark
      whenever there is room, and now yields instead of buying a scrollbar
      when there is not. Genuinely short screens still scroll — deliberately.
   ═════════════════════════════════════════════════════════════════════════ */

body.menu-screen { background-position: center 15% !important; }
body.menu-screen #parallax-bg { background-position: center 15%; }

/* Defect 3's fix is not here: it is on the five `.lobby-spacer-top` rules
   themselves, above. Shadowing them from 600 lines away would have left every
   one of those rules still saying `min-height`, which is the property that
   caused the bug — and the next reader would have found the wrong one first. */

/* The reflex trend curve, drawn as SVG by profileUI.js. A presentation
   attribute cannot read a CSS variable, so the SVG carries classes and the
   colour lives here — which is also what stops it being blue inside a gold
   card, as it was in every theme up to v3.9.0. */
.reflex-graph-stop-top    { stop-color: var(--gold-bright); stop-opacity: 0.28; }
.reflex-graph-stop-bottom { stop-color: var(--gold-bright); stop-opacity: 0; }
.reflex-graph-line {
    fill: none;
    stroke: var(--gold-bright);
    stroke-width: 2;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--gold) 55%, transparent));
}
.reflex-graph-dot {
    fill: var(--gold-bright);
    stroke: #fff;
    stroke-width: 1;
}
.reflex-graph-label {
    fill: rgba(255, 255, 255, 0.85);
    font-size: 6.5px;
    font-weight: 700;
    font-family: sans-serif;
}


/* ═════════════════════════════════════════════════════════════════════════
   v3.10.1 — the footer, once the lobby actually scrolls
   ═════════════════════════════════════════════════════════════════════════
   v3.10.0 gave #main-menu a 44px bottom reserve so the last button row could
   never reach #game-version, and at 1920x914 and 1366x768 that holds: 37px
   clear, measured on the live site. Below roughly 660px of viewport height it
   stops holding, and the reason is structural rather than a matter of degree.

   `#game-version` is `position: absolute; bottom: 10px`, so it is pinned to
   #main-menu's PADDING BOX — a fixed 640px-tall box. The buttons are in
   normal flow, and once the content outgrows that box they keep going into
   the scrollable overflow. Padding at the end of the CONTENT cannot separate
   two things when only one of them is in the content. Measured on the live
   site at 1366x640: Settings 574-615, footer 613-630 — two pixels of overlap,
   growing to 40 by 560px tall.

   So at the heights where the menu genuinely scrolls, the footer stops being
   pinned and joins the flow: it lands after the last button plus its own
   margin, and is reached by scrolling like everything else. The breakpoint is
   the one that already exists, and it is comfortably above where overflow
   begins (~677px of content), so the two can never disagree.
   ═════════════════════════════════════════════════════════════════════════ */

@media (max-height: 760px) {
    /* Beats both the base rule and the max-width:768px mobile rule: same
       specificity as the latter would give, plus the #main-menu ancestor. */
    #main-menu #game-version {
        position: static;
        left: auto;
        right: auto;
        bottom: auto;
        /* 12px, not 20 (v3.27.1): with the Guides link the line can wrap in
           German and Russian, and at 360x740 — the menu already at its
           tightest, top spacer at 0px — the second line ended 4px below the
           screen. 12px keeps both lines on it, and lifts the 375x667 English
           line (5px under) back on screen too. Measured, both. */
        margin: 12px auto 0;
        text-align: center;
    }
    /* The reserve was for a pinned footer. In the flow it needs none — but
       the safe-area inset must survive, because this block sits after the
       max-width:768px rule that carries it and beats it on specificity.
       A short phone (an iPhone in landscape, say) matches BOTH queries. */
    #main-menu { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
}


/* ═════════════════════════════════════════════════════════════════════════
   v3.12.0 — THE SIGN-IN CARD
   ═════════════════════════════════════════════════════════════════════════
   Three defects, one shape.

   1. TWO CARDS. `#account-logged-out` is `.account-section` — a glass panel
      with its own background, border, 16px radius and 2rem of padding — and
      inside it sat `.auth-card`, a SECOND glass panel with its own
      background, border, 18px radius and 2rem more padding. The user saw a
      card inside a card: two borders, two blurs, and roughly 70px of dead
      margin between the outer edge and the first field. `.auth-card` keeps
      its name (JS and the emblem rule reference it) and gives up its skin.
      It is now purely the form's layout: a flex column with one gap.

   2. THE MODE LIVED IN SIX PLACES. Sign-in and register were switched by
      writing `style.display` onto four buttons and a field group from three
      different functions, so the two modes could — and did — disagree. The
      mode is now ONE attribute, `data-mode` on `#auth-form`, and every
      appearance below is derived from it. Inline `display` juggling is gone,
      which is also what makes a transition possible at all: an element the
      JS is not touching can be animated by CSS.

   3. GOLD, LIKE THE PLAYER CARD. The logged-IN half became gold in v3.10.0
      and the logged-OUT half stayed the old blue-on-grey, so the same screen
      changed identity when you signed in. Labels, icons, links and the focus
      ring now speak the same language as the card they lead to.
   ═════════════════════════════════════════════════════════════════════════ */

#account-logged-out.account-section {
    padding: 1.8rem 1.5rem;
}

/* Was a panel; is now a layout. Every property here undoes one that the
   v2.9.0 `.auth-card` rule sets — this block sits later in the file at equal
   specificity, so it wins without `!important`. */
.auth-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.85rem;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.auth-card > .profile-emblem {
    margin: 0 auto;
}

/* --- The fields ----------------------------------------------------------
   `.setting-group` is the settings-screen row: centred, 300px wide, 1.5rem
   of bottom margin and a hover border. In a form that is three kinds of
   wrong at once, so the shared class supplies only its flex column. */
.auth-field {
    max-width: none;
    margin-bottom: 0;
    padding: 0;
    gap: 0.3rem;
    align-items: stretch;
    text-align: left;
    border-color: transparent;
}
.auth-field:hover {
    border-color: transparent;
    box-shadow: none;
    background: none;
}
/* Deliberately almost empty. The first cut of this card gave the labels a
   0.68rem gold uppercase treatment of their own, and the result read as a
   different product from the settings panel, the lobby and every popup in
   the app — which all use `.setting-group label` exactly as it comes. So it
   comes as it is: same size, same colour, same casing. Only the margin goes,
   because the flex `gap` above already spaces the rows. */
.auth-field label {
    margin-bottom: 0;
}

/* The field itself keeps the app's input entirely — its background, border,
   and its theme-coloured focus glow. Only the box is tightened, because
   three stacked 1.3rem fields made the card taller than the screen it opens
   on. Nothing here touches colour. */
.auth-card .auth-input-icon {
    left: 15px;
}
.auth-card .auth-input.crisp-dark {
    font-size: 1.1rem;
    padding: 12px 16px 12px 46px;
}

/* --- The one line that talks back ---------------------------------------
   Validation refusals, Firebase errors and the reset-link confirmation all
   land here. It holds its height whether or not it has something to say, so
   the button underneath never jumps. */
.auth-message {
    margin-top: 0;
    min-height: 1.15rem;
    font-size: 0.82rem;
    line-height: 1.4;
    text-align: left;
}
/* The app's own success colour, the one the accent token exists for. */
.auth-message.is-success {
    color: var(--accent);
}

.auth-submit {
    width: 100%;
    margin-top: 0.1rem;
}
.auth-submit:disabled {
    opacity: 0.55;
    cursor: progress;
    filter: saturate(0.6);
}
.auth-submit:disabled:hover {
    transform: none;
}

/* --- Secondary actions ---------------------------------------------------
   "Register" used to be a full-width button identical in weight to "Sign
   In", so the card offered two equal primary actions and neither read as the
   one you came for. It is a link now; the button is the only button. */
.auth-switch {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.3rem;
}
.auth-switch-line {
    margin: 0;
    font-size: 0.82rem;
    opacity: 0.72;
}
.auth-link {
    background: none;
    border: 0;
    padding: 0;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--primary);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: color-mix(in srgb, var(--primary) 45%, transparent);
    transition: color 0.2s ease, text-decoration-color 0.2s ease;
}
.auth-link:hover {
    color: var(--text-color);
    text-decoration-color: currentColor;
}
.auth-link:disabled {
    opacity: 0.5;
    cursor: default;
    text-decoration: none;
}

/* --- The mode, derived rather than written -------------------------------
   Two id selectors, so the username group's `display: none` beats
   `.setting-group { display: flex }` in sign-in mode — and in register mode
   NOTHING hides it, so the class supplies the flex again by itself. No
   element carries an inline `display` any more, which is precisely why the
   appearance below can be animated. */
#auth-form[data-mode="signin"]   .auth-mode-register  { display: none; }
#auth-form[data-mode="register"] .auth-mode-signin    { display: none; }
#auth-form[data-mode="signin"]   #auth-username-group { display: none; }

#auth-form[data-mode="register"] #auth-username-group {
    animation: authFieldIn 0.28s cubic-bezier(0.25, 1, 0.5, 1);
}
@keyframes authFieldIn {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    #auth-form[data-mode="register"] #auth-username-group { animation: none; }
}

/* --- Busy -----------------------------------------------------------------
   A second tap while the first request is in flight creates a second account,
   or burns a second reset email. The lock is `data-busy` on the same form
   element that carries the mode, so both states are read from one place —
   and the label is swapped by CSS rather than by writing text into a button
   whose own translation would overwrite it on the next language change. */
.auth-submit .auth-mode-busy { display: none; }
#auth-form[data-busy="1"] .auth-submit .auth-mode-busy    { display: inline; }
#auth-form[data-busy="1"] .auth-submit .auth-mode-signin,
#auth-form[data-busy="1"] .auth-submit .auth-mode-register { display: none; }

/* --- Focus, visibly ------------------------------------------------------
   `.auth-link` is a <button> that is neither `.btn` nor `.link-btn`, so the
   v3.9.0 focus-ring rule did not reach it: the reset and mode-switch controls
   were invisible to a keyboard. Same ring, same token as everywhere else. */
.auth-link:focus-visible {
    outline: 3px solid var(--primary);
    outline-offset: 4px;
}


/* ═════════════════════════════════════════════════════════════════════════
   v3.13.0 — RA'S WHEEL, THE ARCADE BUTTONS, AND TWO RULES THE SOURCE
   NEVER WROTE
   ═════════════════════════════════════════════════════════════════════════
   Ported from ers-revamp. The wheel, the tier ladder and the chunky menu
   buttons are that branch's work and arrive largely unchanged. Three things
   did not come across as they were:

   1. `.vibrant-play { animation: vibrantGlow ... }` is NOT here. This
      stylesheet already styles `.btn.vibrant-play`, and `check-lobby` pins
      that button's glow as a rule. A second, lower-specificity opinion on
      the same button is how two stylesheets start disagreeing.

   2. `@keyframes spinBadgePulse` and `tierUpPulse` came WITH the rules that
      name them. An `animation:` pointing at keyframes that do not exist is
      the same defect as a class that styles nothing — silent, and invisible
      in the source forever.

   3. `.photo-finish-banner` and `.on-fire` had NO rule at all in the branch
      they came from. `ui.js` there sets `display:block` on the banner and
      adds `.on-fire` at a three-slap streak, and neither had a single
      declaration anywhere — except, remarkably, a `@media
      (prefers-reduced-motion)` block switching OFF an animation `.on-fire`
      never had. `check-orphan-classes` would have refused the build over
      the banner. Both are written below, properly.
   ═════════════════════════════════════════════════════════════════════════ */

.player-banner-group {
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: 100;
}
.coin-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 36px;
    padding: 8px 14px;
    box-sizing: border-box;
    border-radius: 20px;
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid rgba(255, 215, 0, 0.4);
    color: gold;
    font-weight: bold;
    font-size: 0.95rem;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 0 10px rgba(255, 215, 0, 0.2);
}
.spin-trigger-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 8px 14px;
    box-sizing: border-box;
    border-radius: 20px;
    background: rgba(22, 27, 34, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-color);
    font-family: inherit;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    position: relative;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.spin-trigger-btn:hover {
    border-color: rgba(255, 215, 0, 0.45);
    box-shadow: 0 0 12px rgba(255, 215, 0, 0.18);
}
.spin-icon {
    font-size: 1rem;
    filter: drop-shadow(0 0 4px rgba(245, 158, 11, 0.4));
}
.spin-text {
    font-weight: 700;
    letter-spacing: 0.5px;
}
.spin-badge {
    background: #ef4444;
    color: #fff;
    border-radius: 50%;
    font-size: 0.7rem;
    font-weight: 900;
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 2px;
    box-shadow: 0 0 8px #ef4444;
    animation: spinBadgePulse 1.5s infinite;
}










.spin-modal-backdrop {
    position: fixed;
    inset: 0;
    max-width: 100vw;
    padding: 12px;
    box-sizing: border-box;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    justify-content: center;
    align-items: center;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 10000;
}
.spin-modal-card {
    position: relative;
    width: 94%;
    max-width: min(420px, calc(100vw - 24px));
    box-sizing: border-box;
    padding: 1.6rem 1.4rem 1rem;
    text-align: center;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 16px;
    box-shadow: 0 16px 40px var(--panel-shadow), 0 0 20px var(--panel-glow);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    animation: modalFadeIn 0.25s ease-out;
}
.spin-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
}
.spin-title {
    font-size: 1.4rem;
    font-weight: 900;
    color: #fde68a;
    text-shadow: 0 0 12px rgba(245, 158, 11, 0.4);
    margin-bottom: 4px;
}
.spin-desc {
    font-size: 0.85rem;
    color: #d1d5db;
    margin-bottom: 10px;
    line-height: 1.4;
}
.spin-tier-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.tier-dot {
    font-size: 0.78rem;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    background: rgba(255, 255, 255, 0.05);
    color: rgba(255, 255, 255, 0.4);
    transition: all 0.4s ease;
    letter-spacing: 0.5px;
}
.tier-dot.active {
    transform: scale(1.1);
}
.tier-dot.completed {
    opacity: 0.5;
    text-decoration: line-through;
}
.tier-dot.tier-bronze.active {
    background: rgba(205, 127, 50, 0.2);
    border-color: #cd7f32;
    color: #cd7f32;
    box-shadow: 0 0 12px rgba(205, 127, 50, 0.3);
}
.tier-dot.tier-silver.active {
    background: rgba(192, 192, 192, 0.2);
    border-color: #c0c0c0;
    color: #c0c0c0;
    box-shadow: 0 0 12px rgba(192, 192, 192, 0.3);
}
.tier-dot.tier-gold.active {
    background: rgba(255, 215, 0, 0.2);
    border-color: #ffd700;
    color: #ffd700;
    box-shadow: 0 0 12px rgba(255, 215, 0, 0.3);
}
.tier-arrow {
    color: rgba(255, 255, 255, 0.25);
    font-size: 0.8rem;
}
.wheel-outer-wrapper {
    position: relative;
    margin: 0 auto 12px;
}
.wheel-outer-lg {
    width: 340px;
    height: 340px;
}
.wheel-pointer {
    position: absolute;
    top: -12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    line-height: 0;
    /* v3.17.0: a bronze pawl on a rivet. It hinges at the rivet, so a flick
       swings the TIP, the way a pawl riding over a peg does. */
    transform-origin: 50% 7px;
    transition: transform 70ms ease-out;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.7));
}
.wheel-pawl {
    display: block;
}
.wheel-pointer.is-ticking {
    transform: translateX(-50%) rotate(var(--tick-deg, -14deg));
}
@media (prefers-reduced-motion: reduce) {
    .wheel-pointer { transition: none; }
}
body.reduced-motion .wheel-pointer {
    transition: none;
}
.daily-spin-status {
    font-size: 0.95rem;
    font-weight: 700;
    min-height: 26px;
    margin-bottom: 8px;
    color: #ffd700;
    transition: color 0.3s;
}
.daily-spin-countdown {
    font-size: 0.88rem;
    color: #fbbf24;
    margin-bottom: 12px;
    font-weight: 700;
    letter-spacing: 0.5px;
    background: rgba(251, 191, 36, 0.1);
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(251, 191, 36, 0.25);
    display: inline-block;
}
.spin-action-btn {
    width: 100%;
    padding: 12px;
    font-size: 1.05rem;
    border-radius: 12px;
    cursor: pointer;
    touch-action: manipulation;
}
.spin-btn-spinning {
    opacity: 0.85;
    cursor: wait !important;
}
.spin-tier-up-btn {
    animation: tierUpPulse 0.8s ease-in-out infinite alternate;
}
.spin-claimed-btn {
    background: rgba(255, 255, 255, 0.12) !important;
    border: 1px solid rgba(255, 255, 255, 0.25) !important;
    color: #e5e7eb !important;
    font-size: 1rem;
}
.spin-claimed-btn:hover {
    background: rgba(255, 255, 255, 0.2) !important;
    color: #ffffff !important;
    transform: translateY(-2px);
}
.spin-footer-close {
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.85rem;
    margin-top: 10px;
    cursor: pointer;
    padding: 6px 14px;
    border-radius: 6px;
    transition: color 0.2s, background 0.2s;
    display: inline-block;
}
.spin-footer-close:hover {
    color: #ffffff;
    background: rgba(255, 255, 255, 0.1);
}
.modal-close-btn {
    position: absolute;
    top: 12px;
    right: 14px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 215, 0, 0.3);
    border-radius: 50%;
    color: #ffd700;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    transition: all 0.2s ease;
    z-index: 20;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    touch-action: manipulation;
}
.modal-close-btn:hover {
    color: #ffffff;
    background: rgba(255, 215, 0, 0.25);
    border-color: #ffd700;
    transform: scale(1.08);
}
.modal-close-btn:active {
    transform: scale(0.95);
}
@keyframes spinBadgePulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.25); }
}
@keyframes tierUpPulse {
    0%  { box-shadow: 0 6px 0 #064e3b, 0 10px 25px rgba(16, 185, 129, 0.45); }
    100% { box-shadow: 0 6px 0 #064e3b, 0 10px 35px rgba(16, 185, 129, 0.8), 0 0 50px rgba(16, 185, 129, 0.3); }
}

/* --- The tier labels ------------------------------------------------------
   Their own element so `Localization.apply()` can rewrite the word without
   touching the medal glyph beside it, and so the JS can refresh them on a
   language change without rebuilding the dot. */
.tier-dot-label { font: inherit; }

/* --- Photo finish ---------------------------------------------------------
   Two slaps landed within milliseconds of each other; this says who took the
   pile and by how much. It sits above the screen layer like every other
   overlay, and it retires ITSELF after 2.4s — the v3.12.0 winner banner is
   the cautionary tale, and the smoke gate that caught that one covers this
   element too, by construction. */
.photo-finish-banner {
    position: fixed;
    top: 24%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.86);
    z-index: 9997;
    display: none;
    max-width: min(90vw, 460px);
    padding: 0.6rem 1.4rem;
    border-radius: 999px;
    background: linear-gradient(135deg, rgba(22, 27, 34, 0.94), rgba(12, 16, 22, 0.94));
    border: 1px solid color-mix(in srgb, var(--primary) 55%, transparent);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.55), 0 0 26px color-mix(in srgb, var(--primary) 28%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: var(--text-color);
    font-size: 0.98rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.22s ease-out, transform 0.22s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.photo-finish-banner.active {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.photo-finish-banner strong { color: var(--primary); }

/* --- On fire --------------------------------------------------------------
   Three slaps in a row. `.combustion-glow` already marks two; this is the
   step above it, and it has to read as MORE, not as different — same hue
   family, more of it, plus movement. */
.deck.on-fire {
    border-color: #f59e0b;
    box-shadow:
        0 0 18px rgba(245, 158, 11, 0.75),
        0 0 42px rgba(245, 158, 11, 0.4),
        inset 0 0 16px rgba(245, 158, 11, 0.28);
    animation: onFirePulse 1.1s ease-in-out infinite alternate;
}
@keyframes onFirePulse {
    from {
        box-shadow:
            0 0 18px rgba(245, 158, 11, 0.75),
            0 0 42px rgba(245, 158, 11, 0.4),
            inset 0 0 16px rgba(245, 158, 11, 0.28);
    }
    to {
        box-shadow:
            0 0 26px rgba(255, 215, 0, 0.95),
            0 0 60px rgba(245, 158, 11, 0.6),
            inset 0 0 22px rgba(255, 215, 0, 0.4);
    }
}
@media (prefers-reduced-motion: reduce) {
    .deck.on-fire { animation: none; }
    .photo-finish-banner { transition: opacity 0.22s ease-out; }
    .photo-finish-banner.active { transform: translate(-50%, -50%) scale(1); }
}

/* --- The wheel has to fit the phone it is drawn on ------------------------
   Ported as `width: 340px; height: 340px`, with a canvas carrying
   `width="340"` as an attribute. Measured: open the wheel on a desktop
   window and then narrow it, and the page gains 4px of horizontal scroll
   that survives closing the modal — the card is `width: 94%`, so below
   ~362px it is NARROWER THAN ITS OWN WHEEL, and a fixed-position overlay
   whose content sticks out still lengthens the document.

   The canvas keeps its 340x340 backing store — that is the drawing
   resolution and the wheel is rendered at it — while CSS scales the
   ELEMENT down to whatever the card can give it. `aspect-ratio` keeps it
   round without a second magic number to drift out of step. */
.wheel-outer-lg {
    width: min(340px, 74vw);
    height: auto;
    aspect-ratio: 1 / 1;
}
.wheel-outer-wrapper canvas {
    display: block;
    width: 100%;
    height: 100%;
}
/* Belt and braces: an overlay may never be the reason the PAGE scrolls
   sideways, whatever its contents decide to be. */
.spin-modal-backdrop {
    max-width: 100vw;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 12px;
    box-sizing: border-box;
}
.spin-modal-card {
    max-width: min(420px, calc(100vw - 24px));
    box-sizing: border-box;
}

/* --- The page never scrolls sideways, at either level ---------------------
   `body` has carried `overflow-x: hidden` for a long time: this app is a
   single column and a horizontal scrollbar is always a bug. `html` was
   simply the half nobody set, and the gap is reachable — narrow a DESKTOP
   window to phone width while an overlay is open and the document keeps 4px
   of horizontal scroll afterwards, from a layout pass that body's own clip
   cannot reach.

   Measured honestly, so the comment does not overclaim: loading at 414px or
   360px produces 0px of overflow with or without this rule, and so does
   opening the wheel AT those widths — the only path that reproduces it is
   resizing down from a wide window, which is a desktop gesture, not a phone
   one. `clip` rather than `hidden` on purpose: `hidden` would make <html> a
   scroll container and change how `position: fixed` resolves.

   COUNTED, not remembered — the first draft of this comment stated a number
   from memory, in a file this project audits mechanically, and the number
   was wrong. There are NINE body-level overlays at runtime. Eight are static
   in index.html; #error-modal is the ninth and errorScreen.js creates it,
   which is why counting the markup alone gives eight. Seven resolve to
   `fixed` (#notifications, #photo-finish-banner, #loading-overlay,
   #connection-banner, #daily-spin-modal, #error-modal, #boot-error). Two are
   `absolute` (#confirm-modal, #invite-modal) — measured in the browser, not
   inferred from the stylesheet. */
html { overflow-x: clip; }








/* --- The corner is a ROW now, so its first item has to join it ------------
   `.profile-btn` is `position: absolute` with its own top/left, because for
   most of this app's life it WAS the corner. Now it is the first of three
   items in `.player-banner-group`, and an absolutely positioned flex child
   is not a flex item at all — it stayed pinned to 20/20 and the coin badge
   and spin trigger were drawn straight over it. Measured on the menu at
   1280x900 before this rule: the avatar sat underneath both of them.

   The safe-area inset it used to carry moves to the group, in index.html,
   so a notched phone loses nothing in the handover. */
.player-banner-group > .profile-btn {
    position: static;
    top: auto;
    left: auto;
    flex: 0 0 auto;
}
.player-banner-group { flex-wrap: wrap; max-width: calc(100vw - 30px); }

/* On a narrow phone the corner has to give something up, and the word is
   the cheapest thing to lose: the sun glyph and the red dot still say
   "there is a spin waiting". */
@media (max-width: 480px) {
    .spin-trigger-btn .spin-text { display: none; }
    .spin-trigger-btn { padding: 6px 10px; }
    .coin-badge { font-size: 0.85rem; padding: 6px 10px; }
}

/* --- Legends hub & the Table of the Gods (v3.18.0) -------------------------
   The hall and the HUD sit on the shared panel surface; the gods' portraits
   are world objects (DESIGN.md §4) and carry the theme's colour themselves. */
.legend-section {
    width: 100%;
    max-width: 900px;
    margin: 0 auto 1.5rem;
    padding: 1rem;
    border-radius: 18px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.18);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
/* ERS-18 fix 4: a section heading is a panel heading (.rules-content h3),
   not a world object — gold stays on the god and journey cards. */
.legend-title {
    font-size: 1.3rem;
    color: var(--primary);
    margin: 0.25rem 0 0.6rem;
}
.legend-section .mode-cards {
    margin: 0;
    max-width: none;
}
.legend-desc {
    opacity: 0.8;
    max-width: 62ch;
    margin: 0 auto 1rem;
    line-height: 1.5;
}
.pantheon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
}
.god-card {
    position: relative;
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 12px;
    align-items: start;
    text-align: left;
    padding: 12px;
    border-radius: 16px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.22);
}
.god-card.beaten { border-color: rgba(212, 175, 55, 0.7); }
.god-card.locked .god-portrait { filter: grayscale(0.9) brightness(0.6); }
.god-card.locked .god-body { opacity: 0.65; }
.god-portrait { width: 96px; height: 96px; }
.god-art { width: 100%; height: 100%; display: block; }
.god-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.god-name { margin: 0; font-size: 1.1rem; color: #f0d98a; }
.god-epithet { margin: 0; font-size: 0.8rem; font-style: italic; opacity: 0.7; }
.god-power { margin: 2px 0 0; font-size: 0.85rem; line-height: 1.4; }
.god-meta { margin: 0; font-size: 0.75rem; opacity: 0.6; font-variant-numeric: tabular-nums; }
.god-body .btn { margin-top: 6px; padding: 0.5rem 0.9rem; font-size: 0.9rem; align-self: flex-start; }
.god-ascend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.god-ascend-cap { font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; opacity: 0.65; }
.ascend-pill {
    min-width: 40px;
    min-height: 40px;
    padding: 0.25rem 0.6rem;
    border-radius: 999px;
    border: 1px solid rgba(212, 175, 55, 0.5);
    background: transparent;
    color: #f0d98a;
    font: inherit;
    font-size: 0.8rem;
    cursor: pointer;
}
.god-ascend-note { flex-basis: 100%; margin: 0; font-size: 0.78rem; line-height: 1.35; opacity: 0.8; }
.ascend-pill:hover:not(:disabled) { background: rgba(212, 175, 55, 0.16); }
.ascend-pill:focus-visible { outline: 2px solid #f0d98a; outline-offset: 2px; }
.ascend-pill:disabled { opacity: 0.4; cursor: not-allowed; }
.ascend-pill.done { background: rgba(212, 175, 55, 0.22); border-color: #e3b93c; }
/* The prize: a gilded rim that thickens with each level cleared. */
.god-card.gilded-1 { box-shadow: 0 0 0 1px #e3b93c; }
.god-card.gilded-2 { box-shadow: 0 0 0 2px #e3b93c, 0 0 12px rgba(227, 185, 60, 0.35); }
.god-card.gilded-3 { box-shadow: 0 0 0 3px #f0d98a, 0 0 18px rgba(240, 217, 138, 0.55); }
.god-amulet {
    position: absolute;
    top: 8px;
    right: 12px;
    font-size: 1.3rem;
    color: #e3b93c;
    text-shadow: 0 0 10px rgba(227, 185, 60, 0.6);
}

#top-player.has-boss {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
}
.boss-hud {
    position: relative;
    display: grid;
    grid-template-columns: 64px auto;
    gap: 10px;
    align-items: center;
    padding: 6px 12px 6px 6px;
    border-radius: 14px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.4);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}
.boss-hud[hidden] { display: none; }
.boss-portrait { width: 64px; height: 64px; }
.boss-info { display: flex; flex-direction: column; gap: 3px; min-width: 150px; }
.boss-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.boss-name { font-weight: 800; color: #f0d98a; letter-spacing: 0.02em; }
.boss-hp { font-size: 0.75rem; opacity: 0.8; font-variant-numeric: tabular-nums; }
.boss-bar {
    height: 9px;
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(212, 175, 55, 0.4);
    overflow: hidden;
}
.boss-bar-fill {
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, #b3342a, #e3b93c);
    transition: width 0.35s ease;
}
.boss-bar.low .boss-bar-fill { background: linear-gradient(90deg, #7a1a12, #b3342a); }
.boss-extra { font-size: 0.72rem; color: #f0d98a; min-height: 0.9em; }
.boss-power { font-size: 0.72rem; opacity: 0.75; max-width: 230px; line-height: 1.3; }
.boss-float {
    position: absolute;
    right: 10px;
    top: -4px;
    font-weight: 900;
    font-size: 1.1rem;
    pointer-events: none;
    animation: bossFloat 1.1s ease-out forwards;
}
.boss-float-hit { color: #ffd27a; }
.boss-float-heal { color: #6ee7b7; }
.boss-float-steal { color: #fca5a5; }
.boss-float-ghost { color: #a5f3fc; text-shadow: 0 0 8px rgba(103, 232, 249, 0.8); }
@keyframes bossFloat {
    from { transform: translateY(0); opacity: 1; }
    to { transform: translateY(-26px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .boss-float { animation: none; opacity: 1; }
    .boss-bar-fill { transition: none; }
}
@media (max-width: 520px) {
    /* Phones: the HUD stacks above the god's deck, narrow enough to clear the
       score pill on the right (measured at 390px). */
    #top-player.has-boss { flex-direction: column; gap: 6px; }
    .boss-hud { grid-template-columns: 44px auto; padding: 4px 10px 4px 4px; gap: 8px; }
    .boss-portrait { width: 44px; height: 44px; }
    .boss-info { min-width: 108px; }
    .boss-name { font-size: 0.85rem; }
    .boss-power, .boss-extra:empty { display: none; }
}
@media (max-width: 520px) {
    /* The account/coin chips float over the top of every menu panel on a phone. */
    #legends-panel > h2 { margin-top: 3.25rem; }
}

/* --- The Duat Journey (v3.18.0) ------------------------------------------ */
.legend-best {
    color: #f0d98a;
    font-size: 0.9rem;
    min-height: 1.2em;
    margin: 0 0 0.75rem;
}
/* The night: the whole scene behind the table darkens and cools, and lifts
   hour by hour (duat.js sets --duat-night from 1 in the Duat to 0 at dawn). */
/* The game screen paints its scene on <body> itself, so the night is a
   fixed layer above that background and below every .screen (z-index 5). */
body.duat-journey::after {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    background: radial-gradient(ellipse at 50% 35%, rgba(30, 44, 96, 0.55), rgba(4, 6, 20, 0.92));
    opacity: calc(0.85 * var(--duat-night, 1));
    transition: opacity 1.2s ease;
}
/* The HUD hangs beside your deck without moving it: the deck stays centred,
   where it always is, so the action log never slides under it. */
body.duat-journey #bottom-player { position: relative; }
.duat-hud {
    position: absolute;
    left: calc(50% + 64px);
    top: 50%;
    transform: translateY(-50%);
    z-index: 11;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 200px;
    max-width: 260px;
    padding: 8px 12px;
    border-radius: 14px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.4);
    text-align: left;
}
.duat-hud[hidden] { display: none; }
.duat-hud.dead { border-color: rgba(125, 150, 230, 0.55); }
.duat-title { font-weight: 800; color: #f0d98a; font-size: 0.9rem; }
.duat-hud.dead .duat-title { color: #b9c7ff; }
.duat-pips { display: flex; gap: 4px; flex-wrap: wrap; }
.duat-pip {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1px solid rgba(212, 175, 55, 0.45);
    background: rgba(255, 255, 255, 0.05);
}
.duat-pip.on { background: #e3b93c; border-color: #fff0a6; }
.duat-hud.dead .duat-pip { border-color: rgba(185, 199, 255, 0.45); }
.duat-hud.dead .duat-pip.on { background: #7d8fd8; border-color: #b9c7ff; }
.duat-line { font-size: 0.75rem; opacity: 0.8; line-height: 1.3; min-height: 1em; }
/* v3.19.3 — the three ankhs: tries left in the Duat. Gold and lit while
   yours; a spent one goes dark and cracked, shaking once as Ammit takes it. */
.duat-tries { display: flex; gap: 8px; align-items: center; }
.duat-tries[hidden] { display: none; }
.duat-ankh {
    display: inline-flex;
    width: 22px;
    height: 30px;
    color: #f0d98a;
    filter: drop-shadow(0 0 5px rgba(240, 217, 138, 0.75));
    transition: color 0.4s ease, filter 0.4s ease, opacity 0.4s ease;
}
.duat-ankh svg { width: 100%; height: 100%; display: block; }
.duat-ankh.spent {
    color: #4a5070;
    opacity: 0.55;
    filter: none;
    position: relative;
}
.duat-ankh.spent::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 8%;
    width: 2px;
    height: 84%;
    background: #f85149;
    transform: translateX(-50%) rotate(28deg);
    border-radius: 1px;
}
.duat-ankh.just-spent { animation: duat-ankh-lost 0.6s ease; }
@keyframes duat-ankh-lost {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-3px) rotate(-8deg); }
    40% { transform: translateX(3px) rotate(8deg); }
    60% { transform: translateX(-2px); }
}
/* The Duat keeps you: a stamp over the table before the end screen. */
.duat-verdict {
    position: fixed;
    left: 50%;
    top: 33%;   /* above the winner banner, which the engine centres */
    z-index: 1200;  /* over the slap coach and toasts; the end screen hides it first */
    transform: translate(-50%, -50%) rotate(-6deg);
    max-width: 92vw;
    padding: 10px 28px;
    border: 4px solid #f85149;
    border-radius: 12px;
    color: #f85149;
    background: rgba(10, 8, 20, 0.82);
    font-size: clamp(1.8rem, 10vw, 3.6rem);
    font-weight: 900;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    text-shadow: 0 0 22px rgba(248, 81, 73, 0.55);
    pointer-events: none;
    animation: duat-verdict-in 0.45s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}
.duat-verdict[hidden] { display: none; }
@keyframes duat-verdict-in {
    from { transform: translate(-50%, -50%) rotate(-6deg) scale(1.8); opacity: 0; }
    to { transform: translate(-50%, -50%) rotate(-6deg) scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    body.duat-journey::after { transition: none; }
    .duat-ankh.just-spent, .duat-verdict { animation: none; }
}
@media (max-width: 520px) {
    .duat-hud {
        left: 50%;
        top: auto;
        bottom: calc(100% + 6px);
        transform: translateX(-50%);
        min-width: 190px;
        max-width: 92vw;
        padding: 6px 10px;
    }
    .duat-line { display: none; }
}

/* --- Senet: the Game of Passing (v3.26.0, council ERS-40) -----------------
   The HUD frame is the shared panel surface; the board inside it is a world
   object (DESIGN §4) and is painted like the tomb art. It hangs beside your
   deck as the Duat's clock does — the two are never shown together. */
body.senet-race #bottom-player { position: relative; }
.senet-hud {
    position: absolute;
    left: calc(50% + 64px);
    /* Never past your zone's right edge: the emoji and chat buttons hang just
       outside it (measured at 1024 px: the HUD covered the emoji button). */
    right: 0;
    max-width: 268px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 11;
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 8px 10px;
    border-radius: 14px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.4);
    text-align: left;
}
.senet-hud[hidden] { display: none; }
.senet-title { font-weight: 800; color: #f0d98a; font-size: 0.88rem; }
.senet-board { line-height: 0; }
.senet-svg { width: 100%; height: auto; display: block; }
/* One clock: the browser's own transition, started only by the transform
   senet.js writes when a pile is won (#115). */
.senet-piece { transition: transform 0.45s ease; }
.senet-piece.you { stroke: #fff7d6; stroke-width: 2px; }
.senet-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 2px 10px;
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
    opacity: 0.85;
}
.senet-seat { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.senet-seat.you { font-weight: 800; opacity: 1; }
.senet-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 1px solid #1a1410;
    flex: none;
}
.senet-line { font-size: 0.75rem; opacity: 0.8; line-height: 1.3; min-height: 1em; }
.senet-float {
    position: absolute;
    right: 10px;
    top: -4px;
    font-weight: 900;
    font-size: 1.1rem;
    pointer-events: none;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
    animation: bossFloat 1.1s ease-out forwards;
}
/* The journey card: the third one takes the whole row rather than leaving
   half of one empty, and keeps its text to a readable measure. */
.mode-senet {
    grid-column: 1 / -1;
    box-shadow: inset 0 0 0 1px rgba(61, 127, 214, 0.12), 0 8px 24px rgba(30, 18, 6, 0.35);
}
.mode-senet .mode-desc { max-width: 70ch; }
.senet-throws-cap { margin: 4px 0 0; font-size: 0.78rem; font-weight: 700; opacity: 0.85; }
.senet-throws { margin-top: 0; }
.senet-throws li { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) {
    .senet-piece { transition: none; }
    .senet-float { animation: none; opacity: 1; }
}
/* The table's name labels wear their piece's colour during a race. */
body.senet-race #player-name-display::before,
body.senet-race #p1-name::before,
body.senet-race #p2-name::before,
body.senet-race #p3-name::before {
    content: "";
    display: inline-block;
    width: 9px;
    height: 9px;
    margin-right: 5px;
    border-radius: 50%;
    border: 1px solid #1a1410;
    vertical-align: middle;
}
body.senet-race #player-name-display::before { background: var(--senet-c0); }
body.senet-race #p1-name::before { background: var(--senet-c1); }
body.senet-race #p2-name::before { background: var(--senet-c2); }
body.senet-race #p3-name::before { background: var(--senet-c3); }
@media (max-width: 520px) {
    /* A phone: the board alone, in the gap between the pile and your deck,
       sized to that gap by senet.js (phoneBoardWidth) so it never covers the
       pile. The words go to the log; the colours are on the names. */
    .senet-hud {
        left: 50%;
        right: auto;
        top: auto;
        bottom: var(--senet-hud-bottom, calc(100% + 6px));
        transform: translateX(-50%);
        max-width: none;
        padding: 4px;
        gap: 0;
    }
    .senet-title, .senet-legend, .senet-line { display: none; }
    .senet-board { width: var(--senet-board-w, 200px); }
    .senet-hud.senet-folded { display: none; }
}

/* --- The Pharaoh's Tomb (v3.18.0) ---------------------------------------- */
#tomb-screen {
    background: rgba(10, 14, 20, 0.55);
    backdrop-filter: blur(18px) saturate(1.3);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
}
.tomb-container { padding-top: 3rem; }
.tomb-table { display: flex; flex-direction: column; align-items: center; width: 100%; gap: 10px; }
.tomb-table[hidden], .tomb-draft[hidden], #tomb-done[hidden], #tomb-intro[hidden], #tomb-progress[hidden] { display: none; }
.tomb-guardian { display: flex; align-items: center; gap: 12px; text-align: left; }
.tomb-portrait { width: 76px; height: 76px; }
.tomb-guardian-info { display: flex; flex-direction: column; gap: 2px; }
.tomb-chamber { font-size: 0.8rem; opacity: 0.75; }
.tomb-guard-name { font-weight: 800; color: #f0d98a; font-size: 1.05rem; }
.tomb-count { font-size: 0.8rem; opacity: 0.75; font-variant-numeric: tabular-nums; }
.tomb-pile { width: 150px; height: 130px; margin: 6px 0 4px; cursor: pointer; touch-action: manipulation; }
.tomb-pile .card { width: 90px; }
.tomb-hand { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; min-height: 100px; }
.tomb-card {
    position: relative;
    width: 70px;
    height: 100px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    border-radius: 12px;
    transition: transform 0.15s ease;
}
.tomb-card .card { top: 0; left: 0; }
.tomb-card:hover:not(:disabled) { transform: translateY(-6px); }
.tomb-card:focus-visible { outline: 2px solid #f0d98a; outline-offset: 3px; }
.tomb-card:disabled { cursor: default; opacity: 0.55; }
.tomb-hand.your-turn .tomb-card { box-shadow: 0 0 0 2px rgba(240, 217, 138, 0.55); }
.tomb-draft { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.tomb-actions { display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; }
@media (prefers-reduced-motion: reduce) {
    .tomb-card { transition: none; }
}

/* --- A god at a multiplayer table (v3.18.0) ------------------------------ */
.lobby-god {
    width: 100%;
    display: grid;
    gap: 6px;
    margin-bottom: 16px;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.3);
    text-align: left;
}
.lobby-god-label { color: #f0d98a; font-weight: 700; font-size: 0.9rem; }
.lobby-god-select {
    padding: 0.45rem 0.6rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: rgba(0, 0, 0, 0.35);
    color: #fff;
    font: inherit;
}
.lobby-god-select:disabled { opacity: 0.8; }
.lobby-god-note { margin: 0; font-size: 0.78rem; opacity: 0.75; line-height: 1.35; min-height: 1em; }

/* --- Legends: the two journey cards (v3.18.0) ------------------------------
   Built like the god cards: an emblem, the promise, three facts, the rule,
   the way in. The whole card is the surface; the button no longer floats
   below a paragraph with a gap under it. */
.mode-cards {
    width: 100%;
    max-width: 900px;
    margin: 0 auto 1.5rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 14px;
}
.mode-card {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 14px;
    align-items: start;
    text-align: left;
    padding: 14px;
    border-radius: 18px;
    background: var(--panel-bg);
    border: 1px solid rgba(212, 175, 55, 0.22);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.mode-duat { box-shadow: inset 0 0 0 1px rgba(111, 143, 224, 0.12), 0 8px 24px rgba(6, 10, 28, 0.35); }
.mode-tomb { box-shadow: inset 0 0 0 1px rgba(227, 185, 60, 0.12), 0 8px 24px rgba(40, 20, 4, 0.35); }
.mode-emblem { width: 96px; height: 96px; }
.mode-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.mode-title { margin: 0; font-size: 1.15rem; color: #f0d98a; }
.mode-tagline { margin: 0; font-weight: 700; font-size: 0.95rem; line-height: 1.35; }
.mode-facts {
    list-style: none;
    margin: 2px 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.mode-facts li {
    font-size: 0.75rem;
    padding: 3px 9px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.12);
    white-space: nowrap;
}
.mode-desc { margin: 2px 0 0; font-size: 0.82rem; line-height: 1.5; opacity: 0.72; }
.mode-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.mode-foot .btn { padding: 0.55rem 1.1rem; font-size: 0.95rem; }
.mode-best { font-size: 0.8rem; color: #f0d98a; }
.mode-best:empty { display: none; }
@media (max-width: 520px) {
    .mode-card { grid-template-columns: 64px 1fr; gap: 12px; padding: 12px; }
    .mode-emblem { width: 64px; height: 64px; }
}


/* Tomb intro (ERS-18 fix 3): Practice's intro, with the tomb's emblem and
   the four rules as a list. The trap line is the one rule ERS does not have,
   so it alone is marked. */
.tomb-intro {
    text-align: center;
    padding: 0.5rem 0 1rem;
}
.tomb-intro-emblem {
    width: 88px;
    height: 88px;
    margin: 0 auto 0.75rem;
}
.tomb-intro-emblem svg {
    width: 100%;
    height: 100%;
    display: block;
}
.tomb-rules {
    list-style: none;
    padding: 0;
    margin: 0 auto 1.75rem;
    max-width: 440px;
    text-align: left;
    display: grid;
    gap: 0.55rem;
}
.tomb-rules li {
    position: relative;
    padding-left: 1.4rem;
    line-height: 1.5;
    opacity: 0.9;
}
.tomb-rules li::before {
    content: "\25B8";
    position: absolute;
    left: 0.2rem;
    color: var(--primary);
}
.tomb-rules li.tomb-rule-trap {
    padding: 0.55rem 0.7rem 0.55rem 1.9rem;
    border-radius: 10px;
    background: rgba(244, 114, 94, 0.12);
    border: 1px solid rgba(244, 114, 94, 0.35);
}
.tomb-rules li.tomb-rule-trap::before {
    content: "\26A0";
    left: 0.6rem;
    top: 0.55rem;
    color: #f4a28c;
}

/* ── v3.19.0 — ghost cards (Table of the Gods; council ERS-20) ──────────────
   A clone the god keeps of a card that hurt it. It must stay as READABLE as a
   real card — a player slaps on its rank — so the face keeps its colours and
   only the stock turns spectral: pale ka-blue, a cold glow, a slow pulse. */
:root {
    --ghost-face: rgba(224, 247, 250, 0.84);
    --ghost-edge: rgba(103, 232, 249, 0.9);
    --ghost-glow: rgba(103, 232, 249, 0.55);
}
.card.ghost {
    background: linear-gradient(160deg, var(--ghost-face), rgba(165, 243, 252, 0.72));
    box-shadow: 0 0 14px var(--ghost-glow), inset 0 0 0 1px var(--ghost-edge);
    animation: ghostPulse 2.2s ease-in-out infinite alternate;
}
.card.ghost::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0) 0 5px, rgba(255, 255, 255, 0.16) 5px 6px);
    pointer-events: none;
}
.card.ghost.fly-in {
    animation: cardFlyIn 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, ghostPulse 2.2s ease-in-out 0.2s infinite alternate;
}
@keyframes ghostPulse {
    from { box-shadow: 0 0 8px var(--ghost-glow), inset 0 0 0 1px var(--ghost-edge); }
    to { box-shadow: 0 0 20px var(--ghost-glow), inset 0 0 0 1px var(--ghost-edge); }
}
/* Won pile: a ghost goes to no one. It rises and fades where it lay. */
.card.ghost.ghost-vaporize {
    animation: ghostVaporize 0.55s ease-out forwards;
}
@keyframes ghostVaporize {
    to { opacity: 0; filter: blur(6px); transform: translateY(-42px) scale(1.12); }
}
.ghost-chip {
    position: absolute;
    top: -10px;
    right: -12px;
    z-index: 3;
    font-size: 0.7rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: #083344;
    background: #a5f3fc;
    border: 1px solid #22d3ee;
    border-radius: 999px;
    padding: 1px 7px;
    white-space: nowrap;
    box-shadow: 0 0 10px var(--ghost-glow);
    pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    .card.ghost, .card.ghost.fly-in { animation: none; }
    .card.ghost.ghost-vaporize { animation: ghostFade 0.3s linear forwards; }
    @keyframes ghostFade { to { opacity: 0; } }
}

/* ============================================================
   THE ART DECKS — the Pharaoh's Deck (v3.20.0, council ERS-24) and the
   Deck of the Gods (v3.21.0, ERS-25). pharaohDeck.js dresses a card and
   adds .pd-deck; everything structural below keys on .pd-deck, and each
   skin supplies only its tokens (colours, ground, glow) — one hand, two
   decks. The SVG figures carry classes, never colours.
   ============================================================ */

/* -- the Pharaoh's Deck: ivory parchment by day ----------------------------- */
.card.card-skin-pharaoh {
    --pd-parch: #f4e9cc;
    --pd-parch-edge: #e3cd98;
    --pd-gold: #d4a53f;
    --pd-gold-deep: #8f6a1c;
    --pd-gold-light: #ffe6a3;
    --pd-ink: #1b1410;
    --pd-carn: #a3281c;
    --pd-lapis: #1f4a9a;
    --pd-turq: #1d8278;
    --pd-skin: #c98f55;
    --pd-linen: #fbf6e8;
    --pd-green: #3c9a5f;
    --pd-white: #f6f2e6;
    --pd-red: #c0392b;
    --pd-brown: #8a5a32;
    --pd-line: #2a1d10;
    --pd-panel: rgba(143, 106, 28, 0.07);
    --pd-idx-black: var(--pd-ink);
    --pd-idx-red: var(--pd-carn);
    --pd-suit-black: var(--pd-lapis);
    --pd-suit-red: var(--pd-carn);
    --pd-ground: radial-gradient(ellipse at 50% 42%, #fcf6e4 0%, var(--pd-parch) 58%, var(--pd-parch-edge) 100%);
    --pd-texture: linear-gradient(transparent, transparent);
    --pd-inner-ring: var(--pd-parch);
    --pd-glyph: var(--pd-gold-deep);
    --pd-glyph-light: #fff4c8;
    --pd-glow: rgba(255, 214, 120, 0.42);
    --pd-bloom: rgba(255, 196, 80, 0.95);
    --pd-sun-core: rgba(255, 196, 70, 0.95);
    --pd-sun-mid: rgba(240, 160, 40, 0.5);
    --pd-sheen: rgba(255, 236, 170, 0.9);
    --pd-sheen-edge: rgba(255, 190, 60, 0.28);
    --pd-pip-glow: rgba(255, 214, 120, 0.55);
    --pd-eye-lo: rgba(255, 214, 120, 0.3);
    --pd-eye-hi: rgba(255, 214, 120, 0.95);
    font-family: Georgia, 'Times New Roman', serif;
}

/* -- the Deck of the Gods: lapis lazuli by night --------------------------- */
.card.card-skin-gods {
    --pd-lapis-mid: #1f3d8c;
    --pd-lapis-edge: #0e1c4c;
    --pd-gold: #d9b25a;
    --pd-gold-deep: #a07a2a;
    --pd-gold-light: #ffe9ad;
    --pd-ink: #0b1026;
    --pd-carn: #c0392b;
    --pd-lapis: #16307a;
    --pd-turq: #26a393;
    --pd-skin: #c98f55;
    --pd-linen: #f6f1e2;
    --pd-green: #3fa565;
    --pd-white: #f6f2e6;
    --pd-red: #c8372a;
    --pd-brown: #9a6536;
    --pd-line: #e0bd66;
    --pd-panel: rgba(255, 226, 150, 0.07);
    --pd-idx-black: #f5dfa0;
    --pd-idx-red: #eea0af;
    --pd-suit-black: var(--pd-turq);
    --pd-suit-red: var(--pd-carn);
    --pd-ground: radial-gradient(ellipse at 50% 40%, var(--pd-lapis-mid) 0%, #172f72 55%, var(--pd-lapis-edge) 100%);
    --pd-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='44' viewBox='0 0 44 44'%3E%3Cg fill='%23e8c56a'%3E%3Ccircle cx='6' cy='9' r='0.9' opacity='0.55'/%3E%3Ccircle cx='29' cy='5' r='0.6' opacity='0.45'/%3E%3Ccircle cx='17' cy='24' r='1.1' opacity='0.35'/%3E%3Ccircle cx='38' cy='21' r='0.7' opacity='0.5'/%3E%3Ccircle cx='9' cy='37' r='0.6' opacity='0.4'/%3E%3Ccircle cx='31' cy='36' r='1' opacity='0.3'/%3E%3Cpath d='M22 13l1.2 0.5-0.9 0.9z' opacity='0.35'/%3E%3C/g%3E%3C/svg%3E");
    --pd-inner-ring: #122760;
    --pd-glyph: var(--pd-gold);
    --pd-glyph-light: #fff6d6;
    --pd-glow: rgba(120, 160, 255, 0.4);
    --pd-bloom: rgba(110, 160, 255, 0.95);
    --pd-sun-core: rgba(170, 205, 255, 0.75);
    --pd-sun-mid: rgba(90, 130, 230, 0.35);
    --pd-sheen: rgba(255, 233, 173, 0.75);
    --pd-sheen-edge: rgba(217, 178, 90, 0.22);
    --pd-pip-glow: rgba(140, 180, 255, 0.6);
    --pd-eye-lo: rgba(255, 170, 90, 0.35);
    --pd-eye-hi: rgba(255, 150, 70, 1);
    font-family: Georgia, 'Times New Roman', serif;
}

/* -- one hand for both ----------------------------------------------------- */
.card.pd-deck {
    background: var(--pd-texture) 0 0 / 44px 44px repeat, var(--pd-ground);
    box-shadow:
        0 0 14px var(--pd-glow),
        -2px 5px 10px rgba(0, 0, 0, 0.4),
        inset 0 0 0 2px var(--pd-gold),
        inset 0 0 0 4px var(--pd-inner-ring),
        inset 0 0 0 5px var(--pd-gold-deep),
        inset 0 0 18px rgba(143, 106, 28, 0.28);
}
.card.pd-deck.red   { color: var(--pd-idx-red);   --pd-suit: var(--pd-suit-red); }
.card.pd-deck.black { color: var(--pd-idx-black); --pd-suit: var(--pd-suit-black); }
.card.pd-deck .card-top,
.card.pd-deck .card-bottom { z-index: 3; letter-spacing: -0.5px; }
.card.pd-deck .card-center {
    position: relative;
    z-index: 2;
    -webkit-text-stroke: 1px var(--pd-gold-deep);
    text-shadow: 0 0 10px var(--pd-pip-glow);
}
/* The figure fills the space between the glyph columns. */
.card.pd-deck.pd-court .card-center,
.card.pd-deck.pd-ace .card-center {
    position: absolute;
    inset: 24px 19px;
    display: flex;
    align-items: center;
    justify-content: center;
    -webkit-text-stroke: 0;
    text-shadow: none;
}
.card.pd-deck .pd-art { width: 100%; height: 100%; overflow: visible; }

/* The palette of the figures — each deck's tokens fill the same classes. */
.pd-art .o     { stroke: var(--pd-line); stroke-width: 1.1; stroke-linejoin: round; }
.pd-art .ink   { fill: var(--pd-ink); }
.pd-art .gold  { fill: var(--pd-gold); }
.pd-art .gdeep { fill: var(--pd-gold-deep); }
.pd-art .lapis { fill: var(--pd-lapis); }
.pd-art .turq  { fill: var(--pd-turq); }
.pd-art .carn  { fill: var(--pd-carn); }
.pd-art .skin  { fill: var(--pd-skin); }
.pd-art .linen { fill: var(--pd-linen); }
.pd-art .green { fill: var(--pd-green); }
.pd-art .white { fill: var(--pd-white); }
.pd-art .red   { fill: var(--pd-red); }
.pd-art .brown { fill: var(--pd-brown); }
.pd-art .suit  { fill: var(--pd-suit); }
.pd-art .panel { fill: var(--pd-panel); stroke: var(--pd-gold); stroke-width: 1.4; }
.pd-art .skin-d { fill: #8a5a32; }
.pd-art .ln-g  { fill: none; stroke: var(--pd-gold); stroke-width: 0.9; stroke-linecap: round; }
.pd-art .ln    { fill: none; stroke: var(--pd-ink); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.pd-art [class^="st-"] { fill: none; stroke-linecap: round; }
.pd-art .st-t  { stroke: var(--pd-turq); stroke-width: 3; }
.pd-art .st-g  { stroke: var(--pd-gold); stroke-width: 3; }
.pd-art .st-c  { stroke: var(--pd-carn); stroke-width: 3; }
.pd-art .st-l  { stroke: var(--pd-lapis); stroke-width: 3; }
.pd-art .st-l1 { stroke: var(--pd-lapis); stroke-width: 1.2; }
.pd-art .st-t1 { stroke: var(--pd-turq); stroke-width: 1.6; }
.pd-art .st-g1 { stroke: var(--pd-gold); stroke-width: 1.4; }
.pd-art .st-gw { stroke: var(--pd-gold); stroke-width: 3.2; }
.pd-art .st-lw { stroke: var(--pd-lapis); stroke-width: 3.2; stroke-dasharray: 3 3; }

/* The suit beside a court figure, as on the painted cards. */
.card.pd-deck .pd-pip {
    position: absolute;
    font-size: 1.35rem;
    line-height: 1;
    z-index: 3;
}
.card.pd-deck .pd-pip-a { top: 5%; left: 6%; }
.card.pd-deck .pd-pip-b { bottom: 5%; right: 6%; transform: rotate(180deg); }
.shop-item-preview .card.pd-deck .pd-pip { font-size: 0.62rem; }

/* Hieroglyph columns, inside each long edge, below the corner indices. */
.card.pd-deck .pd-layer { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; }
.card.pd-deck .pd-glyphs { z-index: 1; }
.card.pd-deck .pd-col {
    position: absolute;
    top: 30px;
    bottom: 30px;
    width: 10px;
    overflow: hidden;
    background: var(--pd-glyph);
    opacity: 0.72;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='78' viewBox='0 0 12 78'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cellipse cx='6' cy='4.4' rx='2.3' ry='3'/%3E%3Cpath d='M2 8.6H10M6 8.6V16'/%3E%3Cpath d='M1.4 23.5Q6 19.6 10.6 23.5Q6 27 1.4 23.5Z'/%3E%3Cpath d='M1 32.5L3 30.5L5 32.5L7 30.5L9 32.5L11 30.5M1 36L3 34L5 36L7 34L9 36L11 34'/%3E%3Cpath d='M6 41Q9.4 45.5 6 53Q2.6 45.5 6 41ZM6 53V56'/%3E%3Ccircle cx='6' cy='63' r='3'/%3E%3Cpath d='M2.6 75V70.4Q6 67.6 9.4 70.4V75'/%3E%3C/g%3E%3Ccircle cx='6' cy='23.5' r='1.1' fill='%23000'/%3E%3Ccircle cx='6' cy='63' r='0.9' fill='%23000'/%3E%3C/svg%3E") center top / 100% auto repeat-y;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='78' viewBox='0 0 12 78'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cellipse cx='6' cy='4.4' rx='2.3' ry='3'/%3E%3Cpath d='M2 8.6H10M6 8.6V16'/%3E%3Cpath d='M1.4 23.5Q6 19.6 10.6 23.5Q6 27 1.4 23.5Z'/%3E%3Cpath d='M1 32.5L3 30.5L5 32.5L7 30.5L9 32.5L11 30.5M1 36L3 34L5 36L7 34L9 36L11 34'/%3E%3Cpath d='M6 41Q9.4 45.5 6 53Q2.6 45.5 6 41ZM6 53V56'/%3E%3Ccircle cx='6' cy='63' r='3'/%3E%3Cpath d='M2.6 75V70.4Q6 67.6 9.4 70.4V75'/%3E%3C/g%3E%3Ccircle cx='6' cy='23.5' r='1.1' fill='%23000'/%3E%3Ccircle cx='6' cy='63' r='0.9' fill='%23000'/%3E%3C/svg%3E") center top / 100% auto repeat-y;
}
.card.pd-deck .pd-col-l { left: 8px; }
.card.pd-deck .pd-col-r { right: 8px; }
/* The light that travels down the glyphs — masked by them, so only they glow. */
.card.pd-deck .pd-col::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 45%;
    top: -45%;
    background: linear-gradient(to bottom, transparent, var(--pd-glyph-light) 50%, transparent);
    animation: pdGlyphLight 4.2s ease-in-out infinite;
}
.card.pd-deck .pd-col-r::after { animation-delay: 2.1s; }

/* The disc behind the figure: the sun by day, starlight by night. */
.card.pd-deck .pd-fx { z-index: 1; overflow: hidden; }
.card.pd-deck .pd-sun {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 86%;
    aspect-ratio: 1;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, var(--pd-sun-core) 0%, var(--pd-sun-mid) 34%, transparent 68%);
    opacity: 0.3;
    animation: pdSunrise 1.1s cubic-bezier(0.2, 0.8, 0.2, 1) both, pdSunBreathe 4s ease-in-out 1.1s infinite alternate;
}
.card.pd-deck .pd-sweep {
    position: absolute;
    inset: -10% -60%;
    background: linear-gradient(112deg, transparent 40%, var(--pd-sheen-edge) 46%, var(--pd-sheen) 50%, var(--pd-sheen-edge) 54%, transparent 60%);
    transform: translateX(-70%);
    animation: pdSweep 6s ease-out infinite;
}
.card.pd-deck.pd-ace .card-center .pd-art { animation: pdEye 3.6s ease-in-out infinite alternate; }

/* The Deck of the Gods' signature (ERS-25): the winged sun unfolds, a wave
   of stars lights from the centre out, then the stars keep twinkling. */
.card.pd-deck .pd-wings {
    position: absolute;
    left: 4%;
    right: 4%;
    top: 34%;
    height: 22%;
    opacity: 0.34;
    transform-origin: 50% 50%;
    animation: pdWings 1.3s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.card.pd-deck .pd-wings svg { width: 100%; height: 100%; overflow: visible; }
.card.pd-deck .pd-stars { z-index: 1; }
.card.pd-deck .pd-stars i {
    position: absolute;
    width: 4px;
    height: 4px;
    margin: -2px 0 0 -2px;
    border-radius: 50%;
    background: radial-gradient(circle, #fffbe8 0%, var(--pd-gold-light) 45%, transparent 75%);
    box-shadow: 0 0 5px var(--pd-gold-light);
    opacity: 0.85;
    animation: pdStarIn 0.6s ease-out var(--d, 0s) both, pdTwinkle 2.8s ease-in-out calc(var(--d, 0s) + 0.6s) infinite alternate;
}
.card.pd-deck .pd-stars i:nth-child(3n)   { width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px; }
.card.pd-deck .pd-stars i:nth-child(4n+1) { animation-duration: 0.6s, 3.6s; }

@keyframes pdSunrise {
    0%   { transform: translate(-50%, -50%) scale(0.25); opacity: 0; }
    50%  { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(1);    opacity: 0.3; }
}
@keyframes pdSunBreathe {
    from { opacity: 0.3; }
    to   { opacity: 0.55; }
}
/* The card blooms against the table as it lands — the part of the effect
   that reads from across the table. Gold by day, lapis by night. */
@keyframes pdBloom {
    0%   { box-shadow: 0 0 0 transparent, -2px 5px 10px rgba(0, 0, 0, 0.4), inset 0 0 0 2px var(--pd-gold), inset 0 0 0 4px var(--pd-inner-ring), inset 0 0 0 5px var(--pd-gold-deep), inset 0 0 18px rgba(143, 106, 28, 0.28); }
    45%  { box-shadow: 0 0 38px var(--pd-bloom), -2px 5px 10px rgba(0, 0, 0, 0.4), inset 0 0 0 2px var(--pd-gold-light), inset 0 0 0 4px var(--pd-inner-ring), inset 0 0 0 5px var(--pd-gold), inset 0 0 26px rgba(255, 190, 70, 0.55); }
    100% { box-shadow: 0 0 14px var(--pd-glow), -2px 5px 10px rgba(0, 0, 0, 0.4), inset 0 0 0 2px var(--pd-gold), inset 0 0 0 4px var(--pd-inner-ring), inset 0 0 0 5px var(--pd-gold-deep), inset 0 0 18px rgba(143, 106, 28, 0.28); }
}
#pile-cards .card.pd-deck:last-child,
.shop-item-preview .card.pd-deck { animation: pdBloom 1.2s ease-out both; }
#pile-cards .card.pd-deck.fly-in:last-child { animation: pdBloom 1.2s ease-out both, pdFlyIn 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; }
/* cardFlyIn without its box-shadow: the deck's frame IS its box-shadow. */
@keyframes pdFlyIn {
    0%   { opacity: 0; transform: scale(0.55) translateY(-30px); }
    60%  { opacity: 1; transform: scale(1.12) translateY(4px); }
    80%  { transform: scale(0.97) translateY(-2px); }
    100% { opacity: 1; transform: scale(1) translateY(0px); }
}
@keyframes pdSweep {
    0%        { transform: translateX(-70%); }
    18%, 100% { transform: translateX(70%); }
}
@keyframes pdGlyphLight {
    0%   { top: -45%; }
    100% { top: 100%; }
}
@keyframes pdEye {
    from { filter: drop-shadow(0 0 1px var(--pd-eye-lo)); }
    to   { filter: drop-shadow(0 0 7px var(--pd-eye-hi)); }
}
@keyframes pdWings {
    0%   { transform: scaleX(0.05); opacity: 0;   filter: drop-shadow(0 0 0 transparent); }
    45%  { transform: scaleX(1.06); opacity: 1;   filter: drop-shadow(0 0 7px var(--pd-gold-light)) brightness(1.25); }
    100% { transform: scaleX(1);    opacity: 0.34; filter: drop-shadow(0 0 0 transparent); }
}
@keyframes pdStarIn {
    0%   { transform: scale(0.2); opacity: 0; }
    60%  { transform: scale(1.8); opacity: 1; }
    100% { transform: scale(1);   opacity: 0.85; }
}
@keyframes pdTwinkle {
    from { opacity: 0.85; transform: scale(1); }
    to   { opacity: 0.3;  transform: scale(0.6); }
}

/* Only the TOP card of the pile moves (ERS-24 Q3, ERS-25): the rest rest. */
#pile-cards .card.pd-deck:not(:last-child) .pd-sun,
#pile-cards .card.pd-deck:not(:last-child) .pd-sweep,
#pile-cards .card.pd-deck:not(:last-child) .pd-col::after,
#pile-cards .card.pd-deck:not(:last-child) .pd-wings,
#pile-cards .card.pd-deck:not(:last-child) .pd-stars i,
#pile-cards .card.pd-deck:not(:last-child).pd-ace .card-center .pd-art { animation: none; }
#pile-cards .card.pd-deck:not(:last-child) .pd-sweep,
#pile-cards .card.pd-deck:not(:last-child) .pd-col::after { display: none; }

/* The shop's 68 × 96 preview. */
.shop-item-preview .card.pd-deck .pd-col { top: 17px; bottom: 17px; width: 6px; }
.shop-item-preview .card.pd-deck .pd-col-l { left: 4px; }
.shop-item-preview .card.pd-deck .pd-col-r { right: 4px; }
.shop-item-preview .card.pd-deck.pd-court .card-center,
.shop-item-preview .card.pd-deck.pd-ace .card-center { inset: 14px 11px; }
.shop-item-preview .card.pd-deck .o { stroke-width: 1.5; }
.shop-item-preview .card.pd-deck .pd-stars i { width: 2px; height: 2px; margin: -1px 0 0 -1px; }

@media (prefers-reduced-motion: reduce) {
    .card.pd-deck .pd-sun,
    .card.pd-deck .pd-col::after,
    .card.pd-deck.pd-ace .card-center .pd-art,
    .card.pd-deck .pd-wings,
    .card.pd-deck .pd-stars i,
    #pile-cards .card.pd-deck:last-child,
    #pile-cards .card.pd-deck.fly-in:last-child,
    .shop-item-preview .card.pd-deck { animation: none; }
    .card.pd-deck .pd-sweep,
    .card.pd-deck .pd-col::after { display: none; }
}

/* The mythic tiles in the shop, framed in gold. */
.shop-item.shop-item-mythic {
    border-color: rgba(255, 214, 120, 0.55);
    background: linear-gradient(160deg, rgba(58, 42, 14, 0.75), rgba(30, 24, 12, 0.6));
    box-shadow: inset 0 0 22px rgba(212, 165, 63, 0.22), 0 0 16px rgba(212, 165, 63, 0.18);
}
.shop-item.shop-item-mythic[data-skin="gods"] {
    border-color: rgba(150, 180, 255, 0.5);
    background: linear-gradient(160deg, rgba(20, 34, 84, 0.8), rgba(10, 16, 40, 0.65));
    box-shadow: inset 0 0 22px rgba(90, 130, 230, 0.22), 0 0 16px rgba(217, 178, 90, 0.18);
}

/* =====================================================================
   ADMIN PAGE (v3.22.1, redesigned v3.22.2) — public/admin.html.
   Design system: design-system/ers-admin (designfires, archetype
   "dashboard", tone "precise"), brand-overridden to the game's palette.
   Every colour below is a token; all 24 text/surface pairs were computed
   against WCAG 2.1 AA (lowest: border-strong on surface, 3.04:1 for UI).
   Scoped under body.admin-page so none of it can reach the game.
   ===================================================================== */
body.admin-page {
    --color-bg: #0d1117;
    --color-surface: #161b22;
    --color-surface-2: #1c232d;
    --color-text: #e6edf3;
    --color-muted: #9aa4b2;
    --color-primary: #e8c46a;
    --color-on-primary: #1a1305;
    --color-accent: #79c0ff;
    --color-border: #30363d;
    --color-border-strong: #616771;
    --color-success: #3fb950;
    --color-warning: #f0b429;
    --color-danger: #ff7b72;
    --color-focus: #e8c46a;
    /* translucent roles, as tokens (audit: no literal colour outside this layer) */
    --color-bar: rgba(13, 17, 23, 0.94);
    --color-scrim: rgba(0, 0, 0, 0.65);
    --color-shadow: rgba(0, 0, 0, 0.5);
    --color-warning-soft: rgba(240, 180, 41, 0.1);
    --color-primary-soft: rgba(232, 196, 106, 0.1);
    /* Dark only, on purpose: the game's brand is dark and the operator uses
       the page beside it. Declared, so form controls and scrollbars match. */
    color-scheme: dark;
    --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px;
    --radius: 12px;
    --dur: 140ms;
    --font-mono: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', monospace;
    display: block;
    height: auto;
    min-height: 100vh;
    overflow: auto;
    touch-action: auto;
    background: var(--color-bg);
    color: var(--color-text);
    font-size: 16px;
    line-height: 1.45;
}
.admin-page [hidden] { display: none !important; }
.admin-page h1, .admin-page h2, .admin-page h3, .admin-page h4 { margin: 0; line-height: 1.25; }
.admin-page h3 { font-size: 1.05rem; }
.admin-page h4 { font-size: 0.95rem; margin: var(--space-4) 0 var(--space-2); }
.admin-page .adm-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.admin-page .adm-skip { position: absolute; left: var(--space-2); top: -60px; padding: var(--space-2) var(--space-3); background: var(--color-primary); color: var(--color-on-primary); border-radius: 8px; z-index: 50; }
.admin-page .adm-skip:focus { top: var(--space-2); }
.admin-page .adm-muted { color: var(--color-muted); font-size: 0.9rem; }
.admin-page .adm-mono, .admin-page code, .admin-page .adm-num { font-family: var(--font-mono); font-size: 0.88em; font-variant-numeric: tabular-nums; }
.admin-page .adm-error { color: var(--color-danger); min-height: 1.4em; font-size: 0.92rem; }
.admin-page .adm-ok { color: var(--color-success); font-weight: 700; margin: var(--space-2) 0; }
.admin-page .adm-link { color: var(--color-primary); margin-top: var(--space-3); font-size: 0.92rem; }
.admin-page .adm-linkbtn { background: none; border: 0; padding: 0; color: var(--color-accent); cursor: pointer; font: inherit; text-decoration: underline dotted; min-height: 24px; }
.admin-page :focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* buttons — the page's own, not the game's big .btn */
.admin-page .adm-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    min-height: 36px; padding: 0 var(--space-4);
    border-radius: 10px; border: 1px solid var(--color-border-strong);
    background: var(--color-surface-2); color: var(--color-text);
    font: inherit; font-size: 0.92rem; font-weight: 700; cursor: pointer; text-decoration: none;
    transition: background-color var(--dur) ease-out, border-color var(--dur) ease-out;
}
.admin-page .adm-btn:hover { border-color: var(--color-primary); }
.admin-page .adm-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.admin-page .adm-btn--primary { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary); }
.admin-page .adm-btn--primary:hover { filter: brightness(1.06); }
.admin-page .adm-btn--ghost { background: transparent; }
/* v3.22.3 — a destructive action reads as one: danger outline, never the primary fill */
.admin-page .adm-btn--danger { background: transparent; border-color: var(--color-danger); color: var(--color-danger); }
.admin-page .adm-btn--danger:hover { background: var(--color-surface-2); }
.admin-page .adm-note { margin: var(--space-2) 0; font-size: 0.85rem; max-width: 80ch; }
.admin-page .adm-online-where { display: flex; gap: var(--space-2); flex-wrap: wrap; }
/* v3.22.5 — the two multiplayer tabs read as one group; the online list is split by kind of play */
/* v3.24.0 — "Multiplayer" is a real tab; its two detail tabs read as belonging to it */
.admin-page .adm-tab--sub { font-size: 0.86rem; padding-left: var(--space-2); }
.admin-page .adm-tab--sub::before { content: "↳ "; color: var(--color-text-muted); }
.admin-page .adm-nav-sep { align-self: stretch; width: 1px; margin: var(--space-1) var(--space-2); background: var(--color-border-strong); }
.admin-page .adm-seg { display: inline-flex; flex-wrap: wrap; gap: var(--space-1); }
.admin-page .adm-seg .adm-btn[aria-pressed="true"] { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary); }
.admin-page .adm-online-group { margin-bottom: var(--space-4); }
.admin-page .adm-online-group > header { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-2); }
.admin-page .adm-online-group > header h3 { margin: 0; font-size: 1rem; }
.admin-page .adm-solo { margin-top: var(--space-1); font-size: 0.82rem; display: grid; gap: 2px; }
.admin-page .adm-wide { width: 100%; margin-top: var(--space-3); min-height: 44px; }

/* inputs */
.admin-page input, .admin-page select, .admin-page textarea {
    background: var(--color-bg); color: var(--color-text);
    border: 1px solid var(--color-border-strong); border-radius: 10px;
    min-height: 40px; padding: 0 var(--space-3); font: inherit; font-size: 0.95rem;
}
.admin-page textarea { padding: var(--space-2) var(--space-3); }
.admin-page input[type="checkbox"] { min-height: 0; width: 24px; height: 24px; padding: 0; accent-color: var(--color-primary); }
.admin-page .adm-input { flex: 1 1 220px; min-width: 0; }
.admin-page .adm-textarea { width: 100%; box-sizing: border-box; font-family: var(--font-mono); font-size: 0.85rem; }

/* sign-in */
.admin-page .adm-login { min-height: 100vh; display: grid; place-items: center; padding: var(--space-4); box-sizing: border-box; }
.admin-page .adm-login-card {
    width: min(400px, 100%); box-sizing: border-box;
    display: flex; flex-direction: column; gap: var(--space-2);
    padding: var(--space-5); background: var(--color-surface);
    border: 1px solid var(--color-border); border-top: 3px solid var(--color-primary);
    border-radius: var(--radius); box-shadow: 0 20px 60px var(--color-shadow);
}
.admin-page .adm-login-card label { font-size: 0.95rem; font-weight: 700; margin-top: var(--space-2); }
.admin-page .adm-brand { font-weight: 900; letter-spacing: 0.03em; color: var(--color-primary); font-size: 1.15rem; }
.admin-page .adm-brand--big { font-size: 1.6rem; text-align: center; }

/* frame */
.admin-page .adm-top {
    position: sticky; top: 0; z-index: 10;
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap;
    padding: var(--space-3) var(--space-4); background: var(--color-bar);
    border-bottom: 1px solid var(--color-border); backdrop-filter: blur(6px);
}
.admin-page .adm-top-right { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.admin-page .adm-chip {
    display: inline-flex; align-items: center; gap: var(--space-1);
    min-height: 28px; padding: 0 var(--space-3); border-radius: 999px;
    font-size: 0.82rem; background: var(--color-surface); border: 1px solid var(--color-border);
    font-variant-numeric: tabular-nums;
}
.admin-page .adm-chip.is-good { color: var(--color-success); border-color: var(--color-success); }
.admin-page .adm-chip.is-bad { color: var(--color-danger); border-color: var(--color-danger); }
.admin-page .adm-banner { margin: 0; padding: var(--space-2) var(--space-4); background: var(--color-warning-soft); border-bottom: 1px solid var(--color-warning); color: var(--color-text); font-size: 0.9rem; }
.admin-page .adm-banner p { margin: var(--space-1) 0; }
/* v3.24.0: ten tabs no longer fit one row at 1280px; wrap rather than hide the last ones off-screen */
.admin-page .adm-nav { display: flex; flex-wrap: wrap; gap: var(--space-1); padding: var(--space-2) var(--space-4); border-bottom: 1px solid var(--color-border); }
.admin-page .adm-tab {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--space-2);
    min-height: 40px; padding: 0 var(--space-4); border-radius: 10px;
    background: transparent; color: var(--color-muted); border: 1px solid transparent;
    font: inherit; font-size: 0.92rem; font-weight: 700; cursor: pointer; white-space: nowrap;
    transition: color var(--dur) ease-out, background-color var(--dur) ease-out;
}
.admin-page .adm-tab:hover { color: var(--color-text); background: var(--color-surface); }
.admin-page .adm-tab.is-active { color: var(--color-primary); background: var(--color-surface); border-color: var(--color-border); box-shadow: inset 0 -2px 0 var(--color-primary); }
.admin-page .adm-count:not(:empty) { min-width: 22px; padding: 0 6px; border-radius: 999px; background: var(--color-surface-2); color: var(--color-text); font-size: 0.75rem; text-align: center; font-variant-numeric: tabular-nums; }
.admin-page .adm-main { max-width: 1280px; margin: 0 auto; padding: var(--space-4); box-sizing: border-box; display: block; }
/* the skip link's target: focused by script, never by the user tabbing */
.admin-page .adm-main:focus:not(:focus-visible) { outline: none; }
.admin-page .adm-view { display: flex; flex-direction: column; gap: var(--space-4); }

/* cards */
.admin-page .adm-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); padding: var(--space-4); min-width: 0; }
.admin-page .adm-card > h3 { margin-bottom: var(--space-3); }
.admin-page .adm-card--inset { background: var(--color-bg); margin-top: var(--space-3); }
.admin-page .adm-card--warn { border-color: var(--color-warning); }
.admin-page .adm-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-2); }
.admin-page .adm-card-head h3, .admin-page .adm-card-head h4 { margin: 0; }
.admin-page details.adm-card > summary { cursor: pointer; font-weight: 700; min-height: 24px; }
.admin-page .adm-grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); gap: var(--space-4); }
.admin-page .adm-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: var(--space-2) 0; }
.admin-page .adm-right { justify-content: flex-end; }
.admin-page .adm-check { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 0.9rem; min-height: 32px; cursor: pointer; }
.admin-page .adm-list { display: flex; flex-direction: column; gap: var(--space-2); }
.admin-page .adm-results { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.admin-page .adm-scroll { overflow-x: auto; }

/* stats: the status summary row */
.admin-page .adm-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); gap: var(--space-3); }
.admin-page .adm-stat { display: flex; flex-direction: column; gap: 2px; padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--color-surface); border: 1px solid var(--color-border); border-left: 3px solid var(--color-border-strong); }
.admin-page .adm-stat span { font-size: 0.82rem; color: var(--color-muted); font-weight: 700; }
.admin-page .adm-stat strong { font-size: 1.7rem; font-weight: 900; font-variant-numeric: tabular-nums; }
.admin-page .adm-stat small { font-size: 0.82rem; color: var(--color-muted); }
.admin-page .adm-stat.is-warn { border-left-color: var(--color-warning); }
.admin-page .adm-stat.is-warn strong { color: var(--color-warning); }
.admin-page .adm-stat.is-ok { border-left-color: var(--color-success); }
.admin-page .adm-stat.is-muted strong { color: var(--color-muted); }

/* pills and findings — always a word, never colour alone */
.admin-page .adm-pill { display: inline-block; padding: 1px var(--space-2); border-radius: 999px; font-size: 0.74rem; font-weight: 800; letter-spacing: 0.03em; border: 1px solid currentColor; }
.admin-page .adm-pill.is-error { color: var(--color-danger); }
.admin-page .adm-pill.is-warn { color: var(--color-warning); }
.admin-page .adm-pill.is-info { color: var(--color-accent); }
.admin-page .adm-pill.is-ok { color: var(--color-success); }
.admin-page .adm-findings { list-style: none; margin: var(--space-3) 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.admin-page .adm-findings li { font-size: 0.95rem; padding-left: var(--space-3); border-left: 3px solid var(--color-border-strong); }
.admin-page .adm-findings li.is-error { border-left-color: var(--color-danger); }
.admin-page .adm-findings li.is-warn { border-left-color: var(--color-warning); }
.admin-page .adm-findings li.is-info { border-left-color: var(--color-accent); }
.admin-page .adm-findings code { color: var(--color-muted); }
.admin-page .adm-plus { color: var(--color-success); font-weight: 800; font-variant-numeric: tabular-nums; }
.admin-page .adm-minus { color: var(--color-danger); font-weight: 800; font-variant-numeric: tabular-nums; }

/* rows */
.admin-page .adm-row { display: flex; flex-direction: column; gap: 2px; width: 100%; box-sizing: border-box; text-align: left; color: inherit; font: inherit; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 10px; padding: var(--space-2) var(--space-3); cursor: pointer; }
.admin-page .adm-row:hover { border-color: var(--color-border-strong); }
.admin-page .adm-row--static { cursor: default; }
.admin-page .adm-row-title { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-weight: 700; }

/* states: empty and loading (the skeleton holds the layout, nothing jumps) */
.admin-page .adm-empty { padding: var(--space-4); text-align: center; color: var(--color-muted); list-style: none; }
.admin-page .adm-empty strong { display: block; color: var(--color-text); margin-bottom: var(--space-1); }
.admin-page .adm-empty p { margin: 0; }
.admin-page .adm-skel { height: 56px; border-radius: 10px; background: linear-gradient(90deg, var(--color-surface-2), var(--color-surface), var(--color-surface-2)); background-size: 200% 100%; animation: admSkel 1.4s ease-in-out infinite; }
@keyframes admSkel { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* the event feed */
.admin-page .adm-feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; max-height: 460px; overflow-y: auto; }
.admin-page .adm-ev { display: grid; grid-template-columns: auto auto 1.5em 1fr; align-items: baseline; gap: var(--space-2); padding: var(--space-2) var(--space-1); border-bottom: 1px solid var(--color-border); font-size: 0.92rem; }
.admin-page .adm-ev:last-child { border-bottom: 0; }
.admin-page .adm-ev-time { font-family: var(--font-mono); font-size: 0.8rem; color: var(--color-muted); font-variant-numeric: tabular-nums; }
.admin-page .adm-ev-room { background: none; border: 1px solid var(--color-border); border-radius: 6px; color: var(--color-accent); padding: 0 var(--space-2); cursor: pointer; font-size: 0.78rem; min-height: 24px; }
.admin-page .adm-ev-icon { text-align: center; }
.admin-page .adm-ev.is-bad .adm-ev-text { color: var(--color-danger); }
.admin-page .adm-ev.is-warn .adm-ev-text { color: var(--color-warning); }
.admin-page .adm-ev.is-good .adm-ev-text { color: var(--color-success); }
.admin-page .adm-feed .adm-ev:has(.adm-ev-room) { grid-template-columns: auto auto 1.5em 1fr; }
.admin-page .adm-room .adm-ev { grid-template-columns: auto 1.5em 1fr; }

/* live rooms: list + detail */
.admin-page .adm-split { display: grid; grid-template-columns: minmax(260px, 340px) 1fr; gap: var(--space-4); align-items: start; }
.admin-page .adm-roomlist { display: flex; flex-direction: column; gap: var(--space-2); max-height: 70vh; overflow-y: auto; }
.admin-page .adm-roomitem { display: flex; flex-direction: column; gap: 2px; text-align: left; width: 100%; box-sizing: border-box; padding: var(--space-2) var(--space-3); border-radius: 10px; background: var(--color-bg); color: var(--color-text); border: 1px solid var(--color-border); border-left: 3px solid var(--color-border-strong); font: inherit; cursor: pointer; }
.admin-page .adm-roomitem.is-error { border-left-color: var(--color-danger); }
.admin-page .adm-roomitem.is-warn { border-left-color: var(--color-warning); }
.admin-page .adm-roomitem.is-ok { border-left-color: var(--color-success); }
.admin-page .adm-roomitem.is-selected { background: var(--color-surface-2); border-color: var(--color-primary); }
.admin-page .adm-roomitem-top { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.admin-page .adm-room-head { display: flex; align-items: center; gap: var(--space-2) var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.admin-page .adm-room-head h3 { font-size: 1.2rem; }
.admin-page .adm-status { font-size: 0.82rem; font-weight: 800; padding: 2px var(--space-2); border-radius: 6px; background: var(--color-surface-2); }
.admin-page .adm-status.is-playing { color: var(--color-success); }
.admin-page .adm-status.is-waiting { color: var(--color-accent); }
.admin-page .adm-status.is-done { color: var(--color-muted); }
.admin-page .adm-winner { margin: 0 0 var(--space-3); padding: var(--space-2) var(--space-3); border-radius: 10px; background: var(--color-primary-soft); border: 1px solid var(--color-primary); font-weight: 800; }
.admin-page .adm-seatgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr)); gap: var(--space-2); }
.admin-page .adm-seatcard { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-3); border-radius: 10px; background: var(--color-bg); border: 1px solid var(--color-border); min-width: 0; }
.admin-page .adm-seatcard.is-turn { border-color: var(--color-primary); box-shadow: 0 0 0 1px var(--color-primary); }
.admin-page .adm-seatcard.is-off { border-style: dashed; }
.admin-page .adm-seatcard-top { display: flex; align-items: center; gap: var(--space-2); }
.admin-page .adm-seat-idx { font-family: var(--font-mono); color: var(--color-muted); font-size: 0.8rem; }
.admin-page .adm-turn { font-size: 0.7rem; font-weight: 900; letter-spacing: 0.06em; color: var(--color-on-primary); background: var(--color-primary); border-radius: 4px; padding: 0 6px; }
.admin-page .adm-seat-name { overflow-wrap: anywhere; }
.admin-page .adm-seatcard .adm-linkbtn { align-self: flex-start; }
.admin-page .adm-bar { height: 6px; border-radius: 3px; background: var(--color-surface-2); overflow: hidden; }
.admin-page .adm-bar span { display: block; height: 100%; background: var(--color-accent); }
.admin-page .adm-seat-cards { font-size: 0.85rem; font-variant-numeric: tabular-nums; }
.admin-page .adm-pilebar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1); margin: var(--space-3) 0 0; }
.admin-page .adm-card-chip { font-family: var(--font-mono); font-size: 0.85rem; padding: 1px 6px; border-radius: 4px; background: var(--color-text); color: var(--color-bg); }
.admin-page .adm-tech { margin-top: var(--space-3); border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.admin-page .adm-tech > summary { cursor: pointer; color: var(--color-muted); font-weight: 700; min-height: 24px; }
.admin-page .adm-kvs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); gap: var(--space-2) var(--space-4); margin: var(--space-3) 0; }
.admin-page .adm-kv { display: flex; flex-direction: column; font-size: 0.88rem; min-width: 0; overflow-wrap: anywhere; }
.admin-page .adm-kv span { color: var(--color-muted); font-size: 0.78rem; }
.admin-page .adm-pre { max-height: 360px; overflow: auto; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 10px; padding: var(--space-3); font-family: var(--font-mono); font-size: 0.78rem; }

/* lobby tables */
.admin-page .adm-table { border-left: 3px solid var(--color-border-strong); }
.admin-page .adm-table.is-error { border-left-color: var(--color-danger); }
.admin-page .adm-table.is-warn { border-left-color: var(--color-warning); }
.admin-page .adm-table.is-ok { border-left-color: var(--color-success); }
.admin-page .adm-table-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.admin-page .adm-seats { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.admin-page .adm-seat { font-size: 0.88rem; padding: 2px var(--space-2); border-radius: 8px; background: var(--color-bg); border: 1px solid var(--color-border); }
.admin-page .adm-seat.is-off { border-style: dashed; color: var(--color-muted); }

/* player */
.admin-page .adm-player-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.admin-page .adm-player-head h3 { font-size: 1.3rem; overflow-wrap: anywhere; }
.admin-page .adm-skins { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: var(--space-3) 0; }
.admin-page .adm-skin { font-size: 0.8rem; padding: 1px var(--space-2); border-radius: 6px; border: 1px dashed var(--color-border-strong); color: var(--color-muted); }
.admin-page .adm-skin.is-owned { border-style: solid; border-color: var(--color-primary); color: var(--color-primary); }
.admin-page .adm-grant { margin-top: var(--space-3); padding: var(--space-4); border-radius: var(--radius); background: var(--color-bg); border: 1px solid var(--color-border); border-top: 3px solid var(--color-primary); }
.admin-page .adm-grant h4 { margin-top: 0; }
.admin-page .adm-formgrid { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--space-2) var(--space-3); margin: var(--space-2) 0; }
.admin-page .adm-formgrid label { font-size: 0.95rem; font-weight: 700; }

/* audit */
.admin-page .adm-tbl { width: 100%; border-collapse: collapse; font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.admin-page .adm-tbl th, .admin-page .adm-tbl td { text-align: left; padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--color-border); vertical-align: top; }
.admin-page .adm-tbl th { color: var(--color-muted); font-size: 0.8rem; font-weight: 800; position: sticky; top: 0; background: var(--color-surface); }

/* dialog and toast */
.admin-page .adm-dialog { border: 1px solid var(--color-border); border-top: 3px solid var(--color-primary); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text); padding: var(--space-5); width: min(440px, calc(100vw - 32px)); box-sizing: border-box; }
.admin-page .adm-dialog::backdrop { background: var(--color-scrim); }
.admin-page .adm-dialog p { white-space: pre-line; line-height: 1.6; font-variant-numeric: tabular-nums; }
.admin-page .adm-toast { position: fixed; left: 50%; bottom: var(--space-5); transform: translate(-50%, 24px); opacity: 0; pointer-events: none; transition: opacity var(--dur) ease-out, transform var(--dur) ease-out; padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--color-surface-2); color: var(--color-text); border: 1px solid var(--color-border); border-left: 4px solid var(--color-success); max-width: calc(100vw - 32px); z-index: 30; }
.admin-page .adm-toast.is-shown { opacity: 1; transform: translate(-50%, 0); }
.admin-page .adm-toast.is-warn { border-left-color: var(--color-warning); }
.admin-page .adm-toast.is-error { border-left-color: var(--color-danger); }

/* phone width: one column, the feed stays readable */
@media (max-width: 760px) {
    .admin-page .adm-split { grid-template-columns: 1fr; }
    .admin-page .adm-roomlist { max-height: 40vh; }
    .admin-page .adm-main { padding: var(--space-3) var(--space-4); }
    .admin-page .adm-ev { grid-template-columns: auto 1.5em 1fr; }
    .admin-page .adm-ev-room { grid-column: 1 / -1; justify-self: start; }
    .admin-page .adm-formgrid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
    .admin-page *, .admin-page *::before, .admin-page *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important; transition-duration: 0.001s !important; }
}

/* --- v3.24.1: on a phone, a panel starts below the fixed corner ------------
   #top-left-corner (avatar, coins, the daily spin) sits over every non-game
   screen, from 15px down to about 52px. On a phone every panel is full width,
   so each one's title was drawn UNDER it. That was cosmetic until v3.24.1
   (council ERS-37) put the reading panels' ad directly beneath the title: on
   Slap IQ the unit began 36px below three controls, and AdSense does not
   allow a unit beside navigation or action elements. So below the width at
   which a screen stops being centred (.screen max-width is 600px), a panel's
   content starts clear of the corner. The ID selectors are listed because
   #rules-panel, #leaderboard-panel and #account-panel set their own padding;
   this rule comes after all three. Measured by smoke at 390px. */
@media (max-width: 600px) {
    .screen.scrollable-screen,
    #rules-panel,
    #leaderboard-panel,
    #account-panel {
        padding-top: calc(72px + env(safe-area-inset-top, 0px));
    }
}

/* --- v3.27.0: below-the-fold overview & guide links on #main-menu ----------
   Positioned at top: calc(100% + 12px) of #main-menu so it stays outside
   normal flex flow. At scrollTop = 0 the spacers, username field, buttons and
   #game-version keep the exact coordinates they had in v3.26.0; scrolling the
   menu reveals the game overview and direct links to the Guides hub and all
   seven articles. scrollbar-width: none keeps the artwork free of a scrollbar
   track at rest. */
#main-menu {
    scrollbar-width: none;
}
#main-menu::-webkit-scrollbar {
    display: none;
}
#main-menu .lobby-overview {
    position: absolute;
    top: calc(100% + 12px);
    left: 1rem;
    right: 1rem;
    padding-bottom: 2.5rem;
    text-align: left;
    color: var(--text-color);
    font-size: 0.92rem;
    line-height: 1.6;
}
#main-menu .lobby-overview .rules-section {
    background: var(--panel-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}
#main-menu .lobby-overview h2 {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--primary);
    margin: 0 0 6px;
    line-height: 1.4;
}
#main-menu .lobby-overview p {
    margin: 0;
    color: rgba(230, 237, 243, 0.88);
}
#main-menu .lobby-guide-links {
    margin: 8px 0 0;
    padding-left: 18px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 6px 16px;
}
#main-menu .lobby-guide-links a {
    color: var(--primary);
    text-decoration: none;
}
#main-menu .lobby-guide-links a:hover {
    text-decoration: underline;
}
@media (max-height: 760px) {
    #main-menu .lobby-overview {
        top: calc(100% + 140px);
    }
}
