/* ==========================================================
   DESIGN SYSTEM
   Shared variables used across the game UI.
   Keeping these here makes future theme changes easier.
========================================================== */

:root {
    /* Player colors */
    --p1: #3b82f6;
    --p2: #22c55e;
    --p3: #f97316;
    --p4: #a855f7;

    /* RGB triplets of the above, kept in sync by
       js/ui/cardColor-ui.js applyCardColors() — lets rgba(var(--pN-rgb), a)
       be used anywhere a translucent player color is needed. */
    --p1-rgb: 59, 130, 246;
    --p2-rgb: 34, 197, 94;
    --p3-rgb: 249, 115, 22;
    --p4-rgb: 168, 85, 247;

    /* Base colors */
    --bg-main: #0a1f0f;
    --bg-panel: rgba(255, 255, 255, 0.06);
    --bg-card: linear-gradient(145deg, #1f2937, #111827);

    --text-main: #e5e7eb;
    --text-muted: #cbd5e1;
    --accent: #bd5d38;

    --border: #334155;

    /* Common values */
    --radius-sm: 10px;
    --radius-md: 12px;
    --radius-lg: 18px;

    --shadow-card:
        0 10px 25px rgba(0, 0, 0, 0.4);

    --shadow-panel:
        0 8px 20px rgba(0, 0, 0, 0.35);

    --blur:
        blur(16px);

    /* Shared horizontal padding for standard popups (.modal-content's
       header/body/footer, and the mobile Leaderboard/Party/Trash
       panels) — one responsive value so every popup keeps equal
       left/right breathing room instead of each screen inventing its
       own margin. See css note near .modal-content below. */
    --popup-pad-x: clamp(16px, 4vw, 24px);
}


/* ==========================================================
   STARTUP — Splash → Loading → Error (js/ui/startup-ui.js)
   The very first thing painted; sits above Home (z-index 9999)
   and every modal (z-index 10000) since it can cover both while
   js/home-main.js's bootHome() is still running. Fixed background
   matches .screen-overlay/.modal's existing dark-glass treatment
   so it reads as part of the same app, not a separate splash app.
========================================================== */

.startup-screen {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 20000;

    display: flex;
    justify-content: center;
    align-items: center;

    background: var(--bg-main);

    transition: opacity 0.4s ease;
}

.startup-screen-exit {
    opacity: 0;
    pointer-events: none;
}

.startup-splash,
.startup-loading,
.startup-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.startup-logo {
    width: min(160px, 40vw);
    height: min(160px, 40vw);
    object-fit: contain;
    animation: startupLogoIn 1.4s ease forwards;
}

@keyframes startupLogoIn {
    0%   { opacity: 0; transform: scale(0.85); }
    35%  { opacity: 1; transform: scale(1.04); }
    55%  { opacity: 1; transform: scale(1); }
    100% { opacity: 1; transform: scale(1); }
}

.startup-spinner {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid rgba(255,255,255,0.15);
    border-top-color: var(--accent);
    animation: startupSpin 0.8s linear infinite;
}

@keyframes startupSpin {
    to { transform: rotate(360deg); }
}

.startup-status {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-muted);
    text-align: center;
}

.startup-error .startup-status {
    color: var(--text-main);
}


/* ==========================================================
   ORIENTATION GATE — Rotate Your Device (js/ui/orientation-ui.js)
   Reusable across every real top-level page. Sits above literally
   everything else, including .startup-screen (20000) and every
   .modal (10000/2000), since it must be able to block regardless of
   what else is on screen. Deliberately its own thing rather than a
   .modal: it's not dismissible, has no close button, and is driven
   entirely by device state, not a user action. Same dark-glass
   treatment as .startup-screen/.modal so it still reads as part of
   the same app rather than a bolted-on warning page.
========================================================== */

.orientation-gate {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 999999;

    display: flex;
    justify-content: center;
    align-items: center;

    background: var(--bg-main);

    /* Blocks every click/tap on whatever is rendered underneath —
       this alone is what makes Gameplay/buttons/cards non-interactive
       while shown; nothing underneath is disabled or torn down. */
}

.orientation-gate-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    max-width: min(340px, 84vw);
    text-align: center;
    padding: 32px 28px;
    border-radius: var(--radius-lg);
    background: var(--bg-panel);
    box-shadow: var(--shadow-panel);
}

.orientation-gate-icon {
    font-size: 56px;
    line-height: 1;
    /* Purely decorative flourish on the icon itself — NOT the feature's
       blocking mechanism, which is entirely matchMedia/JS-driven (see
       js/ui/orientation-ui.js). This has zero effect on whether the
       gate shows or hides. */
    animation: orientationGateRock 1.8s ease-in-out infinite;
}

@keyframes orientationGateRock {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(-12deg); }
    75%      { transform: rotate(12deg); }
}

.orientation-gate-title {
    margin: 0;
    font-size: 19px;
    font-weight: 700;
    color: var(--text-main);
}

.orientation-gate-body {
    margin: 0;
    font-size: 14px;
    color: var(--text-muted);
    line-height: 1.45;
}


/* ==========================================================
   GLOBAL
========================================================== */

body {
    margin: 0;

    min-height: 100vh;

    background: var(--bg-main);
    color: var(--text-main);

    font-family: sans-serif;

    overflow-x: hidden;
    overflow-y: auto;

    font-family:'Poppins', sans-serif;
}


/* Shared glass UI component.
   Used by panels, logs, leaderboards, etc. */
.glass-panel {
    background: var(--bg-panel);

    backdrop-filter: var(--blur);

    border-radius: var(--radius-md);

    box-sizing: border-box;
}


/* Shared shadow component */
.card-info,
.modal-content,
.card {
    box-shadow: var(--shadow-panel);
}


/* ==========================================================
   HEADER
========================================================== */

#topBarContent {

    display:grid;

    grid-template-columns: clamp(120px, 22vw, 300px) 1fr clamp(120px, 22vw, 300px);

    align-items:center;

    height: clamp(60px, 6vw, 100px);

    flex-shrink:0;
}


/* LEFT */

#topLeft {

    display: flex;

    flex-direction: column;

    justify-content: center;

    align-items: flex-start;

    height: 100%;

    padding-left: clamp(8px, 1.5vw, 20px);
}

.turn-label {

    font-size: clamp(14px, 2.2vw, 28px);

    font-weight: 700;

    color: var(--accent);
}

.turn-divider {

    width: 120px;

    height: 2px;

    background: rgba(255,255,255,.3);

    margin: 10px 0;
}

.round-label {

    font-size: clamp(11px, 1.4vw, 18px);

    color: var(--text-main);

    display: flex;

    align-items: baseline;

    gap: 6px;
}

.round-timer-sep {
    color: rgba(255,255,255,.35);
}

.turn-timer-icon {

    display: inline-flex;

    align-items: center;

    font-size: clamp(11px, 1.4vw, 18px);

    line-height: 1;
}

/* If config.json's "timer" icon is later switched from an emoji to an
   image path, icon-ui.js swaps in an <img class="icon-image">; size it
   to match the text so the swap doesn't jump the layout. */
.turn-timer-icon .icon-image {

    width: 1em;

    height: 1em;

    object-fit: contain;
}

.turn-timer-label {

    font-weight: 700;

    display: inline-block;

    color: var(--text-main);

    /* JS (renderTurnTimer in game-ui.js) sets the actual color every
       tick, smoothly interpolating from --text-main to red as the
       countdown nears 0 — this transition just softens each step. */
    transition: color .3s ease;
}

/* Last few seconds: an extra pulse on top of the color shift so a
   glance catches the urgency even without focusing on the number. */
@keyframes turnTimerPulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.15); }
}
.turn-timer-label.turn-timer-critical {
    display: inline-block; /* transform: scale() needs this to apply */
    animation: turnTimerPulse 0.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
    .turn-timer-label.turn-timer-critical {
        animation: none;
    }
}

/* Full-screen red flash echoing the turn-timer's urgency once it drops
   under 3 seconds (see #screenDamage in index.html, triggered from
   renderTurnTimer in js/ui/game-ui.js). A plain fixed overlay, never
   intercepts clicks, sits above the game board but below modals/the
   walkthrough overlay (z-index: 50000). */
#screenDamage {
    position: fixed;
    inset: 0;
    z-index: 40000;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(ellipse at center,
        rgba(239,68,68,0) 55%,
        rgba(239,68,68,.55) 100%);
}
#screenDamage.screen-damage-flash {
    animation: screenDamageFlash .5s ease-out;
}
@keyframes screenDamageFlash {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    #screenDamage.screen-damage-flash {
        animation: none;
        opacity: 0;
    }
}


/* CENTER */

#topCenter {

    height: 100%;

    display:flex;

    justify-content:center;

    align-items:center;

    overflow: hidden;
}

#topCenter picture {

    height: 140%;

    display: flex;

    justify-content: center;

    align-items: center;
}

#topCenter img {

    height: 60%;

    width: auto;

    max-height: 100%;

    display: block;

    object-fit: contain;
}


/* RIGHT */

#topRight {

    display: flex;

    justify-content: flex-end;

    align-items: center;

    gap: 12px;

    padding-right: clamp(8px, 1.5vw, 20px);
}

.top-btn {
    width: clamp(34px, 3.5vw, 50px);
    height: clamp(34px, 3.5vw, 50px);

    border-radius: 12px;
    border: none;

    background: transparent;

    color: white;
    font-size: 20px;

    cursor: pointer;
    transition: .2s;

    display: flex;
    justify-content: center;
    align-items: center;
}

.top-btn:hover {

    background: rgba(255,255,255,0.08);

    transform: translateY(-2px);

    box-shadow: 0 6px 15px rgba(0,0,0,.3);
}

/* ── Button tooltip (matches party panel tooltip style) ── */
.top-btn[data-title] {
    position: relative;
}

.top-btn[data-title]::after {
    content: attr(data-title);
    position: absolute;
    top: calc(100% + 8px);
    bottom: auto;
    left: 50%;
    transform: translateX(-50%) scale(0.92);

    background: rgba(10, 31, 15, 0.97);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    font-family: 'Poppins', sans-serif;
    white-space: nowrap;
    padding: 7px 11px;
    border-radius: var(--radius-sm, 8px);
    box-shadow: 0 6px 20px rgba(0,0,0,0.5);

    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s, transform 0.18s;
    z-index: 500;
    line-height: 1.4;
}

.top-btn[data-title]:hover::after {
    opacity: 1;
    transform: translateX(-50%) scale(1);
}

.top-btn[data-title]:hover { cursor: pointer; }


/* Small popup */

.small-popup {

    /* Was a fixed 350px — overflowed horizontally on the narrowest
       real phones (320px-wide viewports leave under 350px of usable
       width once the browser/OS chrome and .modal-content's own
       margins are accounted for). */
    width: min(350px, 92vw);

    text-align: center;
}

.small-popup p {

    font-size: 18px;

    line-height: 1.6;
}

/* ==========================================================
   PAUSE PANEL
========================================================== */

.pause-panel .help-header {
    justify-content: center;
}

.pause-actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: clamp(16px, 5vw, 36px);
    margin-top: 8px;
}

.pause-action {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    background: none;
    border: none;
    padding: 0;
    color: inherit;
    cursor: pointer;
    font-family: inherit;
}

/* Icon box reuses the exact dimensions of the gameplay top-bar
   buttons (.top-btn, css/style.css #topRight) so the pause panel's
   icons read as the same UI element, just in a different context —
   background left transparent, unlike .top-btn's own default. */
.pause-action-icon.top-btn {
    background: transparent;
}

.pause-action-icon.top-btn:hover {
    background: transparent;
    transform: none;
    box-shadow: none;
}

.pause-action-label {
    font-size: 13px;
    font-weight: 600;
    text-align: center;
    white-space: nowrap;
}

#topBar {
    text-align: center;

    margin-bottom: 8px;

    flex-shrink: 0;
}


#gameTitle {

    display:flex;

    justify-content:center;

    align-items:center;

    margin-top:10px;

}

#gameTitle img {

    width:280px;

    height:auto;

    object-fit:contain;

}


#turnInfo,
#currentTurn {
    color: var(--accent);
}


#turnInfo {
    font-size: 14px;

    margin-top: 4px;
}


#currentTurn {
    font-size: 18px;

    font-weight: bold;
}


/* ==========================================================
   PAGE STRUCTURE
========================================================== */

#pageLayout {

    display: grid;

    grid-template-columns: 260px 1fr;

    gap: 20px;

    padding: 10px;

    min-height: 100vh;

    box-sizing: border-box;
}


#leftSidebar {

    width: 260px;

    display: flex;

    flex-direction: column;

    gap: 12px;

    height: calc(100vh - 20px);
}


#gameColumn {

    display: flex;

    flex-direction: column;

    height: calc(100vh - 20px);
}


#gameLayout {

    flex: 1;

    display: grid;

    grid-template-columns:
        clamp(180px, 22vw, 280px)
        1fr
        clamp(180px, 22vw, 280px);

    gap: 12px;

    min-height: 0;

    overflow: hidden;
}


#centerArea {

    display: flex;

    flex-direction: column;

    min-height: 0;
}


/* ==========================================================
   SPLASH FULL SCREEN
========================================================== */

.screen-overlay {

    position: fixed;

    top:0;
    left:0;
    right:0;
    bottom:0;

    width:100vw;
    height:100vh;
    /* Dynamic viewport unit: shrinks to the *visible* area on mobile
       browsers whose address/tab bar can show/hide, instead of the
       old 100vh which is measured against the largest possible
       viewport and can leave content (and buttons) hidden behind the
       browser chrome. Ignored by browsers that don't support dvh,
       which keep the 100vh value above. */
    height:100dvh;

    background:rgba(0,0,0,.8);

    backdrop-filter:blur(10px);

    display:flex;

    justify-content:center;

    align-items:center;

    z-index:9999;

}


.screen-content {

    width:100%;

    height:100%;

    display:flex;

    flex-direction:column;

    /* `safe center`: centers short content exactly like plain `center`
       used to, but falls back to start-aligned once content is taller
       than the viewport instead of clipping/centering it off both
       edges — the exact bug that hid the Choose-Bot-Difficulty and
       End-Game action buttons on short screens. Browsers without
       `safe`/`unsafe` support (very old Safari) just read this as
       `center` and keep the previous behavior; see the `@supports`
       fallback further down that trades centering for correctness on
       those browsers instead. */
    justify-content:center;
    justify-content:safe center;

    align-items:center;

    text-align:center;

    padding:40px;

    background:var(--bg-panel);

    box-sizing:border-box;

    /* Any .screen-content whose content grows taller than the
       viewport now scrolls instead of silently overflowing — this
       alone fixes every "button not visible on smaller screens" case
       across every .screen-overlay page (Choose Bot Difficulty, End
       Game, Coming Soon, guidance prompts, splash) without needing a
       markup change on each one. Panels with real footer buttons
       (Choose Bot Difficulty, End Game) additionally use the
       .screen-content--panel modifier below so those buttons are
       pinned rather than merely scrollable. */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

@supports not (justify-content: safe center) {
    .screen-content {
        /* No `safe` keyword support: prioritize "never hide content"
           over perfect vertical centering for short content. */
        justify-content: flex-start;
    }
}


/* لوگو */

.screen-logo {

    width:min(700px,70vw);

    max-height:60vh;

    object-fit:contain;

}

/* ── Back-to-Home link ────────────────────────────────────
   Every standalone top-level page (Profile, Settings, Cards,
   Game Modes, Coming Soon — see profile.html, settings.html,
   cards.html, game-modes.html, coming-soon.html) uses this same
   affordance to return to Home. It's a real navigation (an <a>
   to index.html), not a modal close — browser Back already does
   the same thing, this is just a visible, clickable equivalent. */
.page-back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    margin-bottom: 14px;
    color: var(--text-muted);
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    transition: color .15s ease;
}

.page-back-link:hover {
    color: var(--text-main);
}

/* دسکتاپ بزرگ */
@media(min-width:1200px){

    .screen-logo{

        width:800px;

        max-height:65vh;

    }

}


/* لپ‌تاپ */
@media(min-width:700px) and (max-width:1199px){

    .screen-logo{

        width:600px;

        max-height:55vh;

    }

}


/* موبایل */
@media(max-width:600px){

    .screen-logo{

        width:90vw;

        max-height:35vh;

    }

}

.creator {

    position:absolute;

    bottom:25px;

    left:0;

    width:100%;

    text-align:center;

    font-family:'Poppins', sans-serif;

    font-size:14px;

    font-weight:400;

    letter-spacing:.5px;

    color:rgba(255,255,255,.75);

}


.creator a{

    color:white;

    text-decoration:none;

    font-weight:600;

    transition:.3s;

}


.creator a:hover{

    opacity:.7;

    text-decoration:underline;

}


/* Mobile */

@media(max-width:600px){

    .creator{

        bottom:15px;

        font-size:12px;

    }

}



/* موبایل */

@media(max-width:600px){

    .creator{

        bottom:15px;

        font-size:12px;

    }

}
/* دکمه */

.screen-btn {

    margin-top:30px;

    padding:14px 35px;

    border:none;

    border-radius:12px;

    cursor:pointer;

    font-size:18px;

    font-weight:700;

}



/* موبایل */

@media(max-width:600px){

    .screen-content{

        padding:20px;

    }


    .screen-logo{

        width:90vw;

        max-height:35vh;

    }


    .screen-btn{

        width:100%;

        max-width:300px;

    }

}

/* ==========================================================
   LEADERBOARD
========================================================== */

#leaderboard {

    width: 100%;

    padding: 12px;

    background: var(--bg-panel);

    backdrop-filter: var(--blur);

    border-radius: var(--radius-lg);

    box-sizing: border-box;

    box-shadow: var(--shadow-panel);
}


/*
  Kept separate from .glass-panel because the leaderboard
  has a unique internal grid structure.
*/

.leaderboard-header,
.leaderboard-row {

    display: grid;

    grid-template-columns:
        1fr
        60px
        60px;

    gap: 10px;

    padding: 6px 0;

    font-size: 13px;
}


.leaderboard-header {

    opacity: 0.6;

    border-bottom:
        1px solid rgba(255,255,255,0.1);

    margin-bottom: 8px;
}


.leaderboard-row {

    align-items: center;
}


/* Player color mapping */

.leaderboard-row[data-player="p1"] {
    color: var(--p1);
}

.leaderboard-row[data-player="p2"] {
    color: var(--p2);
}

.leaderboard-row[data-player="p3"] {
    color: var(--p3);
}

.leaderboard-row[data-player="p4"] {
    color: var(--p4);
}


/* ==========================================================
   TOP PLAYERS
========================================================== */

#topPlayers {

    display: flex;

    justify-content: space-between;

    margin-bottom: 40px;
}


.player {

    width: 200px;

    padding: 10px;

    border:
        1px solid #555;

    border-radius: var(--radius-sm);
}


.player[data-player="p1"] {
    border-left: 4px solid var(--p1);
}

.player[data-player="p2"] {
    border-left: 4px solid var(--p2);
}

.player[data-player="p3"] {
    border-left: 4px solid var(--p3);
}

.player[data-player="p4"] {
    border-left: 4px solid var(--p4);
}

/* ==========================================================
   PANELS
   Reusable glass containers for game sections.
========================================================== */

#partyArea,
#trashArea,
#chatPanel,
#gameLog {

    background: var(--bg-panel);

    backdrop-filter: var(--blur);

    border-radius: var(--radius-lg);

    box-sizing: border-box;
}


/* ==========================================================
   PARTY / TRASH
========================================================== */

#partyArea,
#trashArea {

    display: flex;

    flex-direction: column;

    min-height: 0;
    max-height: calc(100vh - 120px);
    overflow-y: auto;

    padding: 16px;
}


#partyArea h3,
#trashArea h3 {

    margin-top: 0;

    margin-bottom: 12px;

    text-align: center;

    color: var(--text-main);

    letter-spacing: 1px;
}


#partyCards,
#trashCards {

    display: grid;

    grid-template-columns:
        repeat(auto-fill, minmax(60px, 70px));

    gap: 6px;

    justify-content: center;
    overflow: visible;
}


#partyCards .card,
#trashCards .card {

    width: 62px;
    height: 84px;
    font-size: 11px;
    border-radius: 8px;
    transform: none;

}


/* ==========================================================
   CARD COMPONENT
========================================================== */

.card,
.card-info {

    width: clamp(60px, 6.5vw, 90px);

    height: clamp(85px, 9.2vw, 120px);


    border-radius: var(--radius-md);

    background: var(--bg-card);

    border:
        1px solid rgba(255,255,255,0.1);


    display: flex;

    flex-direction: column;

    justify-content: center;

    align-items: center;


    gap: 4px;


    box-shadow: var(--shadow-card);


    transition:
        transform .2s ease,
        box-shadow .2s ease;

    container-type: size;
}

/* Help card-info: same layout as game card but no owner badge */
.card-info {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    padding: 0;
    overflow: hidden;
    /* bigger in the help grid */
    width: clamp(80px, 10vw, 120px);
    height: clamp(110px, 14vw, 165px);
}

.card-info .help-card-emoji {
    font-size: unset;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding-top: 12%;
    font-size: clamp(1.2em, 28cqw, 2.6em);
    line-height: 1;
}

.card-info .card-image {
    width: 65%;
    height: 65%;
    object-fit: contain;
}

.card-info .help-card-footer {
    width: 100%;
    background: rgba(0,0,0,0.38);
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 3% 7%;
    box-sizing: border-box;
    flex-shrink: 0;
}

.card-info .help-card-name {
    font-size: clamp(7px, 10cqw, 11px);
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
}

.card-info .help-card-power {
    font-size: clamp(8px, 12cqw, 14px);
    font-weight: 800;
    color: #fbbf24;
    flex-shrink: 0;
    margin-left: 4%;
    line-height: 1.2;
}


/*
  Interaction feedback:
  Cards lift when hovered to communicate
  that they are selectable.
*/

.card:hover,
.card-info:hover {

    transform:
        translateY(-6px)
        scale(1.05);


    box-shadow:
        0 10px 20px rgba(0,0,0,.4);


    cursor: pointer;
}



/* ── Card new layout ── */

.card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    padding: 0;
    overflow: hidden;
}

/* ── Long-press feedback ──────────────────────────────────
   Scale + shake "wind-up" + glow + circular progress ring while a card
   is being held. Purely visual — driven by the .long-press-active class
   toggled from js/ui/longPress.js the instant a press starts (not once
   it fires), so the shake plays through the whole hold, not just at the
   end. The ring's fill duration is set inline via --long-press-duration
   (see js/ui/game-ui.js) so it always matches the actual timer, with no
   duplicated number in CSS. Disappears immediately (no transition delay)
   if the gesture is cancelled, since the class is simply removed. */
.card.long-press-active {
    animation: long-press-shake 260ms ease-out both;
    box-shadow: var(--shadow-card), 0 0 0 3px rgba(189, 93, 56, 0.55);
    transition: box-shadow 120ms ease-out;
}

@keyframes long-press-shake {
    0%   { transform: scale(1)     rotate(0deg); }
    15%  { transform: scale(1.025) rotate(-1.4deg); }
    30%  { transform: scale(1.035) rotate(1.4deg); }
    45%  { transform: scale(1.04)  rotate(-1deg); }
    60%  { transform: scale(1.04)  rotate(0.7deg); }
    80%  { transform: scale(1.04)  rotate(-0.3deg); }
    100% { transform: scale(1.04)  rotate(0deg); }
}

.card.long-press-active::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 5;
    pointer-events: none;
    border-radius: inherit;
    background: conic-gradient(var(--accent) 0deg, transparent 0deg);
    opacity: 0.35;
    animation: long-press-ring var(--long-press-duration, 800ms) linear forwards;
}

@keyframes long-press-ring {
    from { background: conic-gradient(var(--accent) 0deg, transparent 0deg); }
    to   { background: conic-gradient(var(--accent) 360deg, transparent 360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .card.long-press-active {
        animation: none;
        transform: scale(1.02);
        transition: none;
    }
    .card.long-press-active::after {
        animation: none;
        opacity: 0.25;
    }
}

.card-owner-badge {
    position: absolute;
    top: 5%;
    left: 6%;
    font-size: clamp(7px, 1.1cqw, 10px);
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 20px;
    background: rgba(0,0,0,0.5);
    color: #fff;
    letter-spacing: 0.2px;
    max-width: 75%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    z-index: 2;
    line-height: 1.6;
}

.card-visual {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding-top: 28%;
    min-height: 0;
}

.card-emoji {
    font-size: clamp(1.2em, 38cqw, 3em);
    line-height: 1;
}

.card-image {
    width: 85%;
    height: 85%;
    object-fit: contain;
}

.card-footer {
    width: 100%;
    background: rgba(0,0,0,0.38);
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 3% 7%;
    box-sizing: border-box;
    flex-shrink: 0;
}

.card-name {
    font-size: clamp(7px, 10cqw, 11px);
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: center;
    line-height: 1.2;
}

/* Player card themes.
   Driven by --p1..--p4-rgb (set alongside --p1..--p4 in
   js/ui/cardColor-ui.js applyCardColors()) rather than a fixed color,
   so a picked color actually repaints these — previously hardcoded
   here, this block silently ignored any player-color choice. */

.card[data-player="p1"] {

    background:
        linear-gradient(
            145deg,
            rgba(var(--p1-rgb), .25),
            #111827
        );
}


.card[data-player="p2"] {

    background:
        linear-gradient(
            145deg,
            rgba(var(--p2-rgb), .25),
            #111827
        );
}


.card[data-player="p3"] {

    background:
        linear-gradient(
            145deg,
            rgba(var(--p3-rgb), .25),
            #111827
        );
}


.card[data-player="p4"] {

    background:
        linear-gradient(
            145deg,
            rgba(var(--p4-rgb), .25),
            #111827
        );
}



/* ==========================================================
   BOARD
========================================================== */

#board {

    display: flex;

    justify-content: center;

    gap: 16px;

    min-width: 0;

    flex-wrap: nowrap;
}


/* ==========================================================
   QUEUE
========================================================== */

#queue,
#queue {

    display: flex;

    gap: clamp(6px, 2vw, 30px);
}

#queue .card {

    width: clamp(68px, 8vw, 110px);

    height: clamp(96px, 11.5vw, 155px);

    /* Taken out of flex flow so a second card briefly sharing this slot
       (mid-animation handoff, e.g. Hippo push) can never cause the flex
       container to shrink either card to make room. Both cards keep
       their full, unchanged size and simply overlap instead. */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;

}

/* When two cards are forced into the same queue slot at once, DOM order
   reflects arrival order (appendChild → last child = newest arrival).
   The newer card renders underneath the one already occupying the slot. */
.queue-slot .card ~ .card {
    z-index: 1;
}


.queue-slot {

    width: clamp(68px, 8vw, 110px);

    height: clamp(96px, 11.5vw, 155px);


    border:
        1px dashed rgba(255,255,255,.2);


    border-radius: var(--radius-sm);


    background:
        rgba(255,255,255,.02);


    display: flex;

    align-items: center;

    justify-content: center;
}


#queueArea {

    flex: 1;


    display: flex;

    justify-content: center;

    align-items: center;


    flex-direction: column;


    gap: 20px;
}



/* ==========================================================
   PLAYER HAND
========================================================== */

#handArea {

    display:flex;

    justify-content:center;

    align-items:center;

    gap: clamp(8px, 2vw, 25px);

    margin-top:8px;

    flex-shrink: 0;

    flex-wrap: wrap;

}

#playerHand {

    display:flex;

    justify-content:center;

    gap: clamp(4px, 1.2vw, 16px);


    flex-wrap:wrap;


}

#playerHand .card {

    width: clamp(68px, 8vw, 100px);

    height: clamp(96px, 11.5vw, 140px);

}

/* Let the browser keep handling horizontal scroll/pan of the hand strip
   itself (see the mobile overflow-x:auto rule below); our long-press
   handler cancels on the same real drag via its own movement threshold,
   so this doesn't fight that — it just avoids blocking scroll for the
   fraction of a gesture before our JS threshold check runs. */
#playerHand .card {
    touch-action: pan-x;
}

/* .owner removed - replaced by .card-owner-badge */

/* =========================
   Deck Stack
========================= */


#deckStack {


    display:flex;

    flex-direction: column;

    justify-content:center;

    align-items:center;

    gap: 6px;


}

/* Name + avatar tag above the player's own deck, matching how each
   opponent shows their avatar and name next to their hand
   (.other-avatar / .player-label in the OTHER PLAYER ROW rules
   above) — this is the human seat's equivalent, sitting by their own
   deck instead since their hand is laid out full-width. */
.player-deck-info {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: clamp(90px, 10vw, 130px);
}

.player-deck-avatar-wrap {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    border: 2px solid var(--p1, #4ade80);
}

.player-deck-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.player-deck-name {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (max-width: 600px) {
    .player-deck-avatar-wrap { width: 20px; height: 20px; }
    .player-deck-name { font-size: 10px; }
}



.deck-back {

    width: clamp(68px, 8vw, 100px);

    height: clamp(96px, 11.5vw, 140px);


    border-radius:12px;


    background:
    linear-gradient(
        145deg,
        #374151,
        #111827
    );


    border:
    2px solid rgba(255,255,255,.2);



    box-shadow:
    0 10px 25px rgba(0,0,0,.5);



    display:flex;


    justify-content:center;


    align-items:center;


    position:relative;



}

/* The player's own deck (data-player="p1" — always the human seat, see
   js/game-main.js) — colored the same way the opponents' .other-deck-back
   already is, from the live --p1 variable set in
   js/ui/cardColor-ui.js applyCardColors(). */
.deck-back[data-player="p1"] {
    background:
    linear-gradient(
        145deg,
        var(--p1),
        #0d1a0d
    );
}




#deckCount {


    position:relative;


    font-size:32px;


    font-weight:bold;


    color:white;

}

/* ==========================================================
   OTHER PLAYER HANDS
========================================================== */


#otherPlayers {


    flex-direction:column;

    align-items:center;

    gap:20px;


}



#topPlayer {


    display:flex;

    flex-direction:column;

    align-items:center;

}



#sidePlayers {


    display:flex;

    justify-content:space-between;

    width:100%;

}



.other-hand {


    display:flex;

    gap:6px;

}



.card-back {

    width: clamp(32px, 5.5vw, 85px);

    height: clamp(45px, 8vw, 120px);


    border-radius:8px;


    border:
    1px solid rgba(255,255,255,.25);


    box-shadow:
    0 5px 12px rgba(0,0,0,.4);


    position:relative;


    overflow:hidden;


}

.card-back[data-player="p1"] {

    background:
    linear-gradient(
        145deg,
        var(--p1),
        #111827
    );

}



.card-back[data-player="p2"] {

    background:
    linear-gradient(
        145deg,
        var(--p2),
        #111827
    );

}



.card-back[data-player="p3"] {

    background:
    linear-gradient(
        145deg,
        var(--p3),
        #111827
    );

}



.card-back[data-player="p4"] {

    background:
    linear-gradient(
        145deg,
        var(--p4),
        #111827
    );

}



.card-back::after {


    content:"";


    position:absolute;


    inset:0;


    background-image:
    url("../assets/img/branding/logo-small.png");


    background-repeat:no-repeat;


    background-position:center;


    background-size:60%;


    opacity:0.85;


}



.player-label {


    margin-bottom:8px;


    font-size:14px;


    color:var(--text-muted);


}


/* ==========================================================
   SCOREBOARD
========================================================== */

#scoreboard {

    position: fixed;

    top: 10px;

    left: 10px;
}



/* ==========================================================
   MODAL
========================================================== */

.modal {

    position: fixed;


    inset: 0;


    background:
        rgba(0,0,0,.85);


    backdrop-filter:
        blur(6px);


    display: flex;


    justify-content: center;


    align-items: center;


    /* Home (index.html) is itself a .screen-overlay at z-index 9999
       (see above) — About Developer and the How-to-Play tutorial are
       genuine modals opened *on top of* Home, not a separate page, so
       they need a higher z-index or they'd render underneath it. */
    z-index: 10000;
}


.modal-content {

    width: min(700px, 92vw);


    max-width: 92%;


    padding: 24px;


    border-radius: var(--radius-md);


    max-height: 88vh;
    max-height: 88dvh; /* mobile-browser-chrome-safe, see .screen-overlay */


    overflow-y: auto;


    z-index: 2000;


    color: white;


    border:
        1px solid var(--border);


    background: rgba(10,31,15,0.82);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);


    box-shadow:
        0 20px 60px rgba(0,0,0,.6);

    /* Popup Panel Architecture: Header → Scrollable Body → Fixed
       Footer. Existing modals (no .modal-body/.modal-footer children)
       are unaffected — display:flex + flex-direction:column lays out
       a set of plain block children identically to the old block
       flow, so they keep scrolling as one box exactly as before. Any
       modal that opts in with an explicit .modal-body wrapper (and
       optionally .modal-footer) instead gets a header/footer that
       stay put while only the body scrolls — see the :has() rule
       below and Settings/Profile/Card Guide/Feedback for real
       examples. */
    display: flex;
    flex-direction: column;
}

.modal-content:has(.modal-body) {
    padding: 0;
    overflow: hidden; /* .modal-body scrolls instead of the shell */
}

/* .modal-form: an intermediate wrapper (typically a <form>, e.g. the
   Feedback popup) between .modal-content and .modal-header/body/
   footer — needed because a <form> must directly contain its Submit
   button to work natively, so it can't sit *inside* .modal-body. It
   just continues the same flex column so .modal-body still gets a
   bounded, scrollable height. */
.modal-content > .modal-form {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.modal-content > .modal-header,
.modal-content > .modal-form > .modal-header {
    flex: 0 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 18px var(--popup-pad-x) 14px;
    border-bottom: 1px solid var(--border);
}

.modal-content > .modal-body,
.modal-content > .modal-form > .modal-body {
    flex: 1 1 auto;
    min-height: 0; /* required for a flex child to actually scroll instead of overflowing */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 16px var(--popup-pad-x) 20px;
}

.modal-content > .modal-footer,
.modal-content > .modal-form > .modal-footer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px var(--popup-pad-x) calc(14px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
}

.modal-content .modal-footer .screen-btn,
.modal-content .modal-footer .feedback-submit-btn {
    flex: 1;
    margin-top: 0;
}

@media (max-height: 480px) and (orientation: landscape) {
    .modal-content > .modal-header { padding: 12px var(--popup-pad-x) 10px; }
    .modal-content > .modal-body { padding: 10px var(--popup-pad-x) 14px; }
    .modal-content > .modal-footer { padding: 10px var(--popup-pad-x) calc(10px + env(safe-area-inset-bottom, 0px)); }
}

/* ── About Developer panel redesign ──
   Profile-card layout: close button pinned to the corner, a large
   developer avatar centered up top, title below it, then the usual
   centered body copy and action row. Replaces the old
   .help-header (title+close in a row) for this modal only — that
   shared class is still used as-is by the other modals. */
.about-panel {
    position: relative;
    text-align: center;
    padding-top: 40px;
}

.about-close {
    position: absolute;
    top: 14px;
    right: 14px;
}

[dir="rtl"] .about-close {
    right: auto;
    left: 14px;
}

.about-avatar {
    display: flex;
    justify-content: center;
    margin-bottom: 10px;
}

.about-avatar [data-icon] {
    width: 96px;
    height: 96px;
}

.about-avatar .icon-image {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.about-title {
    margin: 0 0 18px;
    font-size: clamp(20px, 5vw, 26px);
    font-weight: 700;
    color: var(--text-main);
}

.about-content{

    text-align:center;

    line-height:1.7;

    font-size:15px;

}


.about-content strong{

    font-weight:700;

}

/* ── Lucky Wheel — Coming Soon (index.html #luckyWheelModal) ──────
   Same visual language as .about-panel above (dark-glass popup,
   centered icon + title + copy) rather than a new look. Only
   #luckyWheelBody's contents are expected to change when a real
   implementation replaces the Coming Soon state — this shell/layout
   is meant to stay. */

.lucky-wheel-panel {
    position: relative;
    text-align: center;
    padding-top: 40px;
}

.lucky-wheel-close {
    position: absolute;
    top: 14px;
    right: 14px;
}

[dir="rtl"] .lucky-wheel-close {
    right: auto;
    left: 14px;
}

.lucky-wheel-title {
    margin: 0 0 18px;
    font-size: clamp(20px, 5vw, 26px);
    font-weight: 700;
    color: var(--text-main);
}

.lucky-wheel-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.lucky-wheel-illustration {
    display: flex;
    justify-content: center;
    margin-bottom: 4px;
}

.lucky-wheel-illustration [data-icon] {
    font-size: 72px;
    line-height: 1;
}

.lucky-wheel-illustration .icon-image {
    width: 96px;
    height: 96px;
    object-fit: contain;
}

.lucky-wheel-desc {
    margin: 0;
    max-width: 260px;
    line-height: 1.6;
    font-size: 15px;
    color: var(--text-muted);
}


/* Row wrapper for the "Visit Website" / "Give Feedback" pair — keeps
   them side by side on one row (same height, same baseline) instead
   of relying on inline-element wrapping, which could drop the second
   button to its own line depending on available width. */
.about-actions{

    display:flex;

    align-items:center;

    justify-content:center;

    flex-wrap:wrap;

    gap:12px;

    margin-top:15px;

}

.website-link{

    display:inline-flex;

    align-items:center;

    margin-top:0;

    padding:10px 20px;

    border-radius:10px;

    background:var(--accent);

    color:white;

    text-decoration:none;

    font-weight:600;

    transition:.3s;

}


.website-link:hover{

    opacity:.8;

}

.hidden {

    display: none;
}

.icon{

    width:32px;

    height:32px;

    display:flex;

    align-items:center;

    justify-content:center;

    font-size:24px;

}


[data-icon]{

    display:inline-flex;

    align-items:center;

    justify-content:center;

    vertical-align:middle;

}


.icon-image{

    width:2em;

    height:2em;

    object-fit:contain;

    display:inline-block;

    vertical-align:middle;

}
/* ==========================================================
   ANIMAL GRID
========================================================== */

#animalGrid {

    display: grid;

    grid-template-columns: repeat(auto-fill, minmax(clamp(80px,10vw,120px), 1fr));

    gap: 14px;

    align-items: start;
    justify-items: center;
}

/* ==========================================================
   Help COMPONENTS
========================================================== */


.help-layout {

    display: flex;

    flex-direction: column;

    gap: 16px;
}



.help-header {

    display: flex;

    justify-content: space-between;

    align-items: center;
}



.help-card-emoji {

    font-size: 42px;
}



.help-card-power {

    font-size: 24px;

    color: var(--accent);

    font-weight: bold;
}



.help-card-detail {

    text-align: center;
}



.help-card-detail h2 {

    font-size: 26px;

    color: #ffffff;
}

.help-divider,
.settings-divider {

    width: 100%;

    height: 1px;

    background: rgba(255,255,255,.15);

    margin: 24px 0 16px;
}

.tutorial-text p{

    margin: 0 0 6px 0;

    line-height: 1.2;
}

.tutorialPrevBtn,
.tutorialNextBtn {
    background-color: transparent;
    background-repeat: no-repeat;
    border: none;
}

.animal-guide-title {

    text-align: center;

    margin: 0 0 20px;

    font-size: 1.2rem;

    font-weight: 700;

    color: var(--text-main);
}



.help-card-detail h3 {

    margin-top: 20px;

    color: var(--accent);

    font-size: 14px;


    letter-spacing: 1px;


    text-transform: uppercase;
}



.desc-text {

    color: var(--text-muted);

    line-height: 1.5;
}



.detail-emoji {

    font-size: 72px;

    margin-bottom: 10px;
}

/* .detail-image (the animal artwork shown above the ability
   description in the Card Guide's card-detail popup, #cardModal) had
   no size rule at all — it rendered at the source PNG's natural
   pixel size. On Desktop's much larger .modal-content that went
   mostly unnoticed, but combined with this project's landscape-
   mobile "no scroll" layout (short dvh-based max-heights on
   .modal-content, see the Landscape layer further down), an
   unconstrained image could consume the entire available height by
   itself, pushing the "How it Works" ability title/description
   (rendered right after it in the same flex column) out of the
   laid-out content — the root cause of the Card Guide "Animal
   Ability" section appearing empty on Mobile. Matching .detail-emoji
   above with an explicit bounded size fixes this without touching
   the shared .modal-content scroll/overflow architecture. */
.detail-image {
    display: block;
    margin: 0 auto 10px;
    max-width: 100%;
    max-height: clamp(90px, 22dvh, 180px);
    width: auto;
    height: auto;
    object-fit: contain;
}



/* ==========================================================
   POWER BADGE
========================================================== */


.power-badge {

    display: inline-block;


    padding: 8px 16px;


    border-radius: 20px;


    background: var(--accent);


    color: white;


    font-weight: bold;


    margin-bottom: 20px;
}



/* ==========================================================
   EXAMPLE SECTION
========================================================== */


.example-container {

    display: flex;


    align-items: center;


    justify-content: space-between;


    gap: 12px;


    margin-top: 12px;
}



.example-box {


    flex: 1;


    background: rgba(10,31,15,0.82);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);


    border:
        1px solid #374151;


    border-radius:
        var(--radius-md);


    padding: 12px;


    position: relative;


    white-space: pre-line;


    font-family: monospace;
}



.example-box.before {

    border-left:
        3px solid #ef4444;
}



.example-box.after {

    border-left:
        3px solid #22c55e;
}



.example-box .label {

    font-size: 12px;

    opacity: .6;

    margin-bottom: 6px;
}



.example-box .text {

    font-family: monospace;

    font-size: 14px;


    white-space: pre-line;
}



.arrow {

    font-size: 22px;

    opacity: .7;
}



/* ==========================================================
   BUTTON SYSTEM
========================================================== */


.icon-btn {
    width: clamp(34px, 3.5vw, 50px);
    height: clamp(34px, 3.5vw, 50px);

    border-radius: 12px;
    border: none;

    background: transparent;

    color: white;
    font-size: 20px;

    cursor: pointer;
    transition: .2s;

    display: flex;
    justify-content: center;
    align-items: center;
}



.icon-btn:hover {


    background: rgba(255,255,255,0.06);



    transform:
        translateY(-2px);


    box-shadow:
        0 4px 12px rgba(0,0,0,.3);
}



.icon-btn.close,
.panel-close {


    color:
        #ef4444;


    border-color:
        #ef4444;
}



.icon-btn.close:hover,
.panel-close:hover {


    background:
        rgba(239,68,68,.15);
}




/* ==========================================================
   CHAT & LOG
========================================================== */


#chatPanel {


    width: 100%;


    height: 140px;


    padding: 12px;
}



#gameLog {


    width: 100%;


    height: 260px;


    padding: 12px;


    display: flex;


    flex-direction: column;


    flex: 1;
}



#logEntries {


    flex: 1;


    overflow-y: auto;


    font-size: 12px;


    display: flex;


    flex-direction: column;


    gap: 6px;


    min-height: 0;
}



.log-entry {


    padding:
        6px 8px;


    background:
        rgba(255,255,255,.05);


    border-radius:
        8px;
}

.player-name{
    font-weight: 700;
}

.log-entry.p1 .player-name{
    color: var(--p1);
}

.log-entry.p2 .player-name{
    color: var(--p2);
}

.log-entry.p3 .player-name{
    color: var(--p3);
}

.log-entry.p4 .player-name{
    color: var(--p4);
}

/* ==========================================================
   KANGAROO MODAL
========================================================== */


.kangaroo-choice {

    width: min(350px, 100%);

    text-align:center;

}


.kangaroo-buttons {

    display:flex;

    justify-content:center;

    flex-wrap: wrap;

    gap:20px;

    margin-top:20px;

}



.kangaroo-buttons button {


    width: 120px;
    max-width: 40%;

    height:60px;


    border-radius:12px;


    border:1px solid var(--border);


    background:#0d1a0d;


    color:white;


    font-size:18px;


    cursor:pointer;


    transition:.2s;

}



.kangaroo-buttons button:hover {


    background:#132213;


    transform:translateY(-3px);

}


/* ==========================================================
   MOBILE MENU BASE STATE
========================================================== */


#mobileMenu,
#mobileTabs {

    display: none;
}

/* New elements (see the Landscape layout layer near the end of this
   file) — hidden by default same as #mobileTabs/#mobileLeaderboard
   above, and only shown inside the
   `(pointer: coarse) and (orientation: landscape)` layer. Without
   this base rule they'd render with default button/div display on
   Desktop and any other non-mobile context, since neither element
   existed before this file's other mobile-only rules were written. */
#leaderboardBtn, #railLogBtn, #railChatBtn, #mobileSideRail {

    display: none;
}

/* ==========================================================
   RESPONSIVE SYSTEM
   Single mobile breakpoint.
   Previous CSS had multiple duplicated 900px blocks.
========================================================== */







/* ==========================================================
   VERY SMALL DEVICES
   Optional fallback.
   Kept separate because it changes structure.
========================================================== */







/* ============================================================
   MOBILE-ONLY BUTTONS — hidden on desktop
============================================================ */

.mobile-only-btn {
    display: none;
}

/* ============================================================
   TABLET  (601px – 1024px)
============================================================ */

/* ============================================================
   TABLET  (601px – 1024px)
============================================================ */

@media (max-width: 1024px) and (min-width: 601px) {

    #pageLayout {
        grid-template-columns: 220px 1fr;
        gap: 12px;
        padding: 8px;
    }

    #leftSidebar { width: 220px; }

    #gameLayout {
        grid-template-columns: clamp(160px, 20vw, 260px) 1fr clamp(160px, 20vw, 260px);
        gap: 14px;
    }

    #topBarContent {
        height: clamp(70px, 12vw, 140px);
        grid-template-columns: clamp(100px, 18vw, 220px) 1fr clamp(100px, 18vw, 220px);
    }

    .turn-label  { font-size: clamp(13px, 2vw, 22px); }
    .round-label { font-size: clamp(11px, 1.6vw, 16px); }

    #queue .card, .queue-slot {
        width:  clamp(58px, 7.5vw, 96px);
        height: clamp(82px, 10.5vw, 135px);
    }

    #playerHand .card, .deck-back {
        width:  clamp(58px, 7vw, 90px);
        height: clamp(82px, 10vw, 126px);
    }

    #queue { gap: clamp(8px, 1.5vw, 20px); }

    #partyCards .card, #trashCards .card {
        width:  clamp(50px, 6vw, 80px);
        height: clamp(70px, 8.5vw, 110px);
    }

    #animalGrid {
        grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
        gap: 12px;
    }
}

/* ============================================================
   GLOBAL — mobile-only elements hidden on desktop
============================================================ */

/* mobile leaderboard: only shown inside the ≤600px block */
#mobileLeaderboard { display: none; }

/* mobile-only buttons hidden on desktop */
.mobile-only-btn { display: none; }

/* other-deck styled like player deck */
.other-deck { margin-top: 4px; display: flex; justify-content: center; }

.other-deck-back {
    position: relative;
    width:  clamp(32px, 5vw, 70px);
    height: clamp(45px, 7vw, 95px);
    border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,.4);
    border: 1px solid rgba(255,255,255,.2);
    overflow: hidden;
}

.other-deck-back::before {
    content: "";
}

.other-deck-count {
    position: relative; z-index: 1;
    font-size: clamp(12px, 3vw, 18px);
    font-weight: 800; color: #fff;
    text-shadow: 0 1px 4px rgba(0,0,0,.8);
}

.other-deck-back[data-player="p1"] { background: linear-gradient(145deg, var(--p1), #0d1a0d); }
.other-deck-back[data-player="p2"] { background: linear-gradient(145deg, var(--p2), #0d1a0d); }
.other-deck-back[data-player="p3"] { background: linear-gradient(145deg, var(--p3), #0d1a0d); }
.other-deck-back[data-player="p4"] { background: linear-gradient(145deg, var(--p4), #0d1a0d); }

/* ============================================================
   NEW FEATURES — Animations, Warning, Queue, End Game
============================================================ */

/* Warning popup */
#warningPopup {
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%,-50%) scale(0.9);
    background: rgba(10,31,15,0.95);
    backdrop-filter: blur(18px);
    border: 1px solid rgba(249,115,22,0.7);
    color: #fff;
    padding: 18px 28px;
    border-radius: var(--radius-md);
    font-size: 16px; font-weight: 600;
    z-index: 99999;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.25s ease, transform 0.25s ease;
    text-align: center;
    min-width: 220px;
    box-shadow: 0 8px 40px rgba(0,0,0,.7);
}
#warningPopup.visible {
    opacity: 1;
    transform: translate(-50%,-50%) scale(1);
}

/* Turn pulse — always the human seat's hand (p1), so it follows
   whatever color p1 is currently assigned via --p1-rgb. */
@keyframes turnPulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--p1-rgb), 0.7); }
    70%  { box-shadow: 0 0 0 10px rgba(var(--p1-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--p1-rgb), 0); }
}
#playerHand.my-turn .card { animation: turnPulse 1.5s infinite; cursor: pointer; }
#playerHand.my-turn .card:hover { transform: translateY(-8px) scale(1.06); }

/* Card enter */
@keyframes cardEnter {
    from { opacity: 0; transform: scale(0.7) translateY(12px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}
.card-enter { animation: cardEnter 0.32s cubic-bezier(.4,0,.2,1) forwards; }

/* ============================================================
   PRESENTATION LAYER — semantic-event animations
   (js/presentation/director.js + js/ui/game-ui.js presenter)
============================================================ */

/* Input lock: dim the hand while the Director is animating a turn, so
   it visually reads as "not interactive right now". Deliberately does
   NOT set pointer-events:none any more — that used to also block the
   hold-to-info long-press gesture (js/ui/longPress.js) any time it
   wasn't this player's turn (director.isBusy() is true for most of an
   opponent's turn), even though holding is meant to work regardless of
   whose turn it is. Actually preventing a card from being PLAYED
   mid-sequence is already handled in JS — see playThisCard()'s own
   director.isBusy() / isMyTurn checks in game-ui.js — so this class only
   needs to carry the visual "locked" look now. */
body.gameplay-locked #playerHand .card {
    opacity: 0.82;
    filter: saturate(0.85);
}

/* Small "joining the line" settle after a card lands at the back of the
   queue. */
@keyframes cardJoinsLine {
    0%   { transform: scale(1.08) translateY(-6px); }
    60%  { transform: scale(0.97) translateY(1px); }
    100% { transform: scale(1) translateY(0); }
}
.card-joins-line { animation: cardJoinsLine 0.24s cubic-bezier(.4,0,.2,1); }

/* Opponent card-back → real card reveal flip. */
@keyframes cardReveal {
    0%   { transform: rotateY(90deg) scale(0.92); opacity: 0.4; }
    100% { transform: rotateY(0deg) scale(1); opacity: 1; }
}
.card-reveal { animation: cardReveal 0.26s ease-out; }

/* Hippo pushing a weaker card backward — a "flinch and give ground"
   reaction, distinct from being sent to trash. */
@keyframes cardFleeReact {
    0%   { transform: translateX(0) rotate(0deg); }
    30%  { transform: translateX(-6px) rotate(-3deg); }
    70%  { transform: translateX(4px) rotate(2deg); }
    100% { transform: translateX(0) rotate(0deg); }
}
.card-flee-react { animation: cardFleeReact 0.22s ease-in-out; }
.card-fleeing { filter: brightness(0.92); }

/* Removal reaction — plays in place, just before the card leaves the
   queue for good. */
@keyframes cardRemovedReact {
    0%   { transform: scale(1) rotate(0deg); }
    25%  { transform: scale(0.92) rotate(-4deg); }
    50%  { transform: scale(1.03) rotate(3deg); }
    100% { transform: scale(0.94) rotate(0deg); opacity: 0.75; }
}
.card-removed-react { animation: cardRemovedReact 0.26s ease-in-out forwards; }

/* Crocodile's bite — sharper, quicker snap than a generic removal. */
@keyframes cardEatenReact {
    0%   { transform: scale(1); }
    30%  { transform: scale(0.8) rotate(-6deg); }
    60%  { transform: scale(1.05) rotate(4deg); }
    100% { transform: scale(0.7); opacity: 0.5; }
}
.card-eaten-react { animation: cardEatenReact 0.26s ease-in forwards; }

/* Flight toward Trash: shrink + desaturate as it travels. */
.card-to-trash { filter: grayscale(0.6) brightness(0.85); opacity: 0.85; }

@keyframes cardInTrash {
    0%   { transform: scale(1); opacity: 0.85; }
    100% { transform: scale(0.94); opacity: 1; }
}
.card-in-trash { animation: cardInTrash 0.22s ease-out forwards; }

/* Queue-resolution "result" cards — anticipation before the trip to
   Party. */
@keyframes cardResultAnticipation {
    0%   { transform: scale(1) translateY(0); }
    30%  { transform: scale(0.94) translateY(3px); }
    70%  { transform: scale(1.12) translateY(-8px) rotate(-2deg); }
    100% { transform: scale(1.08) translateY(-2px) rotate(0deg); }
}
.card-result-anticipation { animation: cardResultAnticipation 0.26s cubic-bezier(.34,1.4,.64,1) forwards; }

.card-to-party { filter: drop-shadow(0 0 14px rgba(250, 204, 21, 0.55)); }

@keyframes cardPartyCelebrate {
    0%   { transform: scale(1.1) rotate(-3deg); }
    30%  { transform: scale(0.95) rotate(2deg); }
    55%  { transform: scale(1.06) rotate(-1deg); }
    100% { transform: scale(1) rotate(0deg); }
}
.card-party-celebrate {
    animation: cardPartyCelebrate 0.42s cubic-bezier(.34,1.2,.64,1);
    box-shadow: 0 0 0 3px rgba(250, 204, 21, 0.35), var(--shadow-card);
}

/* Queue-full pause beat. */
@keyframes queueFullFlash {
    0%   { box-shadow: 0 0 0 0 rgba(250, 204, 21, 0.65); }
    50%  { box-shadow: 0 0 0 14px rgba(250, 204, 21, 0); }
    100% { box-shadow: 0 0 0 0 rgba(250, 204, 21, 0); }
}
.queue-full-flash { animation: queueFullFlash 0.7s ease-out; }

/* ── Ability-specific visual language ──────────────────────────
   Each animal's rule gets its own motion flavor so the *shape* of the
   animation hints at what happened, not just that something happened. */

/* Lion — aggressive rush to the front: a low, fast dash with a hard
   ease-in, not a polite slide. */
.card-lion-rush { filter: drop-shadow(0 0 10px rgba(239, 68, 68, 0.45)); }
@keyframes cardLionRushTilt {
    0%   { transform: rotate(0deg) scale(1); }
    40%  { transform: rotate(-3deg) scale(1.04); }
    100% { transform: rotate(0deg) scale(1); }
}
.card-lion-rush.card-lion-rush { animation: cardLionRushTilt 0.32s ease-out; }

/* Hippo — a heavy, slower shove; the displaced card resists a touch on
   its way out of the way. */
.card-heavy-push { filter: brightness(0.97); }
@keyframes cardHeavyPushSquash {
    0%   { transform: scaleX(1) scaleY(1); }
    35%  { transform: scaleX(1.08) scaleY(0.94); }
    100% { transform: scaleX(1) scaleY(1); }
}
.card-heavy-push.card-heavy-push { animation: cardHeavyPushSquash 0.46s ease-out; }

/* Giraffe — one crisp little hop over its neighbor. */
@keyframes cardHop {
    0%   { transform: translateY(0) scale(1); }
    45%  { transform: translateY(-14px) scale(1.03); }
    100% { transform: translateY(0) scale(1); }
}
.card-hop.card-hop { animation: cardHop 0.3s cubic-bezier(.34,1.4,.64,1); }

/* Sloth Bear — sticks close behind whoever it's following: a tight,
   short snap rather than a free slide. */
@keyframes cardStick {
    0%   { transform: scale(0.96); }
    100% { transform: scale(1); }
}
.card-stick.card-stick { animation: cardStick 0.22s ease-out; }

/* Sloth Bear being pushed — resists for a beat ("sticky"), then drags
   along, distinct from a card that simply gives ground. */
@keyframes cardStickyReact {
    0%   { transform: translateX(0); }
    50%  { transform: translateX(-3px); }
    100% { transform: translateX(0); }
}
.card-sticky-react { animation: cardStickyReact 0.24s ease-in-out 2; }
.card-sticky-drag { filter: brightness(0.95); }

/* Kangaroo's jump — a bigger hop arc than a plain slide. */
@keyframes cardJumpArc {
    0%   { transform: translateY(0) scale(1) rotate(0deg); }
    40%  { transform: translateY(-30px) scale(1.06) rotate(-4deg); }
    100% { transform: translateY(0) scale(1) rotate(0deg); }
}
.card-jump-arc {
    animation: cardJumpArc 0.46s cubic-bezier(.34,1.2,.64,1);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
}

/* Snake's sort — a small chaotic wiggle while cards cross paths at once. */
@keyframes cardChaosMove {
    0%   { transform: rotate(0deg); }
    25%  { transform: rotate(4deg); }
    60%  { transform: rotate(-3deg); }
    100% { transform: rotate(0deg); }
}
.card-chaos-move.card-chaos-move {
    animation: cardChaosMove 0.38s ease-in-out;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.4);
}

/* Seal's reversal — a dramatic full flip mid-flight. */
@keyframes cardReverseFlip {
    0%   { transform: rotateY(0deg); }
    50%  { transform: rotateY(180deg); }
    100% { transform: rotateY(360deg); }
}
.card-reverse-flip.card-reverse-flip {
    animation: cardReverseFlip 0.48s ease-in-out;
    box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.4);
}

/* A firm, non-moving "block" reaction — Zebra stopping Hippo/Crocodile,
   or a Lion holding its ground against a second Lion. */
@keyframes cardBlockReact {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.08); }
    55%  { transform: scale(0.97); }
    100% { transform: scale(1); }
}
.card-block-react {
    animation: cardBlockReact 0.24s ease-out;
    box-shadow: 0 0 0 3px rgba(148, 163, 184, 0.5);
}

/* Crocodile's satisfied recoil after eating. */
@keyframes cardCrocRecoil {
    0%   { transform: scale(1) rotate(0deg); }
    30%  { transform: scale(1.1) rotate(3deg); }
    60%  { transform: scale(0.96) rotate(-2deg); }
    100% { transform: scale(1) rotate(0deg); }
}
.card-croc-recoil { animation: cardCrocRecoil 0.26s ease-out; }

/* Scared off (Lion's Monkeys, Monkey pair vs Crocodile/Hippo) — a
   jittery flinch, faster and sharper than an ordinary "outmatched"
   removal. */
@keyframes cardScaredReact {
    0%   { transform: translate(0,0) rotate(0deg); }
    20%  { transform: translate(-3px,-2px) rotate(-5deg); }
    40%  { transform: translate(3px,1px) rotate(4deg); }
    60%  { transform: translate(-2px,0) rotate(-3deg); }
    100% { transform: translate(0,0) rotate(0deg); opacity: 0.75; }
}
.card-scared-react { animation: cardScaredReact 0.24s ease-in-out forwards; }

/* Bounced off another Lion — a firm recoil-back rather than fleeing or
   being outmatched. */
@keyframes cardBlockedOutReact {
    0%   { transform: translateX(0) scale(1); }
    30%  { transform: translateX(6px) scale(0.95); }
    100% { transform: translateX(-4px) scale(0.9); opacity: 0.75; }
}
.card-blocked-out-react { animation: cardBlockedOutReact 0.26s ease-out forwards; }

/* ── Anticipation: the wind-up beat before an ability's main action ─── */
@keyframes cardAnticipateRush {
    0%   { transform: translateX(0) scaleX(1); }
    100% { transform: translateX(-4px) scaleX(0.93); }
}
.card-anticipate-rush { animation: cardAnticipateRush 0.18s ease-in forwards; }

@keyframes cardAnticipatePush {
    0%   { transform: scaleX(1); }
    100% { transform: scaleX(0.9) translateX(-3px); }
}
.card-anticipate-push { animation: cardAnticipatePush 0.2s ease-in forwards; }

@keyframes cardAnticipateBite {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.06); }
    100% { transform: scale(1.02); }
}
.card-anticipate-bite {
    animation: cardAnticipateBite 0.22s ease-in-out forwards;
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.4);
}

@keyframes cardAnticipateJump {
    0%   { transform: translateY(0) scaleY(1); }
    100% { transform: translateY(4px) scaleY(0.85); }
}
.card-anticipate-jump { animation: cardAnticipateJump 0.18s ease-in forwards; }

@keyframes cardAnticipateShimmer {
    0%   { transform: rotate(0deg); }
    33%  { transform: rotate(3deg); }
    66%  { transform: rotate(-3deg); }
    100% { transform: rotate(0deg); }
}
.card-anticipate-reverse, .card-anticipate-sort { animation: cardAnticipateShimmer 0.2s ease-in-out; }

@keyframes cardAnticipateHop {
    0%   { transform: translateY(0) scaleY(1); }
    100% { transform: translateY(-3px) scaleY(1.08); }
}
.card-anticipate-hop { animation: cardAnticipateHop 0.12s ease-out forwards; }

@keyframes cardAnticipateGeneric {
    0%   { transform: scale(1); }
    100% { transform: scale(1.03); }
}
.card-anticipate-generic { animation: cardAnticipateGeneric 0.15s ease-out forwards; }

/* Kangaroo hopping over a card — a light "duck" flash, not a full
   reaction, so a 2-card jump doesn't feel heavier than a 1-card one. */
@keyframes cardHoppedOver {
    0%   { transform: scaleY(1); }
    50%  { transform: scaleY(0.92); }
    100% { transform: scaleY(1); }
}
.card-hopped-over { animation: cardHoppedOver 0.22s ease-in-out; }

/* Monkey troop banding together before scaring something off. */
@keyframes cardMonkeyGroup {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.08); }
    100% { transform: scale(1); }
}
.card-monkey-group { animation: cardMonkeyGroup 0.2s ease-in-out; }

/* Temporarily dim everything an ability isn't touching, so the eye goes
   straight to what matters. */
.card.queue-dimmed {
    opacity: 0.4;
    filter: grayscale(0.4);
    transition: opacity 0.2s ease, filter 0.2s ease;
}

/* Confetti burst over the queue when it fills up. */
.confetti-layer {
    position: fixed;
    pointer-events: none;
    overflow: visible;
    z-index: 9998;
}
.confetti-piece {
    position: absolute;
    top: 40%;
    width: 7px;
    height: 12px;
    border-radius: 2px;
    opacity: 0.95;
    animation: confettiFall 0.85s ease-in forwards;
}
@keyframes confettiFall {
    0%   { transform: translateY(0) rotate(0deg); opacity: 1; }
    100% { transform: translateY(90px) rotate(340deg); opacity: 0; }
}

/* Reduced motion: keep the semantic sequence (each step still shows up,
   see js/presentation/flip.js), just drop the flourish. */
@media (prefers-reduced-motion: reduce) {
    .card-joins-line, .card-reveal, .card-jump-arc, .card-flee-react,
    .card-removed-react, .card-eaten-react, .card-in-trash,
    .card-result-anticipation, .card-party-celebrate, .queue-full-flash,
    .card-lion-rush, .card-heavy-push, .card-hop, .card-stick,
    .card-sticky-react, .card-chaos-move, .card-reverse-flip,
    .card-block-react, .card-croc-recoil, .card-scared-react,
    .card-blocked-out-react,
    .card-anticipate-rush, .card-anticipate-push, .card-anticipate-bite,
    .card-anticipate-jump, .card-anticipate-reverse, .card-anticipate-sort,
    .card-anticipate-hop, .card-anticipate-generic, .card-hopped-over,
    .card-monkey-group {
        animation: none !important;
    }
    .card.queue-dimmed { transition: none; }
    .confetti-layer { display: none; }
}

/* Guidance prompt (asked once per new game, before it starts) */
.guide-prompt-actions {
    display: flex;
    gap: 12px;
    margin-top: 20px;
    flex-wrap: wrap;
    justify-content: center;
}
.guide-prompt-no {
    background: rgba(255,255,255,0.08);
    color: inherit;
}
.guide-prompt-dontshow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 16px;
    font-size: 0.85rem;
    opacity: 0.75;
    cursor: pointer;
    user-select: none;
}
.guide-prompt-dontshow input {
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: var(--accent);
}

/* ============================================================
   CONTEXTUAL CARD GUIDANCE
   (js/ui/cardGuidance-ui.js — popup shown after a played card's ability
   resolves, explaining that specific ability with the real before/after
   queue.)
============================================================ */

.guide-modal-content {
    width: min(480px, 92vw);
    text-align: left;
}
[dir="rtl"] .guide-modal-content { text-align: right; }

.guide-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 10px;
}

.guide-visual-img {
    width: 64px;
    height: 64px;
    object-fit: contain;
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.06);
}
.guide-visual-emoji { font-size: 40px; line-height: 1; }

.guide-title-block h3 { margin: 0 0 2px; font-size: 18px; }
.guide-ability-title {
    font-size: 13px;
    font-weight: 700;
    opacity: 0.75;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.guide-desc {
    font-size: 14px;
    line-height: 1.55;
    opacity: 0.92;
    margin: 6px 0 16px;
}

.guide-diagram {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 18px;
}

.guide-queue-block {
    flex: 1 1 140px;
    min-width: 120px;
}

.guide-queue-label {
    font-size: 11px;
    opacity: 0.6;
    margin-bottom: 6px;
    text-align: center;
}

.guide-queue-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
    min-height: 44px;
}

.guide-queue-empty {
    opacity: 0.4;
    font-size: 12px;
}

.guide-diagram-arrow {
    font-size: 20px;
    opacity: 0.5;
    flex: 0 0 auto;
}
[dir="rtl"] .guide-diagram-arrow { transform: scaleX(-1); }

.guide-chip {
    position: relative;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow: visible;
}
.guide-chip-img { width: 26px; height: 26px; object-fit: contain; }
.guide-chip-emoji { font-size: 18px; line-height: 1; }
.guide-chip-power {
    position: absolute;
    bottom: -4px;
    right: -4px;
    font-size: 9px;
    font-weight: 700;
    background: var(--accent, #22c55e);
    color: #06210c;
    border-radius: 50%;
    width: 15px;
    height: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.guide-chip-badge {
    position: absolute;
    top: -8px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 12px;
}

.guide-chip-affected { border-width: 2px; }
.guide-chip-removed  { border-color: #ef4444; box-shadow: 0 0 0 2px rgba(239,68,68,0.35); }
.guide-chip-jumped   { border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59,130,246,0.35); }
.guide-chip-escaped  { border-color: #eab308; box-shadow: 0 0 0 2px rgba(234,179,8,0.35); }
.guide-chip-none     { border-color: #facc15; box-shadow: 0 0 0 2px rgba(250,204,21,0.35); }

.guide-destination { flex-basis: 100%; }
.guide-destination .guide-queue-row { justify-content: flex-start; }

.guide-continue-btn { width: 100%; margin-top: 4px; }

@media (max-width: 600px) {
    .guide-modal-content { padding: 18px; }
    .guide-visual-img, .guide-visual-emoji { width: 48px; height: 48px; }
    .guide-chip { width: 34px; height: 34px; }
    .guide-diagram { gap: 6px; }
    .guide-queue-block { flex-basis: 100%; }
    .guide-diagram-arrow { flex-basis: 100%; text-align: center; transform: rotate(90deg); }
    [dir="rtl"] .guide-diagram-arrow { transform: rotate(90deg) scaleX(-1); }
}

.guide-continue-btn:focus-visible,
#stepGuidanceToggle:focus-visible + .switch-track {
    outline: 2px solid var(--accent, #22c55e);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .guide-reduced-motion .guide-chip { transition: none !important; }
}

/* Slot numbers */
.slot-number {
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%,-50%);
    font-size: clamp(22px, 4cqw, 44px); font-weight: 900;
    color: rgba(255,255,255,0.07);
    pointer-events: none; user-select: none; z-index: 0;
}
.queue-slot { position: relative; }

/* Queue flanking icons */
#queueWithIcons {
    display: flex; align-items: center;
    gap: clamp(8px, 1.5vw, 20px);
    justify-content: center; width: 100%;
}
#queueInner { flex: 1; display: flex; justify-content: center; }
#queueInner #queue { display: flex; gap: clamp(6px, 2vw, 30px); }
/* Queue flanking icons (Party door / Trash exit) — Mobile Landscape
   only. `display: none` here (not `visibility: hidden`, which would
   still reserve their space) is the default for every OTHER viewport,
   including Desktop; the `@media (pointer: coarse) and (orientation:
   landscape)` block further down re-enables them for touch+landscape
   only. #queueWithIcons is a `justify-content: center` flex row with
   #queueInner (flex: 1) already doing the actual Queue centering, so
   with these two hidden the row just naturally reflows around the
   Queue alone — no gap, no extra CSS needed for Desktop specifically.
   The underlying elements, their click/keyboard wiring (js/ui/
   mobile-ui.js), and the Party/Trash popups themselves are all
   untouched — Mobile Landscape still gets exactly the same
   interaction it always did. */
.queue-icon { display: none; font-size: clamp(24px, 4vw, 52px); line-height: 1; flex-shrink: 0; opacity: 0.85; cursor: pointer; }

/* End game — sizing/scroll/footer-pinning comes from the shared
   .screen-content--panel rules; this just supplies the visual "card"
   chrome (background/blur/border/shadow) on top of that. */
#endGameScreen .screen-content {
    max-width: 480px; width: min(480px, 90vw);
    max-height: 85vh;
    max-height: 85dvh;
    background: rgba(10,31,15,0.92);
    backdrop-filter: blur(18px);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: var(--radius-lg);
    box-shadow: 0 20px 60px rgba(0,0,0,.6);
}
#endGameScreen .screen-panel-header { padding-top: 28px; }
#endGameScreen .screen-panel-footer { border-top: none; background: transparent; padding-bottom: max(20px, env(safe-area-inset-bottom)); }
#endGameTitle { font-size: clamp(28px, 7vw, 48px); margin: 0 0 8px; }
#endGameText  { font-size: clamp(14px, 3vw, 18px); opacity: 0.8; margin: 0 0 4px; }

.final-score-header, .final-score-row {
    display: grid;
    grid-template-columns: 40px 1fr 70px 70px;
    gap: 8px; padding: 10px 12px; align-items: center; font-size: 14px;
}
.final-score-header {
    background: rgba(255,255,255,0.08); border-radius: var(--radius-sm);
    font-weight: 700; font-size: 12px; text-transform: uppercase;
    letter-spacing: 0.5px; color: var(--text-muted); margin-bottom: 6px;
}
.final-score-row { border-radius: var(--radius-sm); transition: background 0.2s; }
.final-score-row:nth-child(even) { background: rgba(255,255,255,0.04); }
.final-score-row.winner-row {
    background: rgba(59,130,246,0.18);
    border: 1px solid rgba(59,130,246,0.4);
}
.rank-badge  { font-size: 18px; }
.power-score { color: #fbbf24; font-weight: 700; }
.party-count { color: #86efac; font-weight: 600; }

/* End game — primary actions (Play Again / Return to Home).
   Two buttons with clear visual hierarchy: Play Again is the filled,
   higher-emphasis primary action; Return to Home is the outlined
   secondary action. Row layout on desktop/tablet/mobile-landscape
   (the only orientation game.html is ever shown in — see the
   Orientation Gate), stacking only as a narrow-viewport fallback. */
.endgame-actions {
    display: flex;
    width: 100%;
    gap: 12px;
    margin-top: 0;
    flex-wrap: wrap;
    justify-content: center;
}

.endgame-actions .screen-btn {
    margin-top: 0;
    flex: 1 1 160px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 50px;
    box-sizing: border-box;
}

.endgame-btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    font-size: 18px;
    line-height: 1;
    flex-shrink: 0;
}
.endgame-btn-icon .icon-image { width: 100%; height: 100%; object-fit: contain; }

.endgame-btn-primary {
    background: var(--accent);
    color: #fff;
    box-shadow: 0 8px 20px rgba(189, 93, 56, 0.35);
}
.endgame-btn-primary:hover  { filter: brightness(1.08); }
.endgame-btn-primary:active { filter: brightness(0.96); }

.endgame-btn-secondary {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-main);
    border: 1px solid rgba(255, 255, 255, 0.2);
}
.endgame-btn-secondary:hover  { background: rgba(255, 255, 255, 0.14); }
.endgame-btn-secondary:active { background: rgba(255, 255, 255, 0.06); }

@media (max-width: 420px) {
    .endgame-actions { flex-direction: column; }
    .endgame-actions .screen-btn { width: 100%; }
}

/* Help */
.help-tip {
    background: rgba(255,255,255,0.06);
    border-left: 3px solid var(--accent);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    padding: 10px 14px; margin-top: 18px;
    font-size: 13px; line-height: 1.5; color: var(--text-muted);
}
.help-text {
    font-size: 14px; line-height: 1.7; color: var(--text-muted);
    background: rgba(255,255,255,0.04);
    border-radius: var(--radius-sm); padding: 14px 16px; margin-bottom: 20px;
}

/* Party/Trash: hover no longer enlarges the card — these piles are
   read-only history, not playable/selectable, so a hover lift implied
   an interactivity that wasn't there. Hold-to-show-help (see
   js/ui/longPress.js) is the only interaction left on these cards, and
   it already has its own long-press-active visual feedback. */
#partyCards .card:hover, #trashCards .card:hover {
    transform: none;
    box-shadow: var(--shadow-card);
    z-index: auto;
    cursor: default;
}
#partyCards, #trashCards { overflow: visible; }

/* ============================================================
   MOBILE  (≤ 600px)  — single unified block
============================================================ */

@media (max-width: 600px) {

    /* ── Show mobile-only buttons ── */
    .mobile-only-btn { display: flex; }

    /* ── Hide leaderboard button (inline version used) ── */
    #leaderboardBtn  { display: none !important; }

    /* ── Layout ── */
    #pageLayout    { display: block; padding: 0; }
    #leftSidebar   { display: none; }
    #gameColumn    { display: flex; flex-direction: column; min-height: 100dvh; }

    /* ── Top bar: logo top-center, left=turn/round, right=buttons ── */
    #topBar {
        position: sticky; top: 0; z-index: 100;
        background: var(--bg-main); margin-bottom: 0;
    }

    #topBarContent {
        display: grid !important;
        grid-template-areas:
            "logo  logo"
            "left  right" !important;
        grid-template-columns: 1fr auto !important;
        grid-template-rows: auto auto !important;
        height: auto !important;
        padding: 8px 12px 6px !important;
        gap: 4px 0;
    }

    #topCenter {
        grid-area: logo !important;
        justify-self: center;
        display: flex; justify-content: center; align-items: center;
    }

    #topCenter picture img {
        height: clamp(44px, 14vw, 72px) !important;
        width: auto; object-fit: contain;
    }

    #topLeft {
        grid-area: left !important;
        display: flex; flex-direction: column;
        justify-content: center; align-items: flex-start;
        gap: 2px; padding: 0 !important;
    }

    .turn-label  { font-size: clamp(10px, 2.8vw, 14px) !important; }
    .round-label { font-size: clamp(9px, 2.4vw, 12px)  !important; }
    .turn-timer-label { font-size: clamp(9px, 2.4vw, 12px) !important; }
    .turn-divider { display: none; }

    #topRight {
        grid-area: right !important;
        display: flex; align-items: center;
        gap: 5px !important; padding: 0 !important;
    }

    .top-btn {
        width:  clamp(28px, 8vw, 36px) !important;
        height: clamp(28px, 8vw, 36px) !important;
        font-size: 13px;
    }

    /* ── gameLayout: flex column, controlled order ── */
    #gameLayout {
        display: flex !important;
        flex-direction: column;
        flex: 1; gap: 0;
        padding-bottom: 120px;
    }

    /* ── ORDER: leaderboard → otherPlayers → tabs → queue → hand ── */
    #mobileLeaderboard { order: 0; }
    #otherPlayers      { order: 1; }
    #mobileTabs        { order: 2; }
    #centerArea        { order: 3; }

    /* ── Inline leaderboard ── */
    #mobileLeaderboard {
        display: block !important;
        margin: 6px 12px;
        padding: 8px 10px;
        background: rgba(255,255,255,0.05);
        border-radius: var(--radius-sm);
        box-sizing: border-box;
    }

    #mobileLeaderboard h4 {
        font-size: 11px; font-weight: 700;
        letter-spacing: 0.5px; color: var(--text-muted);
        text-transform: uppercase; margin: 0 0 6px;
    }

    #mobileLeaderboard .leaderboard-row {
        display: grid;
        column-gap: 14px; 
        font-size: 12px;
        padding: 4px 0;
        border-bottom: 1px solid rgba(255,255,255,0.05);
    }

    /* ── Other players ── */
    #otherPlayers {
        display: flex; flex-direction: column;
        align-items: center; gap: 4px;
        padding: 0 12px; margin-bottom: 4px;
    }

    #topPlayer, #leftPlayer, #rightPlayer {
        display: flex; flex-direction: row;
        align-items: center; gap: 8px;
        width: 100%;
    }

    #sidePlayers {
        display: flex; flex-direction: column;
        align-items: center; gap: 4px; width: 100%;
    }

    .player-label { font-size: 11px; white-space: nowrap; }
        .other-hand   { gap: 3px; display: flex; }

    /* player's own hand card-back */
    .card-back {
        width:  clamp(44px, 12vw, 64px) !important;
        height: clamp(62px, 17vw, 90px) !important;
    }

    /* opponent hand cards: fixed small px, independent of viewport */
    .other-hand .card-back {
        width:  24px !important;
        height: 34px !important;
    }

    .other-deck-back {
        width:  clamp(44px, 12vw, 64px) !important;
        height: clamp(62px, 17vw, 90px) !important;
    }

    .other-deck-count { font-size: clamp(12px, 4vw, 18px); }

    /* ── mobileTabs (Party / Trash) ── */
    #mobileTabs {
        display: flex; gap: 8px;
        justify-content: center;
        padding: 6px 12px 4px;
    }

    #partyTab, #trashTab {
        flex: 1; padding: 7px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: #0d1a0d; color: white;
        cursor: pointer; transition: .2s; font-size: 13px;
    }
    #partyTab:hover, #trashTab:hover { background: #132213; }
    #partyTab.active, #trashTab.active {
        border-color: var(--accent);
        background: rgba(189,93,56,.2);
    }

    /* ── Party / Trash popup ──
       Same stretched-box issue as the Mobile Landscape version of
       this popup below (see that rule's long comment for the full
       root-cause explanation) — `top`/`bottom` here define the
       maximum band on a narrow window, not a forced size, so
       `margin: auto 0` centers the shrink-to-fit box instead of
       stretching it and leaving all the slack below the content.
       This rule is a `max-width: 600px` (not landscape-specific)
       leftover from before the Mobile Landscape layer existed; touch
       portrait is gated behind a rotate-to-landscape overlay (see
       js/ui/orientation-ui.js), so in practice this only reaches a
       narrow *non-touch* desktop window — included for consistency
       since it's the same component and same bug, not because it's
       one of this fix's required test sizes. */
    #partyArea, #trashArea {
        display: none;
        position: fixed;
        top: 20px; left: 12px; right: 12px; bottom: 20px;
        margin: auto 0;
        z-index: 3000;
        background: rgba(10,31,15,0.92);
        backdrop-filter: blur(18px);
        border-radius: var(--radius-lg);
        padding: 16px;
        box-shadow: 0 20px 60px rgba(0,0,0,.6);
        overflow-y: auto;
    }
    #partyArea.mobile-open, #trashArea.mobile-open {
        display: flex; flex-direction: column;
    }
    body.popup-open { overflow: hidden; }

    /* ── centerArea ── */
    #centerArea {
        display: flex; flex-direction: column;
        flex: 1; align-items: center;
        padding: 6px 0 0; min-height: 0;
    }

    /* ── Queue ── */
    #queueArea {
        display: flex; flex-direction: column;
        align-items: center; gap: 6px;
        width: 100%; padding: 0 12px; box-sizing: border-box;
    }

    #queue {
        display: flex; flex-wrap: nowrap;
        overflow-x: auto; justify-content: center;
        width: 100%; gap: 5px;
        scrollbar-width: none; padding: 4px 0; box-sizing: border-box;
    }
    #queue::-webkit-scrollbar { display: none; }

    #queue .card, .queue-slot {
        flex: 0 0 auto;
        width:  clamp(52px, 14vw, 80px);
        height: clamp(74px, 20vw, 114px);
    }

    /* ── Hand: pinned to bottom ── */
    #handArea {
        position: fixed; bottom: 0; left: 0; right: 0;
        z-index: 50;
        background: var(--bg-main);
        border-top: 1px solid var(--border);
        padding: 8px 12px 16px !important;
        display: flex; justify-content: center;
        align-items: center; gap: clamp(6px, 2vw, 14px);
        box-sizing: border-box;
    }

    #playerHand {
        display: flex; justify-content: center;
        gap: clamp(4px, 1.5vw, 8px);
        flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    }
    #playerHand::-webkit-scrollbar { display: none; }

    #playerHand .card {
        flex: 0 0 auto;
        width:  clamp(50px, 13vw, 70px);
        height: clamp(70px, 18vw, 98px);
    }

    #deckStack { flex-shrink: 0; }
    .deck-back {
        width:  clamp(50px, 13vw, 70px);
        height: clamp(70px, 18vw, 98px);
    }
    #deckCount { font-size: clamp(16px, 5vw, 26px); }

    /* ── General card ── */
    .card {
        width:  clamp(52px, 14vw, 80px);
        height: clamp(74px, 20vw, 114px);
    }

    /* ── Party/Trash cards bigger ── */
    #partyCards .card, #trashCards .card {
        width:  62px !important;
        height: 86px !important;
    }

    /* ── Mobile popups: bottom-sheet, not a shrunken centered card ──
       Every .modal (Settings, Profile, Card Guide, About, Lucky Wheel,
       Feedback, Tutorial, Log, card detail, etc.) shares one popup
       shell (see the base .modal-content rules above), so this single
       override upgrades all of them at once instead of each screen
       inventing its own mobile treatment — see docs "MOBILE POPUPS" /
       "VISUAL DESIGN SYSTEM". Anchored to the bottom edge, full width,
       rounded only on top, sized to content up to ~92dvh so a short
       popup (e.g. the Lucky Wheel placeholder) doesn't stretch to fill
       the screen. Internal header/scroll-body/footer structure
       (.modal-content:has(.modal-body) etc., set above) is unchanged —
       only the outer shell's position/shape changes here. */
    .modal {
        align-items: flex-end !important;
    }

    .modal-content {
        width: 100% !important;
        max-width: 100% !important;
        max-height: 92dvh !important;
        margin: 0 !important;
        border-radius: 20px 20px 0 0 !important;
        border-left: none;
        border-right: none;
        border-bottom: none;
        box-sizing: border-box;
        animation: modalSheetUp .28s cubic-bezier(.4,0,.2,1);
        /* Small top handle affordance, like a native bottom sheet —
           purely decorative, no layout impact on the header below it. */
        position: relative;
    }

    /* Safe-area bottom padding only for modals using the plain
       (no .modal-body/.tut-footer) scaffold — the header/body/footer
       and tutorial layouts already add their own safe-area-aware
       bottom padding on their footer, so adding it here too would
       double up empty space below their buttons. */
    .modal-content:not(:has(.modal-body)):not(.tut-panel) {
        padding-bottom: max(20px, env(safe-area-inset-bottom)) !important;
    }

    .modal-content::before {
        content: "";
        position: absolute;
        top: 8px;
        left: 50%;
        transform: translateX(-50%);
        width: 36px;
        height: 4px;
        border-radius: 999px;
        background: rgba(255, 255, 255, 0.25);
        pointer-events: none;
    }

    /* Give the handle breathing room without shifting every modal's
       existing header/body padding values individually. */
    .modal-content > .modal-header,
    .modal-content > .modal-form > .modal-header,
    .modal-content .tut-header {
        padding-top: 22px !important;
    }

    @keyframes modalSheetUp {
        from { transform: translateY(24px); opacity: 0; }
        to   { transform: translateY(0);    opacity: 1; }
    }

    @media (prefers-reduced-motion: reduce) {
        .modal-content { animation: none; }
    }

    /* ── Help grid ── */
    #animalGrid {
        grid-template-columns: repeat(3, 1fr) !important;
        gap: 8px !important;
    }
    .card-info {
        width: 100% !important;
        height: auto !important;
        aspect-ratio: 3/4;
    }

    /* ── Warning popup ── */
    #warningPopup {
        font-size: 14px !important;
        padding: 14px 20px !important;
        min-width: 180px;
        z-index: 99999 !important;
    }
}

/* ============================================================
   VERY SMALL  (≤ 380px)
============================================================ */

@media (max-width: 380px) {

    /* Was 26px — under any reasonable touch-target minimum. Shrinking
       the icon's own font-size (not just relying on the button box)
       keeps 5+ icons fitting in a tight top bar while still giving
       each a real ~32px tappable box instead of a 26px one. */
    .top-btn { width: 32px !important; height: 32px !important; font-size: 12px; }
    #topRight { gap: 2px !important; }

    #gameLayout { padding-bottom: 100px; }

    #playerHand .card, .deck-back {
        width:  clamp(44px, 16vw, 58px);
        height: clamp(62px, 22vw, 82px);
    }

    #queue .card, .queue-slot {
        width:  clamp(44px, 16vw, 60px);
        height: clamp(62px, 22vw, 84px);
    }
}

/* ============================================================
   DIFFICULTY MODAL
============================================================ */

/* ── Reusable Header / Scroll / Fixed-Footer panel ───────────
   Opt-in modifier for any .screen-content whose primary action must
   never be allowed to scroll out of reach (Choose Bot Difficulty,
   End Game today). Structure:
     .screen-content.screen-content--panel
       .screen-panel-header   (title/back — flex-shrink:0)
       .screen-panel-scroll   (everything else — flex:1, scrolls)
       .screen-panel-footer   (primary action(s) — flex-shrink:0,
                                always visible, safe-area aware)
   Overrides the plain .screen-content center/scroll-the-whole-thing
   behavior above: here the *panel* scrolls internally instead. */
.screen-content--panel {
    justify-content: flex-start;
    align-items: stretch;
    padding: 0;
    overflow: hidden;
    max-width: 480px;
    width: min(480px, 94vw);
    margin: 0 auto;
}

.screen-panel-header {
    flex: 0 0 auto;
    padding: max(18px, env(safe-area-inset-top)) 24px 4px;
    text-align: center;
}

.screen-panel-header .page-back-link {
    /* .screen-panel-header is text-align:center (for the title below
       it); keep the back link itself left-aligned by making it a
       block-level flex row instead of relying on align-self, which
       only works inside a flex/grid parent. */
    display: flex;
    text-align: left;
    margin-bottom: 6px;
}

.screen-panel-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 12px 24px 20px;
}

.screen-panel-footer {
    flex: 0 0 auto;
    padding: 14px 24px calc(14px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    background: rgba(0, 0, 0, 0.18);
}

.screen-panel-footer .screen-btn {
    width: 100%;
    margin-top: 0;
}

/* Landscape phones (short viewport height): tighten vertical spacing
   so the header/footer leave the scroll area real room instead of
   eating most of a ~360-430px-tall viewport. */
@media (max-height: 480px) and (orientation: landscape) {
    .screen-panel-header { padding-top: max(10px, env(safe-area-inset-top)); padding-bottom: 2px; }
    .screen-panel-scroll { padding-top: 8px; padding-bottom: 10px; }
    .screen-panel-footer { padding-top: 8px; padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
}

.screen-panel-header h2 {
    font-size: clamp(20px, 5vw, 32px);
    margin: 0 0 6px;
}

/* .difficulty-content: still used by game-modes.html's inline
   difficulty section (#difficultyPanelSection) — currently an
   orphaned/unreachable page per index.html's own architecture notes
   (Home goes straight to bot-difficulty.html), kept working rather
   than redesigned since nothing links to it today. bot-difficulty.html
   itself now uses .screen-content--panel + .screen-panel-* instead
   (see above) for the pinned-footer Play button fix. */
.difficulty-content {
    max-width: 480px;
    width: 90vw;
    padding: 20px 28px 28px;
}

.diff-subtitle {
    color: var(--text-muted);
    font-size: 14px;
    margin: 0 0 20px;
}

#difficultyPanel { display: flex; flex-direction: column; gap: 14px; }

.bot-row {
    display: flex;
    align-items: center;
    gap: 16px;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: var(--radius-md);
    padding: 14px 16px;
    border-left: 4px solid #4ade80;
    transition: border-color 0.3s;
}

/* Each row's left border reflects that seat's *actually selected*
   card color (js/ui/cardColor-ui.js sets --p2/--p3/--p4 on :root),
   not the bot's difficulty — difficulty is only shown via the
   Easy/Medium/Hard toggle and the avatar icon above. Reads live off
   the shared --p2..--p4 variables, so it updates the instant the
   color-trigger popover changes a seat's color, no extra JS needed. */
.bot-row[data-player="p2"] { border-left-color: var(--p2, #4ade80); }
.bot-row[data-player="p3"] { border-left-color: var(--p3, #f59e0b); }
.bot-row[data-player="p4"] { border-left-color: var(--p4, #ef4444); }

.bot-avatar {
    font-size: 36px;
    width: 52px;
    text-align: center;
    flex-shrink: 0;
    transition: font-size 0.2s;
}

.bot-info { flex: 1; }

.bot-name {
    font-size: 15px;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--text-main);
}

.diff-toggle { display: flex; gap: 6px; }

.diff-btn {
    flex: 1;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(255,255,255,0.15);
    background: transparent;
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
}

.diff-btn:hover { background: rgba(255,255,255,0.08); color: var(--text-main); }

.diff-btn.active[data-diff="easy"]   { background: rgba(74,222,128,0.2); border-color: #4ade80; color: #4ade80; }
.diff-btn.active[data-diff="medium"] { background: rgba(245,158,11,0.2); border-color: #f59e0b; color: #f59e0b; }
.diff-btn.active[data-diff="hard"]   { background: rgba(239,68,68,0.2);  border-color: #ef4444; color: #ef4444; }

/* Player's own row on the Choose Bot Difficulty screen — same shape as
   a bot row, just without a difficulty toggle, and its left border
   reflects the player's own card color instead of a bot's. */
.player-row { border-left-color: var(--p1, #4ade80); }

/* ── Player avatar display (Choose Bot Difficulty screen) ──
   Read-only portrait showing the player's current avatar, sized to
   match the bot avatar icons in the rows below it. Not a button —
   this screen never lets avatar or name be changed; editing only
   happens on profile.html (see .profile-avatar-grid further down). */
.player-avatar-mount { flex-shrink: 0; width: 52px; text-align: center; }

.player-avatar-display {
    width: 72px;
    height: 72px;
    object-fit: contain;
    display: block;
    pointer-events: none;
}

/* Retained for the legacy avatar-trigger-mount width (still used by
   other emoji-icon rows); not used for the player avatar anymore. */
.avatar-trigger-mount { flex-shrink: 0; width: 52px; text-align: center; }

.avatar-trigger { position: relative; }

.avatar-trigger-btn {
    width: 72px;
    height: 72px;
    padding: 0;
    border-radius: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    overflow: visible;
    transition: transform 0.15s ease, filter 0.15s ease;
}

.avatar-trigger-btn img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.avatar-trigger-btn:hover { transform: scale(1.06); }

.avatar-trigger-btn.open {
    filter: drop-shadow(0 0 6px rgba(255,255,255,0.55));
}

.avatar-trigger-popover {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    display: none;
    gap: 10px;
    padding: 10px;
    background: rgba(10,31,15,0.92);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 30px rgba(0,0,0,0.45);
    z-index: 20;
}

.avatar-trigger-popover.open { display: flex; }

[dir="rtl"] .avatar-trigger-popover { left: auto; right: 0; }

.avatar-choice {
    width: 54px;
    height: 54px;
    padding: 0;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.15);
    background: transparent;
    cursor: pointer;
    overflow: hidden;
    transition: transform 0.15s ease, border-color 0.15s ease;
}

.avatar-choice img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.avatar-choice:hover { transform: scale(1.06); }

.avatar-choice.active {
    border-color: #4ade80;
    box-shadow: 0 0 0 3px rgba(74,222,128,0.25);
}

/* ── Profile modal (js/ui/profile-ui.js) ─────────────────────
   Display name + avatar — the only place either is edited. Reuses
   the .avatar-choice look above at a slightly larger size since this
   grid isn't squeezed into a popover. */
.profile-panel {
    max-width: 360px;
}

/* The Achievement Collection redesign (grid + featured card + filter
   tabs) needs more breathing room than the avatar/name section above —
   still the same popup (per AGENTS.md rule 4), just a wider variant.
   Capped by .modal-content's own min(700px, 92vw)/88vh, so this never
   causes horizontal overflow on any viewport. */
.profile-panel.profile-panel--wide {
    /* .small-popup sets a fixed width: 350px — override it directly
       (not just max-width) so the wider layout actually takes effect. */
    width: min(560px, 92vw);
    max-width: 560px;
}

.profile-content {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 4px 4px 8px;
}

.profile-avatar-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 14px;
}

/* Matches .player-avatar-display's untouched, uncropped look on the
   Choose Bot Difficulty screen — no border-radius/overflow-clipping,
   object-fit: contain so the whole illustration shows instead of
   being cover-cropped into the button's box. */
.profile-avatar-choice {
    width: 72px;
    height: 72px;
    padding: 0;
    border-radius: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    overflow: visible;
    opacity: 0.55;
    transition: transform 0.15s ease, opacity 0.15s ease;
}

.profile-avatar-choice img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.profile-avatar-choice:hover { transform: scale(1.06); }

.profile-avatar-choice.active {
    opacity: 1;
    transform: scale(1.08);
}

.profile-name-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

/* ── Name row: read view (text + Edit) vs edit view (input) ──
   Read view is the default; tapping Edit swaps to the input (see
   js/ui/profile-ui.js setNameEditMode). Both share the row's
   centered layout so nothing shifts horizontally when toggling. */
.profile-name-display {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 40px;
}

.profile-name-text {
    font-size: 16px;
    font-weight: 600;
    color: #fff;
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.profile-name-edit-btn {
    width: 32px;
    height: 32px;
    font-size: 14px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.15);
    background: rgba(255,255,255,0.06);
}

.profile-name-edit-btn:hover {
    background: rgba(255,255,255,0.12);
}

.profile-name-edit-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
}

/* .hidden (display:none) is defined earlier in this file with the
   same specificity as the two rules above — without this compound
   override, source order would let .profile-name-display/.profile-
   name-edit-wrap's own `display: flex` win, so toggling the `hidden`
   class from js/ui/profile-ui.js wouldn't actually hide anything.
   Same pattern as .tut-video-container.hidden elsewhere in this file. */
.profile-name-display.hidden,
.profile-name-edit-wrap.hidden {
    display: none;
}

.profile-name-edit-wrap .player-name-input {
    width: min(220px, 68%);
}

.profile-name-save-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    font-size: 16px;
    border-radius: 12px;
    border: 1.5px solid rgba(74,222,128,0.4);
    background: rgba(74,222,128,0.12);
}

.profile-name-save-btn:hover {
    background: rgba(74,222,128,0.22);
}

/* ── Profile → Achievements section ──────────────────────────
   Reads from js/services/achievements.js, the real achievement
   system — see js/ui/profile-ui.js renderAchievements() and the
   .profile-achievement-* rules further down this file for the actual
   locked/unlocked/progress item styling. */
.profile-achievements {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.profile-achievements-title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: white;
}

/* ── Per-seat color trigger (Choose Bot Difficulty screen) ──
   A small circle showing the seat's current card color; clicking it
   opens a popover with the full palette. Same underlying color state
   as the Settings → Player Colors picker (js/ui/cardColor-ui.js). */
.color-trigger-mount { flex-shrink: 0; }

.color-trigger { position: relative; }

.color-trigger-btn {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.25);
    background: var(--swatch-color);
    padding: 0;
    cursor: pointer;
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.color-trigger-btn:hover { transform: scale(1.08); }

.color-trigger-btn.open {
    border-color: #fff;
    box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
}

.color-trigger-popover {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    display: none;
    min-width: 150px;
    padding: 10px;
    background: rgba(10,31,15,0.92);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 30px rgba(0,0,0,0.45);
    z-index: 20;
}

.color-trigger-popover.open { display: block; }

[dir="rtl"] .color-trigger-popover { right: auto; left: 0; }

/* ============================================================
   SETTINGS — sound switch
============================================================ */

.settings-content { padding: 4px 0; }

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 0;
}

.settings-label { font-size: 14px; font-weight: 600; }

/* About Developer's entry row inside Settings — a clickable
   .settings-row (see the shared layout rule above) rather than a new
   row style, opening the existing #aboutModal nested on top of
   #settingsModal (js/ui/modal-ui.js already supports this — same
   pattern as #cardModal over #helpModal). */
.settings-row-link {
    width: 100%;
    background: none;
    border: none;
    cursor: pointer;
    color: inherit;
    font: inherit;
    text-align: inherit;
}

.settings-row-link .settings-label {
    display: flex;
    align-items: center;
    gap: 8px;
}

.settings-row-chevron {
    opacity: 0.6;
    flex-shrink: 0;
}

[dir="rtl"] .settings-row-chevron {
    transform: scaleX(-1);
}

.settings-divider {
    height: 1px;
    background: rgba(255,255,255,0.08);
    margin: 8px 0 16px;
}

/* Switch button */
.switch-btn { position: relative; display: inline-block; cursor: pointer; }
.switch-btn input { opacity: 0; width: 0; height: 0; position: absolute; }

.switch-track {
    display: block;
    width: 44px; height: 24px;
    background: rgba(255,255,255,0.15);
    border-radius: 12px;
    transition: background 0.25s;
    position: relative;
}

.switch-btn input:checked + .switch-track { background: var(--accent); }

.switch-thumb {
    position: absolute;
    top: 3px; left: 3px;
    width: 18px; height: 18px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.25s;
    box-shadow: 0 1px 4px rgba(0,0,0,.3);
}

.switch-btn input:checked + .switch-track .switch-thumb { transform: translateX(20px); }

/* ============================================================
   PANEL HEADER (party / trash / log)
============================================================ */

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

.panel-header h3 { margin: 0; display: flex; align-items: center; gap: 6px; }

.panel-close { display: none; }  /* shown only on mobile */

/* Info tooltip button */
.panel-info-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: rgba(255,255,255,0.12);
    font-size: 11px;
    cursor: pointer;
    margin-left: 4px;
    position: relative;
    color: var(--text-muted);
    transition: background 0.2s;
}

.panel-info-btn:hover { background: rgba(255,255,255,0.25); }

/* Desktop tooltip */
.panel-info-btn::after {
    content: attr(data-tooltip);
    position: absolute;
    left: 50%; bottom: 130%;
    transform: translateX(-50%);
    background: rgba(10,31,15,0.97);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    font-size: 12px;
    font-weight: 400;
    white-space: normal;
    width: 220px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 20px rgba(0,0,0,.5);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s;
    z-index: 200;
    line-height: 1.5;
}

.panel-info-btn::after {
    bottom: auto;
    top: 130%;
}

.panel-info-btn:hover::after { opacity: 1; }

/* ============================================================
   LEADERBOARD updated rows (4-col)
============================================================ */

.leaderboard-header,
.leaderboard-row {
    display: grid;
    grid-template-columns: 28px 1fr 40px 44px;
    gap: 4px;
    align-items: center;
    padding: 5px 6px;
    font-size: 13px;
}

.leaderboard-header {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    border-bottom: 1px solid rgba(255,255,255,0.08);
    margin-bottom: 4px;
}

.lb-cards { color: #86efac; font-weight: 600; text-align: right; }
.lb-score { color: #fbbf24; font-weight: 700; text-align: right; }

/* ============================================================
   MOBILE LOG PANEL — same as party/trash popup
============================================================ */

.mobile-panel-content {
    display: flex;
    flex-direction: column;
    max-height: 70vh;
}

#mobileLogContent {
    flex: 1;
    overflow-y: auto;
    padding-top: 8px;
}

/* ============================================================
   MOBILE OVERRIDES
============================================================ */

@media (max-width: 600px) {

    /* hide desktop leaderboard; show mobile one */
    #mobileLeaderboard {
        display: block !important;
        order: 0;
        margin: 6px 12px 0;
        padding: 8px 10px;
        background: rgba(255,255,255,0.05);
        border-radius: var(--radius-sm);
        box-sizing: border-box;
    }

    .mobile-only-btn { display: flex !important; }

    /* panel close button */
    .panel-close {
        display: flex;
    }

    /* info tooltip → popup on mobile (handled via JS) */
    .panel-info-btn::after { display: none; }

    /* hide button tooltip on mobile (no hover) */
    .top-btn[data-title]::after { display: none; }

    /* Log modal — same bottom-sheet shell as every other modal (see
       the shared .modal/.modal-content mobile rules above); only
       needs its own height since log entries are usually short and
       shouldn't force a near-full-screen sheet like Settings/Profile
       do. */
    #logModal .modal-content {
        height: 70vh !important;
        max-height: 70dvh !important;
    }

    /* remove stray modal-content that causes scroll */
    #pageLayout > .modal-content,
    #gameColumn > .modal-content,
    #gameLayout > .modal-content {
        display: none !important;
    }

    /* leaderboard order above mobileTabs */
    #gameLayout { display: flex; flex-direction: column; }
    #mobileLeaderboard { order: 0; }
    #mobileTabs         { order: 1; padding: 6px 12px 4px; }
    #otherPlayers       { order: 2; }
    #centerArea         { order: 3; }

    /* log, leaderboard btn hidden */
    #leaderboardBtn { display: none !important; }

    /* leaderboard row smaller on mobile */
    .leaderboard-header,
    .leaderboard-row {
        grid-template-columns: 22px 1fr 34px 38px;
        font-size: 11px;
        padding: 4px 4px;
        column-gap: 16px;
    }

    /* hand bottom padding */
    #handArea { padding: 12px 12px 28px !important; }

    /* help 3-col grid */
    #animalGrid {
        grid-template-columns: repeat(3, 1fr) !important;
        gap: 8px !important;
    }
    .card-info { width: 100% !important; height: auto !important; aspect-ratio: 3/4; }

    /* top bar */
    #topBarContent {
        display: grid !important;
        grid-template-areas: "logo logo" "left right" !important;
        grid-template-columns: 1fr auto !important;
        grid-template-rows: auto auto !important;
        height: auto !important;
        padding: 8px 12px 6px !important;
        gap: 4px 0;
    }
    #topCenter { grid-area: logo !important; justify-self: center; }
    #topCenter picture img { height: clamp(44px, 14vw, 72px) !important; width: auto; }
    #topLeft   { grid-area: left !important; flex-direction: column; align-items: flex-start; }
    #topRight  { grid-area: right !important; }
    .turn-divider { display: none; }
}

/* Info popup overlay (mobile) */
.info-popup-overlay {
    position: fixed; inset: 0; z-index: 9998;
    background: rgba(0,0,0,0.6);
    display: flex; align-items: center; justify-content: center;
}
.info-popup-box {
    background: rgba(10,31,15,0.97);
    backdrop-filter: blur(18px);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: var(--radius-md);
    padding: 24px 20px;
    max-width: calc(100vw - 48px);
    font-size: 14px; line-height: 1.6; color: #fff;
    text-align: center;
    box-shadow: 0 10px 40px rgba(0,0,0,.6);
}

/* ============================================================
   OTHER PLAYER ROW — avatar left, hand center, deck right
============================================================ */

.other-player-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--bot-color, rgba(255,255,255,0.2));
    background: rgba(255,255,255,0.03);
    box-sizing: border-box;
    margin-bottom: 4px;
    /* Outline (not border) so the current-turn frame below never shifts
       layout by changing box size — it just switches from invisible to
       visible/pulsing. */
    outline: 2px solid transparent;
    outline-offset: 2px;
    transition: outline-color .2s ease, background-color .2s ease;
}

/* Whose turn it is, for opponents: a glowing frame in that player's own
   identity color (--bot-color, same one already used for the resting
   left border/avatar), so at a glance the active seat is unmistakable —
   mirrors the pulse already used for the human player's own hand
   (#playerHand.my-turn) but as a full frame around the row instead of
   per-card, since opponents' cards are face-down placeholders. */
.other-player-row.current-turn {
    outline-color: var(--bot-color);
    background: color-mix(in srgb, var(--bot-color) 14%, rgba(255,255,255,0.03));
    animation: turnPulseRow 1.5s infinite;
}

@keyframes turnPulseRow {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--bot-color) 55%, transparent); }
    70%  { box-shadow: 0 0 0 8px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
}

.other-player-left {
    display: flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    min-width: 60px;
}

.other-avatar {
    font-size: 20px;
    line-height: 1;
    flex-shrink: 0;
}

.other-player-right { flex-shrink: 0; }

.other-hand {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    flex: 1;
    justify-content: center;
}

/* Smaller card-backs for opponent hands on desktop */
.other-hand .card-back {
    width:  clamp(20px, 2.8vw, 42px);
    height: clamp(28px, 4vw, 60px);
}

/* ── leftSidebar also constrained ── */
#leftSidebar {
    overflow-y: auto;
}

/* ── centerArea fills remaining space ── */
#centerArea {
    overflow: hidden;
    min-height: 0;
}

@media (max-width: 600px) {
    .other-player-row {
        gap: 6px;
        padding: 3px 6px;
        margin-bottom: 3px;
    }
    .other-avatar { font-size: 16px; }
    .other-player-left { min-width: 50px; gap: 3px; }
}


/* ==========================================================
   MAIN MENU POPUP STANDARDIZATION (Mobile) — Settings, Profile,
   Card Guide, About Developer, Lucky Wheel and Feedback
   (index.html's Home menu popups) now share one visual template
   instead of each having its own slightly-different chrome.

   The template reuses two things that already exist rather than
   inventing a third design system:
     1. The Tutorial Popup's (.tut-panel below) glass background /
        border / radius / shadow treatment.
     2. The existing Header → Scrollable Body → Fixed Footer
        architecture (.modal-header/.modal-body, see the base
        .modal-content rules above and README.md "Panel
        Architecture") that Feedback already used — Settings,
        Profile, Card Guide, About and Lucky Wheel now opt into it
        too via a plain `modal-body` class alongside their existing
        content wrapper class, so all of the mobile-landscape
        no-scroll/bottom-sheet handling already built for
        .modal-header/.modal-body (see further down this file)
        applies to them for free.

   Everything here is scoped to the `.menu-popup` modifier class,
   added only on index.html's Home popups — the base
   .modal-content/.help-header rules, and every popup that keeps
   using them unmodified (game.html's own Pause/Settings/Help/
   About/Feedback modals, Kangaroo, Card detail, Game Log, Card
   Guidance), are completely untouched. Pause in particular must
   never be touched by this task. */

.modal-content.menu-popup {
    background: rgba(10, 28, 15, 0.95);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: var(--radius-lg);
    box-shadow: 0 32px 80px rgba(0,0,0,0.7);
}

/* Header: title left, close button right (already true of the flex
   row + space-between .help-header markup below — this just fixes
   the one real inconsistency between popups, which was typography:
   Card Guide's title is an <h1>, Settings/Profile/About/Lucky
   Wheel/Feedback's are <h3> — with no shared size/margin reset,
   browser defaults gave every popup a visibly different header
   height. Normalizing both tags here is what makes "consistent
   header height" and "consistent spacing between header and
   content" actually hold across every popup, matching the
   Tutorial Popup's header. */
.modal-content.menu-popup > .modal-header {
    border-bottom: 1px solid rgba(255,255,255,0.08);
}

.modal-content.menu-popup > .modal-header h1,
.modal-content.menu-popup > .modal-header h3 {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 800;
    color: #ffffff;
    line-height: 1.25;
}

.modal-content.menu-popup > .modal-footer {
    border-top: 1px solid rgba(255,255,255,0.08);
}

/* About Developer and Lucky Wheel previously used a corner-pinned
   close button + centered title/avatar layout instead of a header
   row (see the base .about-panel/.lucky-wheel-panel rules above,
   still used as-is by game.html's own About modal). Their
   Home instances now use the same header-row markup as every other
   menu popup, so the old absolute-positioned close button and
   top padding hack are no longer needed here — scoped to
   `.menu-popup` only, so `.about-panel`/`.lucky-wheel-panel`
   themselves are untouched for anything still using the old
   layout. */
.about-panel.menu-popup,
.lucky-wheel-panel.menu-popup {
    padding-top: 0;
}

.about-panel.menu-popup .about-body,
.lucky-wheel-panel.menu-popup .modal-body {
    text-align: center;
}

/* Card Guide's body now wraps several previously-top-level children
   (.help-text, .help-divider, the Animal Abilities title, #animalGrid)
   in one .modal-body so the existing Header/Scrollable-Body
   architecture applies — this restores the 16px gap .help-layout
   used to provide between those siblings directly. */
.help-body {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* ==========================================================
   TUTORIAL — redesigned help-page style
========================================================== */

.tut-panel {
    width: min(640px, 92vw);
    /* Was unbounded height with overflow:hidden — a wider viewport
       could always fit header+image+text+footer, but on a short
       viewport (mobile landscape, ~375-430px tall) the panel simply
       grew taller than the screen with no way to scroll, silently
       cutting off the Next/Prev buttons. Bounding the panel and
       letting only .tut-body scroll (below) fixes that while keeping
       the header/progress bar/footer always visible. */
    max-height: 88vh;
    max-height: 88dvh;
    /* Explicit height (not just max-height) — every How To Play step
       reuses this one panel element, only swapping .tut-body's
       content (image/title/text/diagram/video). Without a fixed
       height the panel shrank to fit whichever step's content was
       shortest, so switching steps visibly resized the whole panel.
       A fixed height keeps every step's outer panel identical; a
       step with less content just leaves .tut-body with a little
       breathing room instead of the panel shrinking to meet it. */
    height: min(600px, 88vh);
    height: min(600px, 88dvh);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0;
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: rgba(10, 28, 15, 0.95);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255,255,255,0.10);
    box-shadow: 0 32px 80px rgba(0,0,0,0.7);
}

/* Header */
.tut-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 22px 14px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
}

.tut-header-left {
    display: flex;
    align-items: center;
    gap: 10px;
}

.tut-label {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
}

.tut-counter {
    font-size: 0.75rem;
    color: var(--text-muted);
    opacity: 0.65;
}

/* Progress bar */
.tut-progress-track {
    flex: 0 0 auto;
    width: 100%;
    height: 3px;
    background: rgba(255,255,255,0.08);
}

.tut-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--accent), #e8834a);
    transition: width 0.35s cubic-bezier(.4,0,.2,1);
    width: 0%;
}

/* Body — the one part of the panel that scrolls; min-height:0 is
   required for a flex child to actually shrink below its content
   size instead of forcing the whole panel to overflow the screen. */
.tut-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Now that .tut-panel has a fixed height (see above), a step with
       less content (no image, short text) would otherwise sit at the
       top of .tut-body with empty space below it. `safe center`
       vertically centers that shorter content within the fixed panel
       instead, while still starting from the top and scrolling
       normally if a step's content is tall enough to overflow (the
       `flex-start` fallback via @supports below handles browsers
       without `safe` keyword support, matching the existing
       .screen-content pattern elsewhere in this file). */
    justify-content: safe center;
    padding: 32px 28px 20px;
    gap: 24px;
}

@supports not (justify-content: safe center) {
    .tut-body { justify-content: flex-start; }
}

.tut-image {
    width: 100%;
    max-height: 180px;
    object-fit: contain;
    border-radius: var(--radius-md);
    border: 1px solid rgba(255,255,255,0.07);
    display: none;
}

.tut-content {
    text-align: center;
    flex: 1;
}

.tut-title {
    font-size: clamp(1.15rem, 3.5vw, 1.55rem);
    font-weight: 800;
    color: #ffffff;
    margin: 0 0 16px;
    line-height: 1.2;
}

.tut-text {
    color: var(--text-muted);
    font-size: clamp(0.88rem, 2.5vw, 0.97rem);
    line-height: 1.65;
    max-width: 480px;
    margin: 0 auto;
}

.tut-text p {
    margin: 0 0 8px;
}
.tut-text p:last-child { margin-bottom: 0; }

/* Footer */
.tut-footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 22px calc(22px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(255,255,255,0.07);
    gap: 12px;
}

/* Nav buttons */
.tut-nav-btn {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 44px;
    height: 44px;

    border-radius: 50%;
    border: none;

    background: transparent;

    color: white;
    cursor: pointer;

    transition: transform 0.15s;

    flex-shrink: 0;
}

.tut-nav-btn:hover:not(:disabled) {
    background: rgba(255,255,255,0.08);
    border-color: rgba(255,255,255,0.35);
    transform: scale(1.07);
}

.tut-nav-btn:disabled {
    opacity: 0.25;
    cursor: default;
}

.tut-next.finish-btn {
    background: linear-gradient(135deg, var(--accent), #e8834a);
    border-color: transparent;
    width: 52px;
    height: 52px;
    box-shadow: 0 4px 16px rgba(189,93,56,0.45);
}

.tut-next.finish-btn:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 22px rgba(189,93,56,0.6);
}

/* Dots */
.tut-dots {
    display: flex;
    gap: 7px;
    align-items: center;
    flex: 1;
    justify-content: center;
}

.tut-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgba(255,255,255,0.2);
    transition: background 0.25s, transform 0.25s;
    display: inline-block;
}

.tut-dot.active {
    background: var(--accent);
    transform: scale(1.35);
}

/* ── Responsive ── */
@media (max-width: 480px) {

    .tut-body {
        padding: 22px 18px 16px;
    }

    .tut-header {
        padding: 14px 16px 12px;
    }

    .tut-footer {
        padding: 12px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    }

    .tut-nav-btn {
        width: 40px;
        height: 40px;
    }
}

/* Mobile landscape (short viewport height): the tutorial image alone
   can be up to 180px tall, which combined with header+progress+
   footer easily exceeds a ~375-430px-tall rotated phone screen.
   .tut-body already scrolls (see base rule), but shrinking the image
   and gaps here means most tutorial slides fit without scrolling. */
@media (max-height: 480px) and (orientation: landscape) {
    .tut-body {
        padding: 14px 20px 10px;
        gap: 12px;
    }

    .tut-image {
        max-height: 96px;
    }

    .tut-header {
        padding: 10px 20px 8px;
    }

    .tut-footer {
        padding: 8px 20px calc(8px + env(safe-area-inset-bottom, 0px));
    }
}

/* ══════════════════════════════════════════
   Tutorial Diagrams
══════════════════════════════════════════ */

.tut-diagram-wrap {
    margin-top: 18px;
}

.tut-diagram {
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.09);
    border-radius: var(--radius-md, 12px);
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.tut-diagram-label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent, #bd5d38);
    margin-bottom: 2px;
}

/* ── Cards ── */

.tut-hand {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
}

.tut-card {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 10px;
    padding: 10px 12px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 68px;
    position: relative;
}

.tut-card-sm {
    padding: 7px 10px 6px;
    min-width: 56px;
}

.tut-card-emoji {
    font-size: 1.6rem;
    line-height: 1;
}

.tut-card-name {
    font-size: 0.68rem;
    font-weight: 600;
    color: #ffffff;
    white-space: nowrap;
}

.tut-card-badge {
    position: absolute;
    top: -7px;
    right: -7px;
    background: var(--accent, #bd5d38);
    color: #fff;
    font-size: 0.55rem;
    font-weight: 800;
    letter-spacing: 0.05em;
    padding: 2px 5px;
    border-radius: 20px;
}

.tut-card-new {
    border-color: var(--accent, #bd5d38);
    box-shadow: 0 0 10px rgba(189,93,56,0.35);
}

/* outcome colours */
.tut-card-party {
    border-color: #4caf82;
    background: rgba(76,175,130,0.12);
}
.tut-card-trash {
    border-color: #e05252;
    background: rgba(224,82,82,0.10);
    opacity: 0.7;
}
.tut-card-stay {
    border-color: rgba(255,255,255,0.18);
}

/* ── Queue rows ── */

.tut-queue-row {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 4px;
    justify-content: center;
    overflow-x: auto;
    padding-bottom: 2px;
}

.tut-queue-wrap {
    flex-wrap: wrap;
    gap: 6px 4px;
}

.tut-arrow {
    color: rgba(255,255,255,0.3);
    font-size: 1.1rem;
    flex-shrink: 0;
    padding: 0 2px;
}

/* ── Resolve legend ── */

.tut-resolve-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    margin-top: 4px;
}

.tut-legend-dot {
    font-size: 0.7rem;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 20px;
    white-space: nowrap;
}

.tut-role-badge {
    font-size: 0.55rem;
    font-weight: 700;
    padding: 2px 5px;
    border-radius: 20px;
    white-space: nowrap;
    margin-top: 3px;
}

.badge-party { background: rgba(76,175,130,0.25); color: #4caf82; }
.badge-trash { background: rgba(224,82,82,0.20);  color: #e05252; }
.badge-stay  { background: rgba(255,255,255,0.10);color: rgba(255,255,255,0.6); }

/* ── Ability list ── */

.tut-ability-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.tut-ability-card {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 8px;
    padding: 8px 12px;
}

.tut-ability-emoji {
    font-size: 1.4rem;
    flex-shrink: 0;
}

.tut-ability-info {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 2px;
    text-align: left;
}

.tut-ability-name {
    font-size: 0.78rem;
    font-weight: 700;
    color: #fff;
}

.tut-ability-hint {
    font-size: 0.7rem;
    color: rgba(255,255,255,0.5);
}

.tut-ability-power {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--accent, #bd5d38);
    flex-shrink: 0;
}

/* ── Scoreboard ── */

.tut-scoreboard {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tut-score-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.tut-score-name {
    font-size: 0.78rem;
    font-weight: 700;
    color: #fff;
    width: 56px;
    flex-shrink: 0;
    text-align: left;
}

.tut-score-bar-wrap {
    flex: 1;
    height: 10px;
    background: rgba(255,255,255,0.08);
    border-radius: 999px;
    overflow: hidden;
}

.tut-score-bar {
    display: block;
    height: 100%;
    background: rgba(255,255,255,0.2);
    border-radius: 999px;
    transition: width 0.5s ease;
}

.tut-score-winner .tut-score-bar {
    background: linear-gradient(90deg, var(--accent, #bd5d38), #e8834a);
}

.tut-score-num {
    font-size: 0.72rem;
    font-weight: 700;
    color: rgba(255,255,255,0.55);
    width: 44px;
    text-align: right;
    flex-shrink: 0;
}

/* ── Responsive ── */
@media (max-width: 480px) {
    .tut-card { min-width: 50px; padding: 7px 8px 6px; }
    .tut-card-emoji { font-size: 1.3rem; }
    .tut-ability-card { padding: 7px 10px; }
}

/* ══════════════════════════════════════════
   Language Selector
══════════════════════════════════════════ */

.settings-row-col {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
}

.lang-selector {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    width: 100%;
}

.lang-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.12);
    background: rgba(255,255,255,0.05);
    color: rgba(255,255,255,0.7);
    font-size: 0.78rem;
    font-weight: 600;
    font-family: 'Poppins', sans-serif;
    cursor: pointer;
    transition: background 0.18s, border-color 0.18s, color 0.18s;
}

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

.lang-btn.active {
    background: rgba(189,93,56,0.2);
    border-color: var(--accent, #bd5d38);
    color: #fff;
    box-shadow: 0 0 10px rgba(189,93,56,0.25);
}

.lang-flag { font-size: 1rem; line-height: 1; }
.lang-label { line-height: 1; }

/* ══════════════════════════════════════════
   Card Color Picker (Settings)
   One row per seat (You / Bot 1 / Bot 2 / Bot 3), each repainting the
   shared --p1..--p4 variables that every card, hand border, deck-back
   and leaderboard row already reads its color from — see
   js/ui/cardColor-ui.js. Colors are kept unique across all four seats
   by swapping on conflict, so this UI never lets two seats collide.
══════════════════════════════════════════ */

.player-color-picker {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
}

.player-color-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

.player-color-name {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-muted);
    min-width: 56px;
}

.color-swatch-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.color-swatch {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.15);
    background: var(--swatch-color);
    padding: 0;
    cursor: pointer;
    position: relative;
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.color-swatch:hover {
    transform: scale(1.1);
}

.color-swatch.active {
    border-color: #fff;
    box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
}

.color-swatch.active::after {
    content: "\2713";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,.6);
}

/* RTL global adjustments */
[dir="rtl"] .tut-queue-row,
[dir="rtl"] .tut-hand,
[dir="rtl"] .tut-ability-list { direction: rtl; }
[dir="rtl"] .tut-score-name { text-align: right; }
[dir="rtl"] .tut-score-num  { text-align: left; }

/* ══════════════════════════════════════════
   Splash Settings Button
══════════════════════════════════════════ */

.splash-settings-btn {
    margin-top: 10px;
    padding: 10px 28px;
    background: transparent;
    border: 1px solid rgba(255,255,255,0.2);
    color: rgba(255,255,255,0.65);
    border-radius: 12px;
    font-size: 0.85rem;
    font-weight: 600;
    font-family: 'Poppins', sans-serif;
    cursor: pointer;
    transition: background 0.18s, color 0.18s, border-color 0.18s;
}

.splash-settings-btn:hover {
    background: rgba(255,255,255,0.08);
    color: #fff;
    border-color: rgba(255,255,255,0.4);
}

/* ══════════════════════════════════════════
   Tutorial Video
══════════════════════════════════════════ */

.tut-video-wrap {
    margin-top: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tut-video-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    background: rgba(189,93,56,0.15);
    border: 1px solid rgba(189,93,56,0.35);
    border-radius: 8px;
    color: #fff;
    font-size: 0.82rem;
    font-weight: 600;
    font-family: 'Poppins', sans-serif;
    cursor: pointer;
    transition: background 0.18s, border-color 0.18s;
    width: 100%;
    justify-content: center;
}

.tut-video-toggle:hover {
    background: rgba(189,93,56,0.28);
    border-color: var(--accent, #bd5d38);
}

.tut-video-icon { font-size: 0.9rem; }

.tut-video-container {
    width: 100%;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,0.1);
    background: #000;
    aspect-ratio: 16 / 9;
}

.tut-video-container iframe {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
}

.tut-video-container.hidden { display: none; }


/* ══════════════════════════════════════════
   Settings modal above splash screen
══════════════════════════════════════════ */

#settingsModal {
    z-index: 10000;
}

#settingsModal .modal-content {
    z-index: 10001;
}


/* ══════════════════════════════════════════
   Language-specific fonts
══════════════════════════════════════════ */

:lang(fa) {
    font-family: 'Vazirmatn', sans-serif;
}

:lang(ar) {
    font-family: 'Noto Sans Arabic', sans-serif;
}

:lang(tr) {
    font-family: 'Noto Sans TR', 'Poppins', sans-serif;
}


/* ══════════════════════════════════════════
   RTL: Mirror directional icons
══════════════════════════════════════════ */

[dir="rtl"] .tut-prev img,
[dir="rtl"] .tut-next img {
    transform: scaleX(-1);
}

[dir="rtl"] .example-container .arrow {
    transform: scaleX(-1);
    display: inline-block;
}

/* Back button also flips in RTL */
[dir="rtl"] #cardBackBtn img {
    transform: scaleX(-1);
}


/* ══════════════════════════════════════════
   Numbers always LTR (no digit reversal in RTL)
══════════════════════════════════════════ */

#deckCount,
.other-deck-count,
.slot-number,
.lb-cards,
.lb-score,
.party-count,
.power-score,
.power-badge {
    direction: ltr;
    unicode-bidi: isolate;
}


/* ══════════════════════════════════════════
   RTL font & line-height fixes
   (Vazirmatn/Noto Arabic have taller glyphs)
══════════════════════════════════════════ */

:lang(fa),
:lang(ar) {
    line-height: 1.5;
}

:lang(fa) .card-name,
:lang(ar) .card-name,
:lang(fa) .help-card-name,
:lang(ar) .help-card-name,
:lang(fa) .top-btn,
:lang(ar) .top-btn,
:lang(fa) .screen-btn,
:lang(ar) .screen-btn,
:lang(fa) .panel-header h3,
:lang(ar) .panel-header h3 {
    line-height: 1.3;
}

/* Prevent card footer overflow in RTL */
:lang(fa) .card-footer,
:lang(ar) .card-footer {
    flex-wrap: nowrap;
    gap: 4px;
}

:lang(fa) .card-name,
:lang(ar) .card-name {
    font-size: clamp(9px, 1.3vw, 13px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Tooltip font fix for RTL */
:lang(fa) .top-btn[data-title]::after,
:lang(ar) .top-btn[data-title]::after {
    font-family: 'Vazirmatn', 'Noto Sans Arabic', sans-serif;
}

:lang(tr) .top-btn[data-title]::after {
    font-family: 'Noto Sans TR', 'Poppins', sans-serif;
}


/* ══════════════════════════════════════════
   Player Name Input (difficulty screen)
══════════════════════════════════════════ */

.player-name-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-bottom: 20px;
    width: 100%;
}

.player-name-label {
    font-size: 14px;
    color: var(--text-muted);
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.player-name-input {
    width: min(280px, 80%);
    padding: 10px 16px;
    border-radius: 12px;
    border: 1.5px solid rgba(255,255,255,0.15);
    background: rgba(255,255,255,0.07);
    color: #fff;
    font-size: 16px;
    font-family: inherit;
    text-align: center;
    outline: none;
    transition: border-color 0.2s, background 0.2s;
}

.player-name-input:focus {
    border-color: var(--accent);
    background: rgba(255,255,255,0.11);
}

.player-name-input::placeholder {
    color: rgba(255,255,255,0.3);
    font-size: 14px;
}


/* ══════════════════════════════════════════
   IN-GAME WALKTHROUGH OVERLAY
══════════════════════════════════════════ */

.wt-overlay {
    position: fixed;
    inset: 0;
    z-index: 50000;
    pointer-events: none;
}

.wt-overlay.active {
    pointer-events: all;
}

/* Card-play step: overlay becomes click-through, only wt-box stays interactive */
.wt-overlay.active.wt-passthrough {
    pointer-events: none;
}
.wt-overlay.active.wt-passthrough .wt-box {
    pointer-events: all;
}
/* also dim the backdrop but keep it visible */
.wt-overlay.wt-passthrough::before {
    background: rgba(0,0,0,0.45);
}

/* dark backdrop with hole cut out for spotlight */
.wt-overlay::before {
    content: '';
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.72);
    z-index: 0;
}

/* spotlight — transparent box on top of backdrop */
.wt-spotlight {
    position: fixed;
    border-radius: 12px;
    box-shadow:
        0 0 0 9999px rgba(0,0,0,0.72),
        0 0 0 3px var(--accent),
        0 0 24px 6px rgba(var(--accent-rgb, 80,200,120),0.35);
    transition: all 0.35s cubic-bezier(.4,0,.2,1);
    z-index: 1;
    pointer-events: none;
}

/* info box */
.wt-box {
    position: fixed;
    z-index: 2;
    background: rgba(12, 35, 20, 0.97);
    border: 1.5px solid rgba(255,255,255,0.13);
    border-radius: 16px;
    padding: 18px 20px 14px;
    width: clamp(240px, 80vw, 340px);
    box-shadow: 0 12px 40px rgba(0,0,0,0.6);
    transition: all 0.3s cubic-bezier(.4,0,.2,1);
}

.wt-step-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 8px;
    opacity: 0.85;
}

/* arrow pointing to spotlight */
.wt-arrow {
    display: none;
    position: absolute;
    width: 0;
    height: 0;
}

.wt-arrow.arrow-up {
    display: block;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 10px solid rgba(255,255,255,0.13);
}

.wt-arrow.arrow-down {
    display: block;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%);
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-top: 10px solid rgba(255,255,255,0.13);
}

.wt-arrow.arrow-left {
    display: block;
    left: -10px;
    top: 50%;
    transform: translateY(-50%);
    border-top: 10px solid transparent;
    border-bottom: 10px solid transparent;
    border-right: 10px solid rgba(255,255,255,0.13);
}

.wt-arrow.arrow-right {
    display: block;
    right: -10px;
    top: 50%;
    transform: translateY(-50%);
    border-top: 10px solid transparent;
    border-bottom: 10px solid transparent;
    border-left: 10px solid rgba(255,255,255,0.13);
}

.wt-title {
    font-size: 16px;
    font-weight: 700;
    color: #fff;
    margin: 0 0 8px;
    line-height: 1.3;
}

.wt-text {
    font-size: 13px;
    color: rgba(255,255,255,0.82);
    line-height: 1.6;
    margin: 0 0 14px;
    white-space: pre-line;
}

.wt-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.wt-skip-btn {
    font-size: 12px;
    color: rgba(255,255,255,0.4);
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px 0;
    transition: color 0.15s;
}
.wt-skip-btn:hover { color: rgba(255,255,255,0.7); }

.wt-next-btn {
    padding: 9px 22px;
    background: var(--accent);
    color: #000;
    font-weight: 700;
    font-size: 13px;
    border: none;
    border-radius: 10px;
    cursor: pointer;
    transition: opacity 0.15s, transform 0.15s;
    flex-shrink: 0;
}
.wt-next-btn:hover { opacity: 0.88; transform: scale(1.03); }
.wt-next-btn.pulse {
    animation: wt-pulse 1.2s ease-in-out infinite;
}

/* special: waiting for card play */
.wt-waiting .wt-next-btn { display: none; }
.wt-waiting .wt-skip-btn { margin-left: auto; }

/* highlight ring on elements we want player to interact with */
.wt-highlight {
    position: relative;
    z-index: 49999 !important;
    pointer-events: all !important;
}

/* ensure all children inside highlighted elements are also clickable */
.wt-highlight * {
    pointer-events: all !important;
}

/* on mobile, hand area must sit above the walkthrough overlay when highlighted */
@media (max-width: 600px) {
    #handArea.wt-highlight,
    #handArea:has(.wt-highlight) {
        z-index: 49999 !important;
    }
    /* when walkthrough is active on step 7 (card play), lift hand area */
    body.wt-card-step #handArea {
        z-index: 49999 !important;
        position: fixed !important;
    }
}

@keyframes wt-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb,80,200,120),0.5); }
    50%       { box-shadow: 0 0 0 8px rgba(var(--accent-rgb,80,200,120),0); }
}

[dir="rtl"] .wt-arrow.arrow-left {
    left: auto; right: -10px;
    border-right: none;
    border-left: 10px solid rgba(255,255,255,0.13);
}
[dir="rtl"] .wt-arrow.arrow-right {
    right: auto; left: -10px;
    border-left: none;
    border-right: 10px solid rgba(255,255,255,0.13);
}

/* ══════════════════════════════════════════
   WALKTHROUGH — RESPONSIVE (mobile)
══════════════════════════════════════════ */

@media (max-width: 600px) {
    /* Box: always at bottom of screen, full-width */
    .wt-box {
        position: fixed !important;
        left: 12px !important;
        right: 12px !important;
        bottom: 0 !important;
        top: auto !important;
        transform: none !important;
        width: auto !important;
        max-width: 100% !important;
        border-radius: 16px 16px 0 0 !important;
        padding: 16px 16px 24px !important;
        box-sizing: border-box;
    }

    /* When hand step is active, push box up so it doesn't cover the pinned hand */
    .wt-box.above-hand {
        bottom: 100px !important;
        border-radius: 16px !important;
    }

    /* Arrow hidden on mobile since box is always at bottom */
    .wt-arrow { display: none !important; }

    /* Spotlight still works normally */
}


/* ══════════════════════════════════════════
   CARD HELP — LONG-PRESS DISCOVERABILITY
   (js/ui/cardHelpHint.js + affordance badges below)
══════════════════════════════════════════ */

/* ── Returning-player affordance ──────────────────────────
   A small "info" badge on each hand card, hidden by default and only
   faded in on hover (desktop), keyboard focus, or an active press
   (which also covers touch — see .long-press-active, toggled the
   moment a press starts, from js/ui/longPress.js). Never shown
   permanently, never intercepts a tap/click (pointer-events: none). */
.card-help-affordance {
    position: absolute;
    top: 5%;
    right: 6%;
    z-index: 4;
    width: clamp(14px, 2.6cqw, 20px);
    height: clamp(14px, 2.6cqw, 20px);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    transform: scale(0.7);
    transition: opacity 150ms ease, transform 150ms ease;
    pointer-events: none;
}

.card-help-affordance .icon-image {
    width: 65%;
    height: 65%;
    object-fit: contain;
}

.card:hover .card-help-affordance,
.card:focus-visible .card-help-affordance,
.card.long-press-active .card-help-affordance {
    opacity: 0.95;
    transform: scale(1);
}

[dir="rtl"] .card-help-affordance {
    right: auto;
    left: 6%;
}

/* ── First-time hint bubble ────────────────────────────────
   Positioned with position:fixed and placed via JS from the hand's
   actual bounding rect (see js/ui/cardHelpHint.js) rather than
   anchored inside #handArea — #centerArea uses overflow:hidden for
   its own layout, which would otherwise risk clipping a bubble meant
   to poke up above the hand. Fixed positioning + a below-modal
   z-index keeps it clear of both that clipping and any modal that
   might open. Entirely pointer-events: none — it can never block a
   tap/click meant for a card underneath/behind it. */
.card-help-hint {
    position: fixed;
    z-index: 9500;
    transform: translate(-50%, 8px);
    opacity: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    transition: opacity 220ms ease, transform 220ms ease;
    max-width: min(86vw, 280px);
}

.card-help-hint.visible {
    transform: translate(-50%, 0);
    opacity: 1;
}

.card-help-hint-bubble {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 10px 14px;
    background: var(--bg-panel);
    backdrop-filter: var(--blur);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-panel);
    text-align: center;
}

.card-help-hint-text {
    margin: 0;
    font-size: clamp(11px, 2.4vw, 13px);
    color: var(--text-main);
    line-height: 1.35;
}

.card-help-hint-arrow {
    width: 12px;
    height: 12px;
    margin-top: -7px;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    transform: rotate(45deg);
    backdrop-filter: var(--blur);
}

/* Small self-contained demo: an icon that presses down while a ring
   fills around it, then releases — the same visual language as the
   real long-press feedback (see .card.long-press-active), but staged
   on its own mini widget so the actual hand cards are never touched
   and the real Help modal is never opened automatically. */
.card-help-hint-demo {
    position: relative;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.card-help-hint-demo-icon {
    font-size: 18px;
    line-height: 1;
    animation: card-help-demo-pulse 1.8s ease-in-out 2;
}

.card-help-hint-demo-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(var(--accent) 0deg, transparent 0deg);
    opacity: 0;
    animation: card-help-demo-ring 1.8s ease-in-out 2;
}

@keyframes card-help-demo-pulse {
    0%   { transform: scale(1); }
    10%  { transform: scale(0.88); }
    75%  { transform: scale(0.88); }
    100% { transform: scale(1); }
}

@keyframes card-help-demo-ring {
    0%   { opacity: 0;    background: conic-gradient(var(--accent) 0deg, transparent 0deg); }
    10%  { opacity: 0.9;  background: conic-gradient(var(--accent) 0deg, transparent 0deg); }
    75%  { opacity: 0.9;  background: conic-gradient(var(--accent) 360deg, transparent 360deg); }
    100% { opacity: 0;    background: conic-gradient(var(--accent) 360deg, transparent 360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .card-help-hint-demo-icon,
    .card-help-hint-demo-ring {
        animation: none;
    }
    .card-help-hint-demo-ring {
        opacity: 0.5;
        background: conic-gradient(var(--accent) 180deg, transparent 180deg);
    }
}

/* On the narrow mobile layout #handArea becomes position:fixed at the
   bottom of the screen (see the existing mobile #handArea rule); the
   JS-computed position in cardHelpHint.js already re-anchors above
   whatever the hand's current rect is, so only the bubble's own max
   width needs a tighter mobile cap here. */
@media (max-width: 600px) {
    .card-help-hint {
        max-width: min(80vw, 240px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .other-player-row.current-turn {
        animation: none;
        box-shadow: 0 0 0 3px color-mix(in srgb, var(--bot-color) 55%, transparent);
    }
}

/* ══════════════════════════════════════════════════════════
   Feedback / survey form
   ══════════════════════════════════════════════════════════ */

.feedback-link-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;

    margin-top: 0;

    padding: 10px 20px;

    border-radius: 10px;
    border: 1px solid var(--border);

    background: rgba(255, 255, 255, 0.06);
    color: var(--text-main);

    font-weight: 600;
    font-size: 14px;

    cursor: pointer;
    transition: .2s;
}

.feedback-link-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    transform: translateY(-2px);
}

.endgame-feedback-btn {
    margin-top: 10px;
    display: flex;
    justify-content: center;
}

.feedback-modal-content {
    text-align: left;
    box-sizing: border-box;
}

:lang(fa) .feedback-modal-content,
:lang(ar) .feedback-modal-content {
    text-align: right;
}

.feedback-subtitle {
    color: var(--text-muted);
    font-size: 14px;
    margin: 4px 0 18px;
}

.feedback-form {
    display: flex;
    flex-direction: column;
    gap: 16px;
    width: 100%;
    box-sizing: border-box;
}

.feedback-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-sizing: border-box;
}

.feedback-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
}

.feedback-stars {
    display: flex;
    gap: 6px;
}

.feedback-star {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 28px;
    line-height: 1;
    color: rgba(255, 255, 255, 0.25);
    transition: transform .15s, color .15s;
    padding: 2px;
}

.feedback-star:hover {
    transform: scale(1.15);
}

.feedback-star.active {
    color: #facc15;
}

.feedback-textarea,
.feedback-input {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-main);
    font-size: 14px;
    font-family: inherit;
    resize: vertical;
}

.feedback-textarea:focus,
.feedback-input:focus {
    outline: none;
    border-color: var(--accent);
}

.feedback-status {
    min-height: 18px;
    font-size: 13px;
    margin: 0;
}

.feedback-status.is-error {
    color: #ef4444;
}

.feedback-status.is-success {
    color: #22c55e;
}

.feedback-submit-btn {
    width: 100%;
    box-sizing: border-box;
    margin-top: 0;
}

/* ── Random in-game toast ── */

.feedback-toast {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 1500;

    max-width: 320px;

    opacity: 0;
    transform: translateY(16px);
    transition: opacity .25s ease, transform .25s ease;

    pointer-events: none;
}

:lang(fa) .feedback-toast,
:lang(ar) .feedback-toast {
    right: auto;
    left: 16px;
}

.feedback-toast.visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.feedback-toast-bubble {
    display: flex;
    flex-direction: column;
    gap: 10px;
    box-sizing: border-box;

    padding: 14px 16px;
    border-radius: var(--radius-md);

    background: rgba(10, 31, 15, 0.92);
    border: 1px solid var(--border);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);

    box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}

.feedback-toast-icon {
    font-size: 20px;
}

.feedback-toast-text {
    margin: 0;
    font-size: 14px;
    color: var(--text-main);
    line-height: 1.4;
}

.feedback-toast-actions {
    display: flex;
    gap: 8px;
}

.feedback-toast-yes,
.feedback-toast-later {
    flex: 1;
    padding: 8px 10px;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    transition: .2s;
}

.feedback-toast-yes {
    background: var(--accent);
    color: white;
}

.feedback-toast-yes:hover {
    opacity: .85;
}

.feedback-toast-later {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-muted);
}

.feedback-toast-later:hover {
    background: rgba(255, 255, 255, 0.14);
}

@media (max-width: 600px) {
    .feedback-toast {
        left: 12px;
        right: 12px;
        max-width: none;
    }

    :lang(fa) .feedback-toast,
    :lang(ar) .feedback-toast {
        left: 12px;
        right: 12px;
    }
}

/* ── Achievement Unlock toast (js/ui/achievementNotification-ui.js) ──
   Same fixed-position fade/slide lifecycle as .feedback-toast above,
   anchored top-center instead of bottom-right so it never collides
   with the feedback toast or the in-game action bar. */

.achievement-toast {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translate(-50%, -16px);
    z-index: 1600;

    width: min(360px, calc(100% - 24px));

    opacity: 0;
    transition: opacity .25s ease, transform .25s ease;

    pointer-events: none;
}

.achievement-toast.visible {
    opacity: 1;
    transform: translate(-50%, 0);
    pointer-events: auto;
}

.achievement-toast-bubble {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    box-sizing: border-box;

    padding: 14px 16px;
    border-radius: var(--radius-md);

    background: linear-gradient(135deg, rgba(255, 199, 44, 0.16), rgba(10, 31, 15, 0.94));
    border: 1px solid rgba(255, 199, 44, 0.55);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);

    box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}

.achievement-toast-icon {
    font-size: 28px;
    line-height: 1;
    flex-shrink: 0;
}

.achievement-toast-body {
    flex: 1;
    min-width: 0;
}

.achievement-toast-eyebrow {
    margin: 0 0 2px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .02em;
    color: #ffc72c;
    text-transform: uppercase;
}

.achievement-toast-title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-main);
    line-height: 1.3;
}

.achievement-toast-desc {
    margin: 2px 0 0;
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.35;
}

.achievement-toast-close {
    flex-shrink: 0;
    background: transparent;
    border: none;
    cursor: pointer;
    opacity: .7;
    padding: 2px;
}

.achievement-toast-close:hover {
    opacity: 1;
}

@media (max-width: 600px) {
    .achievement-toast {
        width: calc(100% - 24px);
    }
}

/* ══════════════════════════════════════════════════════════
   ACHIEVEMENT COLLECTION (see index.html #profileAchievements,
   js/ui/profile-ui.js renderAchievements()/renderAchievementCard())

   A game-quality collection UI, not a settings list: header summary +
   overall progress bar, an optional "Recently Unlocked" featured card,
   category filter tabs, then a responsive card grid. All colors/radii/
   shadows reuse the existing design tokens from :root — no parallel
   token system. Locked/unlocked/progress are always communicated with
   an icon + text label, never color alone.
   ══════════════════════════════════════════════════════════ */

.ach-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    text-align: center;
}

.profile-achievements-title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

.ach-header-icon {
    font-size: 16px;
    line-height: 1;
}

.profile-achievements-summary {
    margin: 0;
    font-size: 13px;
    color: var(--text-muted);
}

/* ── Overall progress bar ── */
.ach-progress {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ach-progress-label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 11.5px;
}

.ach-progress-label {
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.ach-progress-pct {
    color: var(--text-main);
    font-weight: 700;
}

.ach-progress-track {
    width: 100%;
    height: 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid var(--border);
    overflow: hidden;
}

.ach-progress-fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--accent), #ffc72c);
    transition: width 0.5s cubic-bezier(.4,0,.2,1);
}

/* ── Featured / "Recently Unlocked" ──
   Only ever shown when real unlock data exists (see
   renderAchievements()) — the section itself stays .hidden otherwise. */
.ach-featured {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ach-featured-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #ffc72c;
}

.ach-featured-card .ach-card {
    animation: ach-featured-in 0.4s cubic-bezier(.4,0,.2,1);
}

@keyframes ach-featured-in {
    from { opacity: 0; transform: translateY(4px) scale(.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── Category filter tabs ── */
.ach-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
}

.ach-filter {
    padding: 5px 12px;
    font-size: 11.5px;
    font-weight: 600;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.ach-filter:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-main);
}

.ach-filter.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.ach-filter:focus-visible,
.ach-card:focus-visible {
    outline: 2px solid #ffc72c;
    outline-offset: 2px;
}

/* ── Card grid ──
   auto-fill/minmax reflows naturally from a single mobile-landscape
   column up to several desktop columns with no per-breakpoint rules
   needed — see the max-width media query below only for a floor on
   very narrow mobile-landscape heights.

   No independent scrolling/max-height here: `.ach-grid` sits inside
   Profile's `.modal-body` (see index.html #profileAchievementsList),
   which is already the popup's one dedicated scroll container (base
   `.modal-content > .modal-body` rule above). Giving this grid its
   own `overflow-y: auto` + `max-height` made it a second, independent
   scroll container nested inside `.modal-body`'s — the exact same bug
   `#animalGrid` had (see the Card Guide fix note further down this
   file) — so a swipe starting on an achievement card could scroll a
   tiny fixed-height box instead of the popup, and content past that
   box's height was unreachable. Letting the grid size to its full
   content height (`overflow: visible`, the default) means Achievements
   contributes to `.modal-body`'s natural height instead, exactly like
   Card Guide's Animal Grid already does. */
.ach-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
    gap: 10px;
    padding: 2px;
}

.ach-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;

    padding: 12px 8px 10px;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.ach-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-card);
}

.ach-card--filtered-out {
    display: none;
}

/* Unlocked state — communicated via a stronger icon presentation, a
   completed badge/status pill, and a subtle warm border/glow, never by
   color alone (the badge icon + status text carry the meaning). */
.ach-card.unlocked {
    background: rgba(255, 199, 44, 0.08);
    border-color: rgba(255, 199, 44, 0.4);
}

.ach-card.locked {
    opacity: 0.82;
}

.ach-card-icon-wrap {
    position: relative;
    width: 46px;
    height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border);
}

.ach-card.unlocked .ach-card-icon-wrap {
    background: rgba(255, 199, 44, 0.15);
    border-color: rgba(255, 199, 44, 0.5);
    box-shadow: 0 0 0 4px rgba(255, 199, 44, 0.08);
}

.ach-card-icon {
    font-size: 24px;
    line-height: 1;
    opacity: .6;
}

.ach-card.unlocked .ach-card-icon {
    opacity: 1;
}

.ach-card-badge {
    position: absolute;
    bottom: -4px;
    right: -4px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    border-radius: 50%;
    background: var(--bg-main);
    border: 1px solid var(--border);
}

.ach-card.unlocked .ach-card-badge {
    border-color: rgba(74, 222, 128, 0.5);
}

.ach-card-title {
    margin: 4px 0 0;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--text-main);
}

.ach-card.locked .ach-card-title {
    color: var(--text-muted);
}

.ach-card-desc {
    margin: 0;
    font-size: 10.5px;
    line-height: 1.3;
    color: var(--text-muted);
}

.ach-card-progress {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 2px;
}

.ach-card-progress-track {
    width: 100%;
    height: 5px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.ach-card-progress-fill {
    height: 100%;
    border-radius: 999px;
    background: var(--accent);
    transition: width 0.4s cubic-bezier(.4,0,.2,1);
}

.ach-card-progress-label {
    font-size: 10px;
    font-weight: 700;
    color: #ffc72c;
}

.ach-card-unlockdate {
    margin: 2px 0 0;
    font-size: 9.5px;
    color: var(--text-muted);
}

.ach-card-status {
    margin-top: 4px;
    font-size: 9.5px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-muted);
}

.ach-card.unlocked .ach-card-status {
    background: rgba(74, 222, 128, 0.18);
    color: #4ade80;
}

/* Featured card variant: same card, slightly larger/centered, no
   duplicate rules needed since it reuses .ach-card directly. */
.ach-featured-card .ach-card {
    max-width: 220px;
    margin: 0 auto;
    padding: 16px 12px 12px;
}

.ach-featured-card .ach-card-icon-wrap {
    width: 56px;
    height: 56px;
}

.ach-featured-card .ach-card-icon {
    font-size: 28px;
}

@media (prefers-reduced-motion: reduce) {
    .ach-progress-fill,
    .ach-card-progress-fill,
    .ach-card,
    .ach-filter {
        transition: none;
    }
    .ach-featured-card .ach-card {
        animation: none;
    }
}

/* ── Mobile landscape (the game is landscape-only — see
   js/ui/orientation-ui.js) — keep the grid to two columns and trim
   vertical paddings so the whole Achievements section stays reachable
   within a short viewport without introducing horizontal overflow;
   .modal-content's own mobile rule already goes full-width as a
   bottom sheet below 600px. ── */
@media (max-width: 700px) {
    .ach-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .ach-card { padding: 10px 6px 8px; }
    .ach-filters { gap: 5px; }
    .ach-filter { padding: 4px 10px; font-size: 11px; }
}

@media (max-height: 420px) and (orientation: landscape) {
    .ach-featured { display: none; }
}


/* ==========================================================
   HOME / MAIN HUB
   New default landing screen between the splash name-entry
   step and the existing splash->difficulty->match flow.
   Reuses existing tokens (--bg-panel, --radius-*, --shadow-*,
   --accent) and the .screen-overlay/.screen-content/.top-btn
   visual language already established by the splash screen and
   in-game top bar, per docs/UI_UX_PLAN.md secs 1-2, 11-16.
========================================================== */

.home-screen {
    align-items: stretch;
}

.home-content {
    width: 100%;
    height: 100%;
    max-width: 640px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 18px;
    padding: 18px 20px 14px;
    box-sizing: border-box;
    overflow-y: auto;
    background: var(--bg-panel);
}

.home-topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* ── Profile entry point ──────────────────────────────────
   Compact avatar + name chip — the one place on Home that
   surfaces the player's identity (js/services/profile.js).
   Tapping it opens #profileModal (js/ui/profile-ui.js). */
.home-profile-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px 5px 5px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-main);
    font-family: inherit;
    cursor: pointer;
    max-width: 42vw;
    transition: background .18s ease, transform .18s ease;
}

.home-profile-chip:hover {
    background: rgba(255, 255, 255, 0.14);
    transform: translateY(-1px);
}

.home-profile-chip-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(255, 255, 255, 0.1);
    flex-shrink: 0;
}

.home-profile-chip-name {
    font-size: 14px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Currency group — wraps the Coins + Gems pills so .home-topbar's
   space-between still puts exactly two items (profile chip, this
   group) on opposite ends, regardless of how many currencies exist. */
.home-currency-group {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Coin pill — a real, persisted balance (js/services/profile.js),
   defaulting to 0 for every player since nothing can earn/spend it
   yet (see docs/ECONOMY_PLAN.md and the Achievement/Shop/Lucky Wheel
   foundation notes in profile.js). Reused by Store/Rewards once a
   real economy is wired up. */
.home-coin-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-weight: 700;
    font-size: 14px;
    color: var(--text-main);
}

.home-coin-icon {
    font-size: 16px;
    line-height: 1;
}

/* Gem pill — same shape/behavior as the coin pill, tinted toward the
   existing --p4 (purple) player color token rather than a new color
   system, so it reads as a distinct currency without introducing a
   parallel palette. */
.home-gem-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: rgba(var(--p4-rgb), 0.12);
    border: 1px solid rgba(var(--p4-rgb), 0.35);
    border-radius: 999px;
    font-weight: 700;
    font-size: 14px;
    color: var(--text-main);
}

.home-gem-icon {
    font-size: 16px;
    line-height: 1;
}

.home-banner {
    width: min(420px, 78vw);
    max-height: 22vh;
    object-fit: contain;
    margin: 0 auto;
}

/* ── Start Game tabs ──────────────────────────────────────
   Kept as the dominant, vertically-centered focus of Home
   regardless of where the secondary nav/profile chip above it end
   up sizing to (auto margins share the flex column's remaining
   space with .home-bottom-nav's own margin-top: auto). Only Play vs
   Bot is active; Rank/Friendly are real switchable tabs whose panel
   honestly says Coming Soon rather than pretending to start a
   match. */
.home-gamestart {
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: 100%;
    margin-top: auto;
    margin-bottom: auto;
}

.home-gamestart-title {
    margin: 0;
    text-align: center;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--text-muted);
}

.home-tabs {
    display: flex;
    gap: 6px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 4px;
}

.home-tab {
    flex: 1;
    border: none;
    border-radius: calc(var(--radius-md) - 4px);
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-weight: 800;
    font-size: 15px;
    padding: 10px 8px;
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
}

.home-tab:hover {
    color: var(--text);
}

.home-tab[aria-selected="true"] {
    background: linear-gradient(145deg, var(--accent), #8f4527);
    color: #fff;
}

.home-tab-panel {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.home-tab-panel.hidden {
    display: none;
}

.home-tab-comingsoon {
    margin: 0;
    text-align: center;
    color: var(--text-muted);
    font-size: 15px;
    padding: 22px 12px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px dashed var(--border);
    border-radius: var(--radius-md);
}

.home-primary-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    border: none;
    border-radius: var(--radius-md);
    padding: 18px 24px;
    font-size: 19px;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    transition: transform .18s ease, box-shadow .18s ease, background .18s ease;
}

.home-play-btn {
    background: linear-gradient(145deg, var(--accent), #8f4527);
    color: #fff;
    box-shadow: var(--shadow-card);
    font-size: 22px;
    padding: 22px 24px;
}

.home-play-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.45);
}

.home-btn-icon {
    font-size: 1.1em;
    line-height: 1;
}

.home-coming-soon-tag {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .3px;
    text-transform: uppercase;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: var(--text-muted);
    padding: 2px 6px;
    border-radius: 999px;
    white-space: nowrap;
}

/* Coming Soon badge: a small corner badge attached to the slot it
   belongs to, not a primary text block inside the button — see
   .home-bottom-btn below (the only place this tag currently
   renders). Kept as its own selector (not folded into the base
   rule above) so any future non-badge use of .home-coming-soon-tag
   is unaffected. */
.home-bottom-btn {
    position: relative;
}

.home-bottom-btn .home-coming-soon-tag {
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 7px;
    padding: 1px 5px;
    pointer-events: none;
    max-width: calc(100% - 8px);
    overflow: hidden;
    text-overflow: ellipsis;
}

:lang(fa) .home-bottom-btn .home-coming-soon-tag,
:lang(ar) .home-bottom-btn .home-coming-soon-tag {
    right: auto;
    left: 4px;
}

/* ── Secondary nav row ────────────────────────────────────
   Same icon-button visual language as the in-game top bar
   (.top-btn), extended with a text label since these sit on
   their own screen rather than a cramped top bar. */
.home-secondary-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 10px;
}

.home-nav-btn {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--text-main);
    padding: 12px 8px 10px;
    min-height: 76px;
    cursor: pointer;
    font-family: inherit;
    transition: background .18s ease, transform .18s ease;
}

.home-nav-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateY(-2px);
}

.home-nav-icon {
    font-size: 22px;
    line-height: 1;
    min-height: 2em; /* reserve the icon's box even if the image
                         404s and js/ui/icon-ui.js clears it, so a
                         missing icon doesn't collapse the button and
                         throw the row out of alignment (see the
                         "How to Play" button). */
    display: flex;
    align-items: center;
    justify-content: center;
}

.home-nav-label {
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    line-height: 1.25;
}

.home-nav-soon {
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 8px;
    font-weight: 700;
    text-transform: uppercase;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 6px;
    padding: 2px 5px;
    color: var(--text-muted);
    letter-spacing: .3px;
}

/* ── Bottom nav (Store / Tournament / Leaderboard) ───────── */
.home-bottom-nav {
    margin-top: auto;
    display: grid;
    /* Same auto-fit sizing strategy as .home-secondary-row (left side)
       instead of a fixed 3-column grid, so a 4th entry (Lucky Wheel)
       wraps into the same balanced row shape rather than orphaning
       onto its own half-empty row. */
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 8px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
}

/* Same visual language as .home-nav-btn (left-side secondary nav) —
   background, border, radius, padding, min-height, typography — so
   the right-side Store/Tournament/Leaderboard/Lucky Wheel buttons
   read as the same navigation system rather than a separate,
   flatter component. */
.home-bottom-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 12px 8px 10px;
    min-height: 76px;
    cursor: pointer;
    transition: background .18s ease, transform .18s ease;
}

.home-bottom-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateY(-2px);
    color: var(--text-main);
}

.home-bottom-icon {
    font-size: 22px;
    line-height: 1;
    min-height: 2em;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ── Disabled-state primitive (reused wherever a Home feature
   is gated: Online Game today, future locked nav entries) ── */
[aria-disabled="true"] {
    opacity: .72;
}

/* ── Keyboard focus (Home introduces plain <button> elements
   that had no prior focus-visible treatment in this project) ── */
.home-primary-btn:focus-visible,
.home-nav-btn:focus-visible,
.home-bottom-btn:focus-visible,
.home-coin-pill:focus-visible,
.home-gem-pill:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* ── Responsive ───────────────────────────────────────────
   Mirrors the existing splash-screen breakpoints so Home reads
   as part of the same shell rather than a bolted-on screen. */
@media (max-width: 600px) {
    .home-content {
        padding: 14px 14px 10px;
        gap: 14px;
    }

    .home-banner {
        width: 82vw;
        max-height: 16vh;
    }

    .home-primary-btn {
        padding: 16px 18px;
    }

    .home-play-btn {
        font-size: 19px;
        padding: 18px 18px;
    }

    /* .home-secondary-row keeps its base auto-fit grid — a forced
       2-column override here used to orphan the 3rd button (Card
       Guide / Settings / How to Play) onto its own half-empty row on
       every portrait phone, since 84px×3 + gaps already fits well
       under 320px of content width. auto-fit already reflows
       correctly for any future button count without a fixed
       breakpoint. */    .home-coin-pill,
    .home-gem-pill {
        padding: 5px 10px;
        font-size: 12.5px;
    }

    .home-currency-group {
        gap: 6px;
    }
}

@media (min-width: 900px) {
    .home-gamestart {
        max-width: 420px;
        margin-left: auto;
        margin-right: auto;
    }
}

/* Mobile landscape (phones rotated — short viewport height): the
   stacked banner + 3-up row + play section + bottom nav can add up
   to more than ~375-430px of height. .home-content already scrolls
   (overflow-y:auto, set unconditionally — see base rule), so nothing
   is ever unreachable, but shrinking the banner and gaps here means
   most phones fit without needing to scroll at all. */
@media (max-height: 480px) and (orientation: landscape) {
    .home-content {
        padding: 10px 16px 8px;
        gap: 10px;
    }

    .home-banner {
        max-height: 13vh;
        width: min(360px, 55vw);
    }

    .home-nav-btn,
    .home-bottom-btn {
        min-height: 56px;
        padding: 8px 8px 7px;
    }

    .home-gamestart {
        gap: 8px;
    }

    .home-bottom-nav {
        margin-top: 10px;
        padding-top: 8px;
    }
}

/* RTL (Persian/Arabic) — reuse the same button/icon layout since
   flex/grid already flip correctly under dir="rtl"; only the
   coming-soon badge's absolute offset needs mirroring. */
:lang(fa) .home-nav-soon,
:lang(ar) .home-nav-soon {
    right: auto;
    left: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .home-play-btn,
    .home-nav-btn,
    .home-bottom-btn {
        transition: none;
    }

    .home-play-btn:hover,
    .home-nav-btn:hover {
        transform: none;
    }
}


/* ==========================================================
   LANDSCAPE-ONLY MOBILE — NO-SCROLL LAYOUT LAYER
   ----------------------------------------------------------
   Wild Guest List is landscape-only on touch devices (see
   js/ui/orientation-ui.js — portrait is gated with a "please
   rotate" overlay before any of this is ever seen). Everything
   below only ever applies once the device is confirmed
   landscape + touch, so it never touches desktop/laptop layouts
   (fine pointer) regardless of window shape.

   Why this is a SEPARATE layer from the existing
   `@media (max-width: 600px)` mobile rules above, instead of
   editing them in place: those rules key on narrow WIDTH, which
   correctly targets a portrait phone (e.g. 390×844) but never
   fires for a landscape phone (e.g. 844×390) — same device,
   same short dimension, but it's now the HEIGHT that's small,
   not the width. Left as-is, a landscape phone at 700-930px
   wide falls through to the tablet/desktop sidebar layout
   below, which assumes far more vertical room than a phone in
   landscape actually has — that mismatch is the root cause of
   the "desktop UI squeezed into a small viewport, needs
   scrolling" problem this section fixes. Keying on
   `(pointer: coarse) and (orientation: landscape)` instead
   targets the actual constraint (short viewport, touch input)
   regardless of width, and stacks under three height tiers
   mirroring the sizes called out for testing:
     - base tier:            up to ~500px tall (932×430 and down)
     - standard tier (≤440): 667×375 / 844×390
     - small tier   (≤340):  568×320
   Scrolling is not used as the fix for oversized content on the
   top-level screens below (Home, Choose Bot Difficulty, End Game,
   etc.) — each panel is resized/restructured to fit. Popups are
   different: `.modal-body` (see the base .modal-content > .modal-body
   rule above) is the dedicated internal-scroll container for any
   popup content that doesn't reliably fit after compaction — Card
   Guide's Animal Ability grid and Profile's Achievements list in
   particular are genuinely open-ended (their length depends on the
   card set / what the player has unlocked), so they rely on real
   scrolling here rather than a "safety net". The popup HEADER never
   scrolls (flex: 0 0 auto); only its .modal-body does — see
   README.md § Responsive Design / Panel Architecture.
========================================================== */

@media (pointer: coarse) and (orientation: landscape) {

    html, body {
        overflow: hidden;
        height: 100%;
    }

    /* ── Shared shells (Home, Choose Bot Difficulty, End Game,
       Coming Soon, guidance prompts, every top-level .screen-overlay
       page) — stop relying on page-level scroll as the fit strategy;
       each concrete screen below is resized to actually fit. ── */
    .screen-content {
        overflow-y: hidden;
        padding: 10px 16px;
    }

    .screen-content--panel .screen-panel-scroll {
        overflow-y: hidden;
    }

    /* Equal left/right breathing room, responsive rather than a fixed
       px margin that breaks at different widths — .modal already
       flex-centers this, so this just guarantees the width itself
       stays symmetric and never gets edge-to-edge on short screens. */
    .modal-content {
        max-height: 94dvh;
        width: calc(100% - 12dvw);
        max-width: 640px;
        margin: 0 auto;
    }

    /* Pause popup: icons were reusing the cramped top-bar .top-btn
       size while the label stayed full-size, so the icon read as too
       small next to its text. Grown independently here to a balanced
       icon:label ratio (roughly the same ratio the desktop pause
       panel already uses). */
    .pause-actions { gap: clamp(10px, 3dvh, 20px); }

    .pause-action-icon.top-btn {
        width: clamp(34px, 9dvh, 46px) !important;
        height: clamp(34px, 9dvh, 46px) !important;
        font-size: 20px;
    }

    .pause-action-label {
        font-size: clamp(11px, 2.6dvh, 14px);
    }

    /* .modal-body is the intended internal-scroll container (see the
       base .modal-content > .modal-body rule above: flex:1 1 auto;
       min-height:0; overflow-y:auto — the standard fix for the
       flexbox "min-height:auto" trap this section's own comment
       warns about). This landscape layer previously forced it to
       overflow-y:hidden, which was harmless while only Feedback's
       short, always-fits form used .modal-body, but became a real
       regression once Settings/Profile/Card Guide/About/Lucky Wheel
       (see Home menu popup standardization) opted into the same
       architecture: Card Guide's Animal Ability grid and Profile's
       Achievements section could silently overflow past the popup's
       bounded landscape height with no way to reach them — the
       #animalGrid/.ach-grid overflow-auto "safety net" below never
       actually engaged, because their own parent (this element) was
       clipping them before their own overflow could ever matter.
       Keeping this as plain overflow-y:auto (matching the base rule,
       just restated here for clarity) means: content that already
       fits after compaction shows no scrollbar and behaves exactly
       as before, and content that doesn't fit scrolls internally
       instead of being clipped — the page/body itself (html, body
       {overflow:hidden} above) still never scrolls. */
    .modal-content > .modal-body,
    .modal-content > .modal-form > .modal-body {
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Achievements and Card Guide are the two screens whose content
       length genuinely depends on how much the player has unlocked /
       how many cards the game has — real, growing lists rather than a
       fixed composition. The grid sizing right below aims to fit the
       common case (a season's worth of achievements, the current
       card set) so scrolling is rarely needed in practice. The actual
       scrolling, when it is needed, happens on the shared .modal-body
       ancestor above (both grids sit inside one) — or, for game.html's
       in-game Help modal, which never opted into .modal-body, on
       .modal-content itself (base rule: `overflow-y: auto`), which
       scrolls as one box exactly as before.

       Fix — Profile → Achievements had its own nested scroll container
       on Mobile, especially visible on Android (unify-mobile-popup-
       scroll task): `.ach-grid` used to keep its own `overflow-y: auto`
       here even after #animalGrid's identical bug (below) was fixed,
       on the stated basis that it was "unrelated UI". It wasn't — same
       architecture, same bug: a flex item with non-`visible` overflow
       nested inside `.modal-body`'s own scroll container is a second,
       independent scrollbar, so a swipe over an Achievement card
       scrolled `.ach-grid` in place instead of the popup, and
       Achievements past its fixed max-height (removed above, alongside
       this rule) could become unreachable. Removed so `.ach-grid` uses
       default `overflow: visible` and sizes to its full content height,
       exactly like #animalGrid — the ONLY scroll container for both
       popups is `.modal-body`. */

    /* Fix — Card Guide Animal Ability grid empty on Mobile (1.30.5),
       revised (1.30.6): #animalGrid is a flex item of a column flex
       container (.help-body on index.html; .modal-content.help-layout
       directly on game.html). Giving it its OWN overflow-y:auto (as it
       had until 1.30.4) made it a second, independent scroll container
       nested inside .modal-body's scroll container — two separate
       scrollbars/scroll positions for what the user experiences as one
       popup. Combined with flexbox's rule that a flex item with
       non-`visible` overflow gets an automatic min-height of 0 instead
       of a content-based one, the mobile-landscape layer's compacted
       height let flex-shrink collapse #animalGrid to 0px tall, clipping
       every card out of view even though they rendered at full size.
       1.30.5 patched the collapse with `min-height: min-content` but
       kept the second scroll container. The correct fix is to remove
       #animalGrid's own scrolling entirely and let it size to its full
       content height, so the ONLY scroll container is the popup's own
       .modal-body — exactly like Desktop already does, and exactly the
       "Header / Scrollable Body / Fixed Footer" architecture documented
       in README.md. No overflow property here now means #animalGrid
       uses default `overflow: visible`, which also restores its normal
       content-based automatic minimum size — the flex-shrink collapse
       fix and the "one scrollbar" fix are the same change. `.ach-grid`
       (Profile → Achievements) had the identical bug — see the fix
       note above this one — and got the identical treatment. */
    #animalGrid {
        overflow: visible;
    }

    /* ── HOME ──────────────────────────────────────────────────
       Re-composed from a 5-row vertical stack (topbar / banner /
       secondary-nav / gamestart / bottom-nav) into a 3-row grid:
       top bar spanning full width (with the logo centered inside
       that same row, overlapping via a shared grid-area — see
       below), a middle row with secondary nav + game-mode tabs,
       and the bottom row. No markup changes needed: grid-area
       placement below works regardless of DOM order.

       `.home-content`'s own base rule caps `max-width: 640px` for
       portrait phones, which would otherwise leave this whole grid
       stranded in a narrow column with the dark `.screen-content`
       background showing as empty space on both sides — override it
       here so the grid genuinely fills the landscape viewport. */
    /* 3-column grid with the SAME minmax() track on both side columns
       — that symmetry is what keeps "gamestart" mathematically
       centered on the true viewport center, regardless of what the
       left/right nav groups contain. A flex `justify-content:
       space-between` layout can't guarantee this: it centers relative
       to the leftover space, which shifts as soon as the two side
       groups differ in width. Store/Tournament/Leaderboard/Lucky
       Wheel move from a full-width bottom row into this new right
       ("bottom" grid-area, kept as the id/class name so JS wiring in
       js/ui/home-ui.js needs no changes) column. */
    .home-content {
        max-width: none;
        display: grid;
        grid-template-columns: minmax(96px, 152px) 1fr minmax(96px, 152px);
        grid-template-rows: auto 1fr;
        grid-template-areas:
            "topbar    topbar    topbar"
            "secondary gamestart bottom";
        align-items: center;
        gap: 8px;
        padding: 8px 14px;
        overflow: hidden;
        height: 100dvh;
        box-sizing: border-box;
    }

    .home-topbar   { grid-area: topbar; }
    .home-secondary-row { grid-area: secondary; align-self: center; }
    .home-gamestart {
        grid-area: gamestart;
        margin: 0;
        justify-self: center;
        width: 100%;
        max-width: 360px;
    }
    .home-bottom-nav {
        grid-area: bottom;
        margin-top: 0;
        align-self: center;
        grid-template-columns: 1fr;
        border-top: none;
        padding-top: 0;
        gap: 6px;
    }

    /* The logo shares the SAME grid cell as the top bar (both
       assigned `grid-area: topbar`) rather than getting its own
       column — grid allows multiple items in one area, so they
       stack in that cell instead of each claiming separate space.
       `.home-topbar`'s own children (profile chip, currency pills)
       keep `justify-content: space-between`, pushing them to the
       left/right edges of the cell; the logo is centered within the
       same cell on top, giving a true top-center logo without
       needing a wrapping element around all three. */
    .home-banner {
        grid-area: topbar;
        justify-self: center;
        align-self: center;
        width: min(150px, 32vw);
        max-height: 9dvh;
        pointer-events: none;
    }

    .home-secondary-row {
        grid-template-columns: 1fr;
        gap: 6px;
        align-content: center;
    }

    .home-nav-btn {
        flex-direction: row;
        justify-content: flex-start;
        min-height: 0;
        padding: 6px 10px;
        gap: 8px;
    }

    .home-nav-icon { font-size: 16px; min-height: 0; }
    .home-nav-label { font-size: 11px; }

    .home-gamestart-title { font-size: 11px; margin-bottom: 2px; }
    .home-tabs { padding: 3px; }
    .home-tab { padding: 6px 6px; font-size: 13px; }

    .home-primary-btn { padding: 10px 16px; }
    .home-play-btn { font-size: 16px; padding: 12px 16px; }

    .home-tab-comingsoon { padding: 10px 10px; font-size: 12px; }

    /* Same compact icon-left/label-right row shape as .home-nav-btn
       just above, so the new right-side column reads as one
       consistent secondary-nav language rather than two different
       button styles. */
    .home-bottom-btn {
        flex-direction: row;
        justify-content: flex-start;
        min-height: 0;
        padding: 6px 8px;
        font-size: 10px;
        gap: 6px;
    }
    .home-bottom-icon { font-size: 15px; min-height: 0; }
    /* Badge stays a corner badge (see base rule) instead of an
       inline margin-left:auto tag, so it reads the same
       icon+label+corner-badge shape at every breakpoint. */
    .home-bottom-btn .home-coming-soon-tag {
        font-size: 6px;
        padding: 1px 4px;
        top: 3px;
        right: 3px;
    }
    :lang(fa) .home-bottom-btn .home-coming-soon-tag,
    :lang(ar) .home-bottom-btn .home-coming-soon-tag {
        right: auto;
        left: 3px;
    }

    .home-profile-chip { padding: 3px 8px 3px 3px; }
    .home-profile-chip-avatar { width: 22px; height: 22px; }
    .home-profile-chip-name { font-size: 12px; }
    .home-coin-pill, .home-gem-pill { padding: 3px 8px; font-size: 11px; }

    /* ── CHOOSE BOT DIFFICULTY ─────────────────────────────────
       All three bot rows + the read-only player row + the Play
       footer must be visible with no scrolling — compact every row
       so 4 rows total fit inside the remaining height once the
       header/footer are shrunk. */
    .screen-panel-header { padding: 6px 4px 4px; }
    .screen-panel-header h2 { font-size: clamp(16px, 3.4vh, 22px); margin: 0 0 2px; }
    .diff-subtitle { font-size: 11px; margin: 0; }

    .screen-panel-scroll {
        padding-top: 4px;
        padding-bottom: 4px;
        /* Stretch to fill the vertical space actually available
           between the header and the Play footer, and lay its one
           child (#difficultyPanel) out as a column that can be told
           to fill that same height below. */
        display: flex;
        flex-direction: column;
    }

    /* Recalculated slot heights: the player row + 3 bot rows now
       share the full height of .screen-panel-scroll equally (flex:1
       each, below) instead of sizing to their own content — this is
       what removes the large empty gap that used to sit between the
       last bot slot and the Play button on short landscape screens,
       and what lets the bot section genuinely fill the space the
       header/footer leave available. */
    #difficultyPanel {
        gap: 6px;
        flex: 1 1 auto;
        min-height: 100%;
    }

    .bot-row {
        /* align-items: center (base .bot-row rule) already centers
           each row's content vertically within its now-taller slot. */
        flex: 1 1 0;
        min-height: 0;
        padding: 5px 12px;
        gap: 10px;
        border-radius: var(--radius-sm);
    }

    .bot-avatar, .player-avatar-mount, .avatar-trigger-mount {
        width: 34px;
        font-size: 22px;
    }

    .player-avatar-display, .avatar-trigger-btn {
        width: 34px;
        height: 34px;
    }

    .bot-name { font-size: 12px; margin-bottom: 3px; }
    .diff-btn { padding: 4px 6px; font-size: 10px; }

    .avatar-choice { width: 34px; height: 34px; }

    .screen-panel-footer { padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px)); }
    .screen-panel-footer .screen-btn { margin-top: 0; padding: 8px 24px; font-size: 15px; }

    /* ── GAME BOARD ────────────────────────────────────────────
       Left-side rail (Leaderboard / Party / Trash as compact
       buttons, each opening its own popup — none permanently
       visible) beside the main gameplay column (Other Players row,
       Queue, Player Hand stacked in that order). `#gameLayout` is a
       2-column grid: the rail and `#centerArea` are its only two
       grid items — `#mobileLeaderboard`/`#partyArea`/`#trashArea`
       are `position: fixed` overlays, which CSS Grid excludes from
       layout entirely, so they don't consume a grid cell regardless
       of where they sit in the DOM. */
    .mobile-only-btn { display: flex; }

    /* Two older `@media (max-width: 600px)` rules force-hide
       #leaderboardBtn with !important — leftover from when this id
       had no matching element and the leaderboard was inline-only
       (see the Home/Panel Architecture sections above). At the
       smallest tested landscape width (568×320), that old rule's
       width condition and this Landscape layer's condition are both
       true at once, so it would otherwise win and hide the button
       here too; !important + later source order is what overrides
       it back to visible. */
    #leaderboardBtn { display: flex !important; }

    #pageLayout {
        display: block;
        padding: 0;
        height: 100dvh;
        min-height: 0;
        overflow: hidden;
    }

    #leftSidebar { display: none; }

    #gameColumn {
        display: flex;
        flex-direction: column;
        height: 100dvh;
        overflow: hidden;
    }

    #topBar {
        position: relative;
        margin-bottom: 0;
        flex: 0 0 auto;
    }

    #topBarContent {
        display: grid !important;
        grid-template-areas: "left logo right" !important;
        grid-template-columns: auto 1fr auto !important;
        grid-template-rows: auto !important;
        height: auto !important;
        /* Real top safe-space (env() for notches/status bars, with a
           sane minimum on devices that report 0) instead of the old
           3px sliver — the header no longer touches the top edge. */
        padding: max(8px, env(safe-area-inset-top, 0px)) 12px 6px !important;
        gap: 0 8px;
        align-items: center;
    }

    /* Logo brought up to roughly Home's own scale (.home-banner uses
       max-height: 9dvh at this same tier) so it doesn't suddenly look
       tiny compared to Home when entering the game. */
    #topCenter { grid-area: logo !important; }
    #topCenter picture img { height: clamp(26px, 9dvh, 46px) !important; width: auto; }

    #topLeft {
        grid-area: left !important;
        flex-direction: row !important;
        gap: 10px !important;
        align-items: center !important;
    }

    /* TURN | ROUND | TIMER — both dividers now read as the same
       vertical-bar language. .round-timer-sep is already a plain "|"
       character between Round and Timer; .turn-divider (a desktop
       horizontal rule, `display: none` on the older mobile-portrait
       tier) is restyled into a matching vertical bar here instead of
       being left to render as a stray horizontal line in a row
       layout. */
    .turn-divider {
        display: block !important;
        width: 1px !important;
        height: 1.5em;
        background: rgba(255,255,255,.3);
        margin: 0 !important;
    }

    .turn-label, .round-label, .turn-timer-label { font-size: clamp(9px, 2dvh, 12px) !important; }

    #topRight { grid-area: right !important; gap: 4px !important; }

    .top-btn {
        width: clamp(22px, 5.5dvh, 28px) !important;
        height: clamp(22px, 5.5dvh, 28px) !important;
        font-size: 11px;
    }

    #gameLayout {
        display: grid !important;
        grid-template-columns: minmax(58px, 84px) 1fr;
        align-items: stretch;
        flex: 1 1 auto;
        min-height: 0;
        overflow: hidden;
        gap: 6px;
        padding: 4px 8px 6px;
    }

    /* ── Left rail: Leaderboard / Log / Chat ──
       Three compact vertical buttons, none permanently occupying
       gameplay space. Leaderboard toggles its own popup; Log opens
       the shared #logModal; Chat just surfaces "Coming Soon" (all
       wired in js/ui/mobile-ui.js). Party/Trash are intentionally not
       here — they open from the door/trash icons flanking the Queue
       instead (see .queue-icon below). */
    #mobileSideRail {
        display: flex;
        flex-direction: column;
        gap: 6px;
        min-width: 0;
    }

    /* #mobileTabs (Party/Trash) is deliberately left at its base
       `display: none` here — Party/Trash access moved to the
       queue-adjacent door/trash icons (see .queue-icon above), so
       this rail no longer carries separate Party/Trash buttons. The
       rail is now Leaderboard → Log → Chat, in that order. */

    #leaderboardBtn, #railLogBtn, #railChatBtn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        padding: 6px 2px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: #0d1a0d;
        color: white;
        cursor: pointer;
        font-size: 9px;
        line-height: 1.15;
        text-align: center;
        box-sizing: border-box;
        width: 100%;
    }

    #leaderboardBtn [data-icon], #railLogBtn [data-icon], #railChatBtn [data-icon] {
        font-size: 15px;
    }

    #leaderboardBtn.active {
        border-color: var(--accent);
        background: rgba(189,93,56,.2);
    }

    #railLogBtn:hover, #railChatBtn:hover {
        background: #132213;
    }

    /* ── Leaderboard / Party / Trash popups ──
       Hidden by default — the base (desktop) rule for
       #partyArea/#trashArea is an always-visible sidebar panel
       (display: flex), and #mobileLeaderboard's base rule is a
       permanently-visible inline block; both are explicitly
       overridden to `none` here, or they render as permanent bars
       instead of tap-to-open overlays. JS toggles the shared
       `.mobile-open` class (see js/ui/mobile-ui.js's initMobileTabs,
       which now groups all three as one open-one-at-a-time set) —
       this layer only handles sizing once open, fitting the
       landscape viewport without page-level scroll via a compact
       layout rather than `overflow-y: auto`.

       `top`/`bottom` (4dvh each) plus the explicit `max-height` below
       define the MAXIMUM available band — the same role `88dvh` plays
       for `.modal-content` above — not a forced size. `height` is left
       at its default `auto`, so the box only grows to fit its actual
       header + card grid, and `margin: auto 0` (vertical auto-margins
       only; the fixed `left`/`right` keep the width unchanged) centers
       that shrink-to-fit box within the band instead of stretching it
       to fill it. Root cause of the old bottom-heavy look: with no
       `margin`/`max-height` override here, this fixed-position box
       (both `top` and `bottom` set) either stretched to fill the whole
       4dvh–4dvh band with `height: auto`, or — once the base (desktop)
       rule's inherited `max-height: calc(100vh - 120px)` clamped it
       shorter than that band on most landscape phones — settled at
       that clamped height anchored to `top` alone (per the CSS2.1
       over-constrained rule, an unset `bottom` margin makes `bottom`
       itself the ignored value). Either way the result was the same:
       Party/Trash's actual content (often just a couple of cards) sat
       flush against a small top gap while all the slack collected
       below it as one large gap, reading as lopsided padding. Auto
       margins fix both paths at once by centering whatever height the
       box ends up at — content-based or `max-height`-clamped — within
       the band; the `max-height` below replaces the inherited desktop
       one so this rule's own sizing doesn't quietly depend on a value
       tuned for a different (always-visible sidebar) layout. */
    #mobileLeaderboard, #partyArea, #trashArea {
        display: none;
        position: fixed;
        top: 4dvh; left: 6dvw; right: 6dvw; bottom: 4dvh;
        max-height: calc(100dvh - 8dvh);
        margin: auto 0;
        z-index: 3000;
        padding: 8px var(--popup-pad-x);
        overflow: hidden;
    }

    #mobileLeaderboard.mobile-open,
    #partyArea.mobile-open,
    #trashArea.mobile-open {
        display: flex;
        flex-direction: column;
    }

    body.popup-open { overflow: hidden; }

    /* Full-screen dimmed backdrop behind the Leaderboard/Party/Trash
       panel — same "popup overlay covers the viewport" presentation
       as every Home .modal, applied here with a pure-CSS pseudo-
       element (no JS/markup change) keyed off the body.popup-open
       class already toggled by js/ui/mobile-ui.js's initMobileTabs().
       Sits just below the panels' z-index so exactly one panel is
       ever the topmost, dimmed layer. */
    body.popup-open::before {
        content: "";
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, .85);
        backdrop-filter: blur(6px);
        -webkit-backdrop-filter: blur(6px);
        z-index: 2999;
    }

    #mobileLeaderboard .panel-header h3,
    #partyArea h3, #trashArea h3 { margin-bottom: 4px; font-size: 13px; }

    #mobileLeaderboardInline { overflow: hidden; }
    /* flex + min-height:0 gives these a bounded height within the
       column (instead of growing unconstrained), which is what lets
       `overflow-y: auto` actually trigger a scrollbar here instead of
       silently doing nothing while the parent's `overflow: hidden`
       clips the excess. Safety-net scroll, not the primary fix — this
       element (part of the game board itself, not a popup) has no
       ancestor `.modal-body` to defer to the way Achievements'
       `.ach-grid` / Card Guide's `#animalGrid` now do (see the
       unify-mobile-popup-scroll fix above: those two no longer keep
       their own `overflow-y: auto` at all, precisely to avoid a
       second scroll container nested inside `.modal-body`). The
       outer popup's `top`/`bottom`/`max-height` band above already
       comfortably fits a full 12-card party or trash grid at every
       tested landscape size, so this should never actually engage —
       it just prevents clipping instead of a silent overflow if that
       ever changes. */
    #partyCards, #trashCards {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        gap: 4px;
    }

    /* The base .leaderboard-header/.leaderboard-row rule (shared with
       the always-visible desktop sidebar leaderboard) sets
       font-size: 13px and padding: 6px 0 — !important here because
       icons inside each row (.icon-image) are sized in `em`, so
       shrinking the font is what actually shrinks the medal/party/
       power icons too, not just the text. */
    #mobileLeaderboard .leaderboard-header,
    #mobileLeaderboard .leaderboard-row {
        font-size: 11px !important;
        padding: 3px 0 !important;
        gap: 6px !important;
        grid-template-columns: 1fr 44px 44px !important;
    }

    #mobileLeaderboard .leaderboard-header {
        margin-bottom: 4px !important;
    }

    /* ── centerArea / Other Players / Queue / Hand ──
       Source order already IS the required hierarchy (Other
       Players → Queue → Hand are siblings in that DOM order in
       game.html), so no `order` overrides are needed here — each
       just gets a flex-basis share of the remaining height. */
    #centerArea {
        flex: 1 1 auto;
        min-height: 0;
        min-width: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 0;
        gap: 4px;
        overflow: hidden;
    }

    #otherPlayers {
        flex: 0 0 auto;
        display: flex !important;
        flex-direction: row !important;
        justify-content: center;
        align-items: center;
        gap: 10px;
        padding: 0;
        margin: 0;
        /* Clear separation from the (now taller) header, without
           eating into Queue/Hand's share below — responsive so it
           doesn't turn into empty space on the shortest tiers. */
        margin-top: clamp(4px, 2.2dvh, 16px);
    }

    #topPlayer, #leftPlayer, #rightPlayer {
        flex-direction: row;
        gap: 4px;
        width: auto;
    }

    .player-label { font-size: 9px; }

    .other-hand .card-back { width: 14px !important; height: 20px !important; }
    .other-deck-back { width: clamp(28px, 6dvh, 40px) !important; height: clamp(38px, 8dvh, 54px) !important; }
    .other-deck-count { font-size: 10px; }

    /* Queue keeps a smaller share and smaller cards than the Hand
       below it — Player Hand is the higher-priority element per the
       gameplay hierarchy, so it gets more of both. */
    #queueArea {
        flex: 1 1 44%;
        min-height: 0;
        width: 100%;
        padding: 0 8px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    #queue {
        height: 100%;
        align-items: center;
    }

    /* Queue cards ~90% of Player Hand's size (clamp(48/15dvh/90,
       68/21dvh/126) below) — clearly recognizable, still visibly
       secondary to the Hand. */
    #queue .card, .queue-slot {
        width: clamp(44px, 13.5dvh, 82px);
        height: clamp(60px, 19dvh, 114px);
    }

    /* Door (queue entry / Party) and Trash (queue exit) icons sit
       tight against the Queue instead of floating with a large gap,
       and now double as the click targets that open the Party/Trash
       popups (see .queue-icon.active and js/ui/mobile-ui.js) — no
       separate Party/Trash buttons elsewhere. */
    #queueWithIcons { gap: clamp(4px, 1.5dvh, 10px); }

    .queue-icon {
        /* Re-enable — hidden by default (Desktop and every other
           viewport) at the base .queue-icon rule above; this is the
           one place they're meant to render, per this task's own
           Mobile Landscape design (see the base rule's comment for
           why). */
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: clamp(20px, 6.5dvh, 34px);
        padding: 6px;
        border-radius: var(--radius-sm);
        transition: background .15s ease, transform .15s ease;
    }

    .queue-icon:hover,
    .queue-icon:focus-visible {
        background: rgba(255,255,255,.08);
        transform: scale(1.08);
    }

    .queue-icon.active {
        background: rgba(189,93,56,.22);
        box-shadow: inset 0 0 0 1px var(--accent);
    }

    #handArea {
        position: static !important;
        flex: 1 1 56%;
        min-height: 0;
        width: 100%;
        border-top: 1px solid var(--border);
        background: transparent;
        padding: 4px 8px !important;
        display: flex;
        justify-content: center;
        align-items: center;
        gap: clamp(4px, 1.2vw, 10px);
        box-sizing: border-box;
    }

    /* Player Hand cards significantly larger than Queue cards —
       Player Hand is the top-priority gameplay element once
       Leaderboard/Party/Trash stop permanently eating vertical
       space, there's real room to grow it. */
    #playerHand .card-back, .card-back {
        width: clamp(48px, 15dvh, 90px) !important;
        height: clamp(68px, 21dvh, 126px) !important;
    }

    #deckStack { transform: scale(0.85); transform-origin: center; }

    /* ── PROFILE / SETTINGS / CARD GUIDE (small-popup panels) ── */
    .small-popup { padding: 14px 18px; }
    .profile-panel .profile-avatar-grid { gap: 6px; }
}

/* Standard mobile landscape (667×375, 844×390): a touch more room
   than the small tier below, but still tight — one more notch of
   compaction on top of the base tier above. */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 440px) {
    .home-content { padding: 6px 12px; gap: 6px; }
    .home-banner { max-height: 12dvh; }

    .bot-row { padding: 4px 10px; }
    .bot-avatar, .player-avatar-display, .avatar-trigger-btn, .avatar-choice {
        width: 28px; height: 28px; font-size: 18px;
    }

    #topBarContent { padding: max(4px, env(safe-area-inset-top, 0px)) 8px 4px !important; }
    #topCenter picture img { height: clamp(24px, 11dvh, 40px) !important; }
}

/* Small mobile landscape (e.g. 568×320) — the tightest tier called
   out for validation. Every element above shrinks further via its
   own clamp()/dvh sizing already; this tier only trims what those
   formulas can't reach (fixed paddings, decorative gaps). */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 340px) {
    .home-content { padding: 4px 10px; gap: 4px; }
    .home-banner { max-height: 9dvh; width: min(100px, 85%); }
    .home-nav-btn { padding: 4px 8px; }
    .home-gamestart-title { display: none; } /* redundant once tabs are the only content in that column at this size */

    .screen-panel-header { padding: 3px 4px 2px; }
    .bot-row { padding: 3px 8px; gap: 6px; }
    #difficultyPanel { gap: 4px; }

    #topBarContent { padding: max(3px, env(safe-area-inset-top, 0px)) 6px 2px !important; }
    #gameLayout { padding: 1px 6px 2px; }
    #otherPlayers { padding: 0; }
}
