@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Cairo+Play:wght@700&display=swap');

:root {
    color-scheme: dark;

    /* Card face and card edge. These are the same in both themes: a number card
       is white with a navy edge whatever the page behind it looks like. */
    --primary: #ffffff;
    --secondary: #16213e;
    --highlight: #cc3350;   /* the logo red - go, the 7, and anything that stops you */
    --cream: #fff3d6;       /* the logo letters - the dark-mode your-turn glow */
    --success: #4caf50;
    --danger: #cc3350;
    --warning: #ff9800;
    --text-dark: #1a1a2e;   /* the ink on a white card - not the page ink */
    --on-accent: #ffffff;   /* text on a red or coloured fill; never changes */
    --card-gradient: linear-gradient(135deg, #cc3350 0%, #c62f47 100%);
    --glow: 0 0 10px rgba(204, 51, 80, 0.5);

    /* Theme tokens. Dark is the default; html[data-theme="light"] and the
       prefers-color-scheme block below swap every one of these and nothing else.
       The *-rgb triplets exist so the sheet can keep its many rgba() fades:
       rgba(var(--ink-rgb), 0.1) is "ink at 10%" in either theme. */
    --surface-0: #1a1a2e;                 /* the page */
    --surface: #16213e;                   /* panels, popups, the header */
    --surface-2: #0f3460;                 /* wells inside a panel */
    --surface-rgb: 22, 33, 62;
    --surface-2-rgb: 15, 52, 96;
    --gradient-bg: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
    --ink: #ffffff;
    --ink-rgb: 255, 255, 255;
    --ink-muted: rgba(255, 255, 255, 0.6);
    --line: rgba(255, 255, 255, 0.12);
    --line-strong: rgba(255, 255, 255, 0.35);
    --shadow-rgb: 0, 0, 0;                /* box-shadows and darkened wells */
    --scrim-rgb: 0, 0, 0;                 /* the sheet behind a popup */
    --scrim-mul: 1;                       /* light mode thins the scrim */
    --highlight-text: #ffb3c0;            /* red as text on the page */
    --highlight-text-soft: #ffd7de;
    --turn: var(--cream);                 /* the your-turn ring and glow */
    --turn-rgb: 255, 243, 214;
    --turn-ink: var(--text-dark);         /* text on a --turn badge */
    --number-card-shadow: none;           /* light mode lifts white cards off white */

    /* Solid stand-in for surfaces that normally rely on backdrop-filter.
       Used by the @supports fallback below. */
    --surface-solid: rgba(var(--surface-rgb), 0.95);

    /* Spacing - 4px base. The odd values that used to appear inline
       (0.35rem, 0.7rem, 0.9rem) round to the nearest step. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;

    /* Radius - derived from what the sheet actually used.
       15px and 16px were indistinguishable in context and collapse to one step. */
    --radius-xs: 5px;
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-pill: 999px;
    --radius-circle: 50%;

    /* Stacking. Seven named rungs replacing thirteen ad-hoc values that
       reached 20001 purely to beat 20000. Gaps are deliberate - insert
       between rungs rather than inventing a new magic number. */
    --z-base: 0;        /* board, players, cards in hand */
    --z-raised: 10;     /* hover lift, count badges */
    --z-sticky: 100;    /* game header, deck area */
    --z-controls: 200;  /* fixed HIT / Stand bar */
    --z-overlay: 300;   /* scrim behind popups */
    --z-popup: 400;     /* tutorial, round summary, target pickers */
    --z-toast: 500;     /* transient notices, disconnect banner */
}

/* Light mode. The same tokens, different values; nothing below this block
   knows which theme it is in. Two copies of the block because a selector list
   cannot contain a media query: the first is an explicit choice from the
   Settings menu, the second follows the OS when nothing has been chosen.
   font-palette is here too: Cairo Play is a colour font and ignores `color`,
   so its navy twin (defined further down) is picked with the theme. */
html[data-theme="light"] {
    color-scheme: light;
    --surface-0: #eceff5;
    --surface: #ffffff;
    --surface-2: #dfe4ee;
    --surface-rgb: 255, 255, 255;
    --surface-2-rgb: 223, 228, 238;
    --gradient-bg: linear-gradient(135deg, #eceff5 0%, #e3e8f2 100%);
    --ink: #1a1a2e;
    --ink-rgb: 26, 26, 46;
    --ink-muted: rgba(26, 26, 46, 0.62);
    --line: rgba(26, 26, 46, 0.14);
    --line-strong: rgba(26, 26, 46, 0.32);
    --shadow-rgb: 20, 30, 60;
    --scrim-rgb: 20, 30, 60;
    --scrim-mul: 0.6;
    --highlight-text: #a3243e;
    --highlight-text-soft: #8f1f36;
    --turn: #1a1a2e;
    --turn-rgb: 26, 26, 46;
    --turn-ink: #ffffff;
    --number-card-shadow: 0 1px 3px rgba(20, 30, 60, 0.25);
    font-palette: --hit7-flat-ink;
}

@media (prefers-color-scheme: light) {
    html:not([data-theme="dark"]) {
        color-scheme: light;
        --surface-0: #eceff5;
        --surface: #ffffff;
        --surface-2: #dfe4ee;
        --surface-rgb: 255, 255, 255;
        --surface-2-rgb: 223, 228, 238;
        --gradient-bg: linear-gradient(135deg, #eceff5 0%, #e3e8f2 100%);
        --ink: #1a1a2e;
        --ink-rgb: 26, 26, 46;
        --ink-muted: rgba(26, 26, 46, 0.62);
        --line: rgba(26, 26, 46, 0.14);
        --line-strong: rgba(26, 26, 46, 0.32);
        --shadow-rgb: 20, 30, 60;
        --scrim-rgb: 20, 30, 60;
        --scrim-mul: 0.6;
        --highlight-text: #a3243e;
        --highlight-text-soft: #8f1f36;
        --turn: #1a1a2e;
        --turn-rgb: 26, 26, 46;
        --turn-ink: #ffffff;
        --number-card-shadow: 0 1px 3px rgba(20, 30, 60, 0.25);
        font-palette: --hit7-flat-ink;
    }
}

/* Cairo Play is a colour font: its glyphs carry their own paint (red, purple,
   amber, green) and ignore `color`, which is why every score and the deck count
   came out green no matter what the rules above them said. Overriding all four
   palette slots to white flattens the layers into one plain white glyph.
   font-palette inherits, so setting it once on the root covers every heading,
   score and counter that uses the face. */
@font-palette-values --hit7-flat {
    font-family: 'Cairo Play';
    override-colors: 0 #ffffff, 1 #ffffff, 2 #ffffff, 3 #ffffff;
}

/* The same trick in navy for light mode. Chosen by the theme blocks above. */
@font-palette-values --hit7-flat-ink {
    font-family: 'Cairo Play';
    override-colors: 0 #1a1a2e, 1 #1a1a2e, 2 #1a1a2e, 3 #1a1a2e;
}

html {
    font-palette: --hit7-flat;
}

/* Without backdrop-filter a translucent surface just shows whatever is behind it,
   unblurred, which makes text on these surfaces hard to read. This replaces the old
   .blur-bg rule, which stopped matching anything when the JS that applied that class
   was removed. No !important is needed: an @supports block and its plain counterpart
   never both apply, so there is nothing here to out-rank. */
@supports not ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
    /* .game-container is deliberately absent: it is the page, not a surface on it. */
    .game-header,
    .game-code-display,
    .controls,
    .menu-container,
    .waiting-screen,
    .deck-stats-container,
    .remaining-pile .regular-cards,
    .remaining-pile .special-cards,
    .remaining-card .card-count,
    .select-card-popup .card-count,
    .htp .htp-card,
    .history-popup .popup-content,
    .round-summary-popup .popup-content {
        background: var(--surface-solid);
    }
}

html,
body {
    width: 100%;
    height: 100%;
}

/* Installed on a phone the page no longer fills every pixel of the screen: the safe
   areas around the notch and the home indicator sit outside the body box, and whatever
   is behind them is html, which is white by default. This is the only thing painting
   those edges, so it has to match the top of the body gradient and the manifest's
   background_color exactly. */
html {
    background-color: var(--surface-0);
}

body {
    font-family: 'Roboto', sans-serif;
    background: var(--gradient-bg);
    color: var(--ink);
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    position: relative;
    overflow-x: hidden;
    overflow: hidden;
    height: 100vh;
    padding: 0;
}

body::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: url('data:image/svg+xml,<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><rect width="20" height="20" fill="none"/><circle cx="10" cy="10" r="1" fill="rgba(var(--ink-rgb), 0.05)"/></svg>') repeat;
    z-index: -1;
    opacity: 0.5;
}

/* Lobby Screen */
.lobby-screen {
    text-align: center;
    padding: 2rem;
    max-width: 600px;
    width: 100%;
    /* max(), not a plain margin: this is the one top-level screen with nothing between
       it and the top of the display, and its logo is the first thing a notch would eat.
       Reads as the old 2rem whenever the inset is 0, which is every case today. */
    margin-top: max(2rem, env(safe-area-inset-top));
}

/* Game Logo Styling */
.game-logo {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 2rem 0;
}

.logo-image {
    max-width: 140px;
    width: auto;
    height: auto;
    object-fit: contain;
    margin-right: 0.75rem;
}

.game-logo .hit {
    font-family: 'Cairo Play', sans-serif;
    font-size: 6rem;
    text-align: center;
    margin: 2rem 0;
    text-transform: uppercase;
    position: relative;
    letter-spacing: -0.03em;
    text-shadow: 0 0 20px rgba(204, 51, 80, 0.4);
}

/* No hover on the logo: it is not a button, and a thing that reacts to the
   mouse but does nothing when clicked only teaches people to click it. */

.game-logo .hit {
    background: var(--card-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-weight: 800;
    padding-right: 10px;
}

.game-logo .seven {
    color: var(--highlight);
    font-weight: 900;
    font-size: 1.2em;
    position: relative;
    top: 5px;
    text-shadow: var(--glow);
}

/* Header Logo (smaller version) */
.game-header .game-logo {
    font-size: 3rem;
    margin: 0;
    text-shadow: 0 0 20px rgba(204, 51, 80, 0.4);
}

.game-header .game-logo .hit {
    background: var(--card-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-weight: 800;
    padding-right: 5px;
}

.game-header .game-logo .seven {
    color: var(--highlight);
    font-weight: 900;
    font-size: 1.2em;
    position: relative;
    top: 3px;
    text-shadow: var(--glow);
}

.lobby-button {
    background: var(--highlight);
    color: var(--on-accent);
    padding: 1rem 2rem;
    border: none;
    border-radius: 12px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.8rem;
    box-shadow: 0 4px 15px rgba(204, 51, 80, 0.3);
    width: 100%;
    max-width: 280px;
    justify-content: center;
    font-family: 'Roboto', sans-serif;
    font-weight: 500;
    height: 50px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.lobby-button:hover {
    transform: translateY(-2px);
    background: #b02a44;
    box-shadow: 0 6px 20px rgba(204, 51, 80, 0.4);
}

.lobby-input {
    width: 100%;
    max-width: 280px;
    padding: 1.2rem;
    margin: 1rem 0;
    border: 2px solid var(--highlight);
    border-radius: 12px;
    background: rgba(var(--ink-rgb), 0.1);
    color: var(--ink);
    font-size: 1.2rem;
    text-transform: uppercase;
    text-align: center;
    font-family: 'Poppins', sans-serif;
    font-weight: 500;
    height: 50px;
}

.lobby-input:focus {
    outline: none;
    box-shadow: 0 0 12px var(--highlight);
}

/* Game Code Display */
.game-code-display {
    background: rgba(var(--surface-rgb), 0.8);
    padding: 1.2rem 2rem;
    border-radius: 12px;
    margin: 2rem 0;
    font-size: 1.4rem;
    animation: slideIn 0.3s ease;
    border: 1px solid rgba(204, 51, 80, 0.2);
    -webkit-backdrop-filter: var(--material-thin);
    backdrop-filter: var(--material-thin);
    font-family: 'Cairo Play', sans-serif;
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    justify-content: center;
}

.game-code {
    display: none;
}

@keyframes slideIn {
    from { opacity: 0; transform: translateY(-10px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Game Area - Updated for full screen without scroll */
.game-container {
    display: none;
    width: 100vw;
    height: 100vh;
    max-width: none;
    /* 100vw plus 1rem of padding was overflowing the viewport by 32px; body's
       overflow-x hid it, but the right edge of the board was being clipped. */
    box-sizing: border-box;
    margin: 0; /* remove negative margin to avoid layout shift */
    padding: 1rem;
    /* Not a frosted panel. This element IS the whole screen, so there is nothing behind
       it to blur except the page background - a full-viewport backdrop-filter that
       produces no picture and costs more than anything else on the page. Worse, the
       translucent slab blended the board to a slightly different shade from the page
       behind it, so every strip the container did not reach - the safe areas on a phone
       - read as a band of the wrong colour. Transparent, and the body gradient runs
       edge to edge with nothing to line up. */
    background: transparent;
    border-radius: 0;
    border: none;
    box-shadow: none;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    overflow-y: auto;
    max-height: 100vh; /* Ensure it doesn't exceed the viewport height */
}

.game-container.active {
    display: flex;
}

/* Update Game Header Styling */
.game-header {
    background: rgba(var(--surface-rgb), 0.8);
    border-radius: 15px;
    padding: 0.75rem 1.5rem;
    margin-bottom: 1rem;
    border: 1px solid rgba(204, 51, 80, 0.2);
    box-shadow: 0 4px 20px rgba(var(--shadow-rgb), 0.2);
    position: relative;
    overflow: hidden;
    display: flex;
    justify-content: space-between;
    align-items: center;
    -webkit-backdrop-filter: var(--material-regular);
    backdrop-filter: var(--material-regular);
    min-height: 72px; /* allow flexible height on small screens */
    width: 100%;
    box-sizing: border-box;
}

.header-left,
.header-right {
    display: flex;
    align-items: center;
    height: 100%;
}

.header-left {
    flex: 0 0 auto;
    min-width: 120px; /* Add minimum width to ensure logo space */
}

.header-left .game-logo {
    font-size: 1.6rem;
    margin: 0;
    text-shadow: 0 0 14px rgba(204, 51, 80, 0.35);
    display: flex;
    align-items: center;
}

.header-left .logo-image {
    height: 64px; /* sensible desktop logo height */
    max-height: 10vh;
    width: auto; /* Maintain aspect ratio */
    object-fit: contain;
    margin-right: 0.5rem;
}

.header-right {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex: 1;
    justify-content: flex-end;
}

.header-right .game-code-display {
    margin-right: auto; /* Push to left within header-right */
}

.game-header::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(45deg, 
        rgba(var(--ink-rgb), 0.03) 0%, 
        rgba(var(--ink-rgb), 0.06) 50%, 
        rgba(var(--ink-rgb), 0.03) 100%);
}

.game-header > * {
    position: relative;
    z-index: 1;
}

.game-logo.header-logo {
    font-size: 2.5rem;
    position: relative;
    left: auto;
    transform: none;
    margin: 0;
}

.deck-info {
    font-size: 1.2rem;
    background: rgba(var(--shadow-rgb), 0.15);
    padding: 0.8rem 1.5rem;
    border-radius: 8px;
    display: flex;
    gap: 0.8rem;
    align-items: center;
}

.game-header .game-code-display {
    background: transparent;
    /* The base rule frosts this. With the background taken away that leaves a blurred
       rectangle floating in the header, drawing nothing and hazing what is behind it. */
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    padding: 0;
    margin: 0;
    border: none;
    box-shadow: none;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.game-header .game-code-display .label {
    font-family: 'Cairo Play', sans-serif;
    font-size: 1.4rem;
    color: var(--ink);
    opacity: 0.8;
}

.deck-area {
    display: flex;
    justify-content: center;
    gap: 2rem;
    margin-bottom: 1rem;
    align-items: center;
    padding: 0.5rem;
    margin-top: 1rem;
}

/* Players Container - Updated for centered layout */
.players-container {
    display: flex;
    flex-direction: row;
    gap: 1rem;
    width: calc(100vw - 2rem);
    overflow-x: auto;
    padding: 0.5rem;
    margin-bottom: 90px; /* Space for controls */
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: var(--highlight) var(--surface);
    justify-content: center;
    overflow-y: visible;
    max-height: calc(100vh - 150px); /* Adjust for header and controls */
    flex: 1;
    flex-wrap: nowrap;
}

/* Desktop/tablet layout for players - responsive grid */
@media (min-width: 768px) {
    .players-container {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
        justify-content: center;
        align-items: start;
        width: 100%;
        overflow-x: visible;
    }

    .players-container .player {
        width: 100%;
        max-width: 450px;
        margin: 0 auto;
    }
}

/* Player Card.
   One block, one spacing scale. This used to be two .player rules fighting each
   other, and the losing one still landed `max-height: calc(100vh - 250px)` with
   no overflow rule — so on any short viewport the rounded background stopped
   partway down and the card grids spilled out below the box. The panel hugs its
   content instead; the scrolling belongs to .players-container and .my-hand.

   Every gap inside the panel now comes from this flex `gap`, so the children
   below carry no vertical margins of their own to double up with it. */
.player {
    /* The hover sheet below is absolute with every edge at 0. Without this it
       is placed against the nearest positioned ancestor - the whole game
       screen - and, being a child of the panel, keeps the panel in :hover
       wherever the mouse goes next. The header's buttons went dead until the
       pointer left the window. The lift transform used to contain it by
       accident; the compact seats have no lift. */
    position: relative;
    flex: 1;
    min-width: 350px;
    max-width: 450px;
    scroll-snap-align: center;
    margin: 0 auto;
    padding: var(--space-4);
    background: rgba(var(--surface-rgb), 0.9);
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.2);
    border: 1px solid rgba(204, 51, 80, 0.2);
    height: fit-content;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.player:hover {
    transform: translateY(-5px);
}

.player:hover::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: 15px;
    box-shadow: 0 8px 30px rgba(var(--shadow-rgb), 0.3);
    opacity: 1;
    transition: opacity 0.3s ease;
    /* Decoration only; it must never be the thing under the mouse. */
    pointer-events: none;
}

.player::after {
    opacity: 0;
    transition: opacity 0.3s ease;
}

.player.current-turn {
    border: 2px solid var(--turn) !important;
    animation: border-pulse 2s infinite;
    box-shadow: 0 0 20px rgba(var(--turn-rgb), 0.3);
}

@keyframes border-pulse {
    0% { box-shadow: 0 0 15px rgba(var(--turn-rgb), 0.2); }
    50% { box-shadow: 0 0 25px rgba(var(--turn-rgb), 0.55); }
    100% { box-shadow: 0 0 15px rgba(var(--turn-rgb), 0.2); }
}

.player.busted {
    border-color: var(--danger);
    background: linear-gradient(to bottom right, var(--surface), rgba(204, 51, 80, 0.25));
    animation: busted-flash 1s ease 2;
}

@keyframes busted-flash {
    0% { background: var(--surface); }
    50% { background: rgba(204, 51, 80,0.3); }
    100% { background: var(--surface); }
}

/* Frozen Status */
.player.frozen {
  border-color: #3498db;
  background: linear-gradient(to bottom right, var(--surface), #2c3e50);
}

.status-icon.frozen { color: #3498db; }
.player-summary.frozen .status-badge { background: #3498db; }

.scores {
    display: grid;
    /* Round and Total. There used to be a third box counting cards (0/7), but
       the seven slots under it already say that. */
    grid-template-columns: repeat(2, 1fr);
    /* One label row and one value row shared by both boxes. Without this a
       label that wraps to two lines makes its own box taller and leaves the
       numbers beside it sitting higher - which is exactly what CARDS vs
       ROUND SCORE / TOTAL SCORE used to do. */
    grid-template-rows: auto auto;
    gap: 0.5rem;
    background: rgba(var(--surface-2-rgb), 0.5);
    padding: var(--space-2);
    border-radius: var(--radius-md);
    margin: 0;
    border: 1px solid rgba(204, 51, 80, 0.1);
}

.score-box {
    /* Spans both rows of .scores and borrows them, so every label bottom and
       every value top lines up across the row. In .player-summary the parent is
       a flex container, where subgrid resolves to none and this stays a plain
       two-row grid. */
    display: grid;
    grid-row: span 2;
    grid-template-rows: subgrid;
    align-content: start;
    text-align: center;
    padding: var(--space-2);
    background: rgba(var(--ink-rgb), 0.05);
    border-radius: 12px;
    transition: transform 0.3s ease;
    border: 1px solid rgba(var(--ink-rgb), 0.1);
    font-size: 0.9rem;
}

.score-box:hover {
    transform: translateY(-2px);
    background: rgba(var(--ink-rgb), 0.08);
}

.score-value {
    font-size: 1.2rem;
    font-weight: bold;
    color: var(--highlight);
    margin-top: 0.5rem;
    text-shadow: 0 0 10px rgba(204, 51, 80, 0.3);
}

/* Sits inside .player-header, which has no gap of its own, so the top margin
   is what separates it from the name. */
.player-status {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: var(--space-2) 0 0;
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: rgba(var(--surface-2-rgb), 0.5);
    border: 1px solid rgba(var(--ink-rgb), 0.1);
}

.status-icon {
    font-size: 1.8rem;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.status-text {
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.9rem;
    color: var(--highlight);
}

.busted-card {
    background: rgba(204, 51, 80,0.15);
    padding: 0.5rem;
    border-radius: 5px;
    margin-top: 0.5rem;
    font-size: 0.9rem;
    color: var(--danger);
    font-weight: bold;
    margin: 0.8rem 0 0;
    padding: 0.3rem 0.6rem;
    background: rgba(204, 51, 80,0.1);
    border-radius: 5px;
    display: inline-block;
}

/* Card Grid and Slots.
   No margin here: this rule is overridden further down by one that sets
   width:100%, and a margin on top of that pushed the grid 8px past the panel
   on both sides — the right-hand column was clipped and the left had a double
   gap. Spacing between the grids comes from .cards-section's gap. */
.card-grid {
    display: grid;
    grid-template-columns: repeat(7, 45px);
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-2);
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: var(--radius-md);
    border: 1px solid rgba(var(--ink-rgb), 0.1);
    position: relative;
    justify-content: center;
}

/* Card and Empty Slot Styling */
.card,
.empty-slot {
    width: 45px;  /* Match special card width */
    height: 63px; /* Match special card height */
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
    font-weight: bold;
}

.empty-slot {
    background: rgba(var(--ink-rgb), 0.05);
    border: 2px dashed rgba(var(--ink-rgb), 0.1);
}

.empty-slot.special {
    border: 2px dashed rgba(204, 51, 80, 0.2);
}

/* Special Card Styling */
.card.special {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    border-width: 2px;
    border-style: solid;
    font-size: 1.2rem;
    width: 45px;
    height: 63px;
    border-radius: 8px;
    margin: 0;
}

/* Second Chance Card Styling */
.card.special.second-chance {
    position: relative;
}

.card.special.second-chance::before {
    text-shadow: none !important;
    filter: none !important;
    content: "";
    font-size: 1.8rem;
    display: block;
    margin-top: -5px;
}

/* Player & Discard Shared Styles */
.card.special.second-chance {
    position: relative;
}

.card.special.second-chance::before {
    text-shadow: none !important;
    filter: none !important;
    content: "";
    font-size: 1.8rem;
    display: block;
    margin-top: -5px;
}

/* Used State for Both */
.card.special.sc-used {
    background: #95a5a6;
    opacity: 0.7;
}

.card.special.sc-used::before {
    content: "🛡️❌";
    filter: grayscale(1);
}

.card.special.freeze::before {
    content: "" !important; /* Single emoji */
    font-size: 1.8rem;
    position: absolute;
    bottom: 5px;
    right: 5px;
}

/* Special Cards Section */
.special-cards-container {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    min-height: 70px;
    align-items: center;
}

/* Controls */
.controls {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 70px;
    background: rgba(var(--surface-rgb), 0.98);
    border-top: 2px solid rgba(204, 51, 80, 0.3);
    padding: 0.5rem;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 1.2rem;
    z-index: var(--z-controls);
    -webkit-backdrop-filter: var(--material-regular);
    backdrop-filter: var(--material-regular);
    box-shadow: 0 -4px 20px rgba(var(--shadow-rgb), 0.3);
}

.game-button {
    background: var(--highlight);
    color: var(--on-accent);
    padding: 1rem 2rem;
    border: none;
    border-radius: 12px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.8rem;
    box-shadow: 0 4px 15px rgba(204, 51, 80, 0.3);
    min-width: 120px;
    height: 50px;
    font-family: 'Roboto', sans-serif;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.game-button:hover:not(:disabled) {
    transform: translateY(-2px);
    background: #b02a44;
    box-shadow: 0 6px 20px rgba(204, 51, 80, 0.4);
}

.game-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: #95a5a6 !important;
    box-shadow: none !important;
    transform: none !important;
}

/* Every button is the brand red unless it is the quieter of a pair - Stand next to
   HIT, Cancel next to a confirm, Leave next to Start. Those get an outline instead of
   a fill, so there is one loud thing on screen at a time. */
.game-button.quiet {
    background: transparent;
    color: var(--ink);
    border: 2px solid rgba(var(--ink-rgb), 0.35);
    box-shadow: none;
}

.game-button.quiet:hover:not(:disabled) {
    background: rgba(var(--ink-rgb), 0.08);
    border-color: rgba(var(--ink-rgb), 0.6);
    box-shadow: none;
}

/* Copy link sits next to Start Game, so it takes the quiet look; the colour lives
   with .copy-link-btn further down. */
.game-button.copy-link-btn {
    min-width: 160px; /* Ensure same width as reset button */
    padding: 1rem 2.5rem; /* Same padding as other game buttons */
}

.game-button:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 5px 12px rgba(var(--shadow-rgb), 0.2);
}

.game-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: #95a5a6 !important;
    color: #3b3b3b !important;
    box-shadow: none !important;
    transform: none !important;
}

/* Winner Popup */
.winner-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul))) !important;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.winner-popup .popup-content {
    background: var(--surface);
    padding: 2.5rem;
    border-radius: 15px;
    max-width: 600px;
    width: 100%;
    box-shadow: 0 0 30px rgba(var(--shadow-rgb), 0.5);
    border: 3px solid var(--highlight);
    text-align: center;
}

.winner-popup h2 {
    color: var(--highlight);
    font-size: 2.5rem;
    margin: 0 0 1.5rem;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

.winner-name {
    font-size: 1.8rem;
    margin: 1rem 0;
    color: var(--ink);
}

.winner-score {
    font-size: 2rem;
    color: var(--success);
    margin: 1rem 0;
    font-weight: bold;
}

.trophy-banner {
    font-size: 4rem;
    margin-bottom: 1rem;
    animation: bounce 1s infinite;
}

.leaderboard {
    margin: 2rem 0;
    text-align: left;
}

.leaderboard h3 {
    color: var(--highlight);
    text-align: center;
    margin-bottom: 1rem;
}

.leaderboard-container {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.leaderboard-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.8rem;
    background: rgba(var(--surface-rgb), 0.9);
    border-radius: 8px;
    border: 1px solid rgba(204, 51, 80, 0.2);
}

.leaderboard-row.winner {
    border: 2px solid var(--highlight);
    background: rgba(204, 51, 80, 0.1);
}

.leaderboard-row .rank {
    font-size: 1.5rem;
    min-width: 40px;
}

.leaderboard-row .player-name {
    flex: 1;
    color: var(--ink);
}

.leaderboard-row .player-score {
    font-weight: bold;
    color: var(--success);
}

.winner-popup .waiting-message {
    margin-top: 1.5rem;
    padding: 1rem;
    background: rgba(var(--ink-rgb), 0.1);
    border-radius: 8px;
    color: var(--ink);
    font-size: 1.1rem;
    animation: pulse 2s infinite;
}

.winner-popup #rematchButton {
    margin: 1.5rem auto 0;
    display: block;
    min-width: 200px;
}

.info-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul))) !important;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 2rem;
    border: none;
    border-radius: 15px;
    max-width: 100%;
    text-align: center;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.info-popup h2 {
    color: var(--danger);
    font-size: 1.8rem;
    margin: 0 0 1rem;
}

.popup-countdown {
    font-size: 1.4rem;
    color: var(--ink);
    margin: 0;
}

/* Reset Confirmation Popup */
.settings-confirm-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul))) !important;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.settings-confirm-popup .popup-content {
    background: var(--surface);
    padding: 2rem;
    border-radius: 15px;
    max-width: 400px;
    width: 100%;
    box-shadow: 0 0 30px rgba(var(--shadow-rgb), 0.5);
    border: 3px solid var(--highlight);
    text-align: center;
}

.settings-confirm-popup h2 {
    color: var(--highlight);
    margin-top: 0;
}

.settings-confirm-popup p {
    color: var(--ink);
    margin-bottom: 2rem;
}

.settings-confirm-popup .button-group {
    display: flex;
    gap: 1rem;
    justify-content: center;
}

@keyframes popupIn {
    from { opacity: 0; transform: translate(-50%, -60%); }
    to { opacity: 1; transform: translate(-50%, -50%); }
}

@keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-20px); }
}

/* Second Chance Indicator */
.second-chance-indicator {
    background: transparent !important;
    border: 2px solid #2ecc71 !important;
    padding: 0.3rem 0.8rem !important;
    color: #2ecc71 !important;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
    box-shadow: none !important;
}

/* Remaining Pile Container */
.remaining-info {
    display: flex;
    align-items: center;
    gap: 2rem;
    margin-bottom: 2rem;
    background: rgba(var(--ink-rgb), 0.1);
    padding: 1.5rem;
    border-radius: 15px;
    width: 100%;
    max-width: 800px;
}

/* Deck Stats Container - Horizontal Layout */
.deck-stats-container {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3rem;
    padding: 1.5rem 2rem;
    background: rgba(var(--surface-rgb), 0.8);
    border-radius: 12px;
    border: 1px solid rgba(204, 51, 80, 0.2);
    -webkit-backdrop-filter: var(--material-regular);
    backdrop-filter: var(--material-regular);
    margin-bottom: 1.5rem;
}

.deck-stat-item {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.stat-label {
    font-size: 1.4rem;
    font-family: 'Cairo Play', sans-serif;
    white-space: nowrap;
    color: var(--ink);
}

.stat-value {
    font-weight: bold;
    background: var(--card-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    text-shadow: var(--glow);
    font-size: 1.6rem;
    font-family: 'Cairo Play', sans-serif;
}

/* Remaining Pile Cards Container */
.remaining-pile {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    min-height: 100px;
    padding: 1.5rem;
    background: var(--surface);
    border-radius: 15px;
    flex-grow: 1;
}

/* Regular Cards Section */
.remaining-pile .regular-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: 1.5rem;
    background: rgba(var(--surface-2-rgb), 0.5);
    border-radius: 15px;
    position: relative;
    border: 1px solid rgba(204, 51, 80, 0.2);
    -webkit-backdrop-filter: var(--material-regular);
    backdrop-filter: var(--material-regular);
}

/* Special Cards Section */
.remaining-pile .special-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: 1.5rem;
    background: rgba(var(--surface-2-rgb), 0.5);
    border-radius: 15px;
    position: relative;
    border: 1px solid rgba(204, 51, 80, 0.2);
    -webkit-backdrop-filter: var(--material-regular);
    backdrop-filter: var(--material-regular);
}

/* Individual Remaining Cards */
.remaining-card {
    width: 50px;
    height: 70px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 1.2rem;
    box-shadow: 0 4px 8px rgba(var(--shadow-rgb), 0.2);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    position: relative;
    border: 2px solid rgba(var(--ink-rgb), 0.1);
}

.remaining-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 6px 12px rgba(var(--shadow-rgb), 0.3);
}

/* Card Count Badge */
.remaining-card .card-count {
    position: absolute;
    bottom: 4px;
    right: 4px;
    background: rgba(var(--shadow-rgb), 0.7);
    color: var(--on-accent);
    font-size: 0.8rem;
    padding: 2px 6px;
    border-radius: 8px;
    line-height: 1;
    font-weight: bold;
    box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
    -webkit-backdrop-filter: var(--material-thin);
    backdrop-filter: var(--material-thin);
}

/* Regular Cards Section */
.remaining-pile .regular-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    padding: 1rem;
    background: rgba(var(--ink-rgb), 0.05);
    border-radius: 8px;
    position: relative;
}

/* Special Cards Section */
.remaining-pile .special-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    padding: 1rem;
    background: rgba(var(--ink-rgb), 0.05);
    border-radius: 8px;
    position: relative;
}

/* Individual Remaining Cards */
.remaining-card {
    width: 50px;
    height: 70px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 1.2rem;
    box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
    transition: transform 0.2s ease;
}

.remaining-card:hover {
    transform: translateY(-3px);
}

/* Card Count Badge */
.remaining-card .discard-count {
    position: absolute;
    bottom: 2px;
    right: 2px;
    background: rgba(var(--shadow-rgb), 0.7);
    color: var(--on-accent);
    font-size: 0.7rem;
    padding: 2px 5px;
    border-radius: 3px;
    line-height: 1;
}

/* Card Count Badge */
.discard-count {
    position: absolute;
    bottom: 2px;
    right: 2px;
    background: rgba(var(--shadow-rgb), 0.4);
    color: var(--ink);
    font-size: 0.7rem;
    padding: 2px 5px;
    border-radius: 3px;
    line-height: 1;
}

/* Round Summary Popup */
.round-summary-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul))) !important;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.round-summary-popup .popup-content {
    background: var(--surface);
    padding: 2.5rem;
    border-radius: 15px;
    max-width: 600px;
    width: 100%;
    box-shadow: 0 0 30px rgba(var(--shadow-rgb), 0.5);
    border: 3px solid var(--highlight);
}

.round-summary-popup h2 {
    color: var(--highlight);
    text-align: center;
    margin-bottom: 2rem;
    font-size: 2rem;
    font-weight: 600;
}

/* Player List - Horizontal Scroll */
.player-list {
    display: block;
    overflow-x: visible;
    gap: 0;
    padding-bottom: 0;
}

.player-summary {
    flex: 0 0 auto; /* Prevent items from shrinking */
    width: 300px; /* Adjust as needed */
    min-width: 300px;
    background: rgba(var(--surface-rgb), 0.9);
    border-radius: 15px;
    padding: 1.5rem;
    border: 1px solid rgba(204, 51, 80, 0.2);
    transition: all 0.3s ease;
    gap: 1.5rem;
}

.summary-left {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.player-name {
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 0.3rem;
    display: block;
}

.status-info {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.8rem;
}

.status-badge {
    padding: 0.5rem 1rem;
    border-radius: 20px;
    color: var(--on-accent);
    font-size: 0.8rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    min-width: 80px;
    text-align: center;
}

/* Status Badge Colors */
.status-badge.active { background: var(--turn); color: var(--turn-ink); }
.status-badge.stood { background: #2ecc71; }
.status-badge.busted { background: #cc3350; }
.status-badge.frozen { background: #95a5a6; }
.status-badge.finished { background: #9b59b6; }

.bonus-badge {
    background: #9b59b6;
    color: var(--on-accent);
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: bold;
    animation: pulse 2s infinite;
}

.summary-scores {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
    min-width: 120px;
}

.score-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    background: rgba(var(--shadow-rgb), 0.2);
    padding: 0.8rem 1rem;
    border-radius: 8px;
}

.score-label {
    color: var(--ink);
    opacity: 0.8;
    font-size: 0.9rem;
}

.score-value {
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--highlight);
}

.player-summary .busted-card {
    background: rgba(204, 51, 80,0.2);
    color: #cc3350;
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: bold;
    margin: 0;
}

.countdown {
    text-align: center;
    font-size: 1.2rem;
    color: var(--highlight);
    margin-top: 2rem;
    font-weight: 500;
    background: rgba(var(--shadow-rgb), 0.2);
    padding: 1rem;
    border-radius: 10px;
}

@keyframes pulse {
    0% { opacity: 0.6; }
    50% { opacity: 1; }
    100% { opacity: 0.6; }
}

/* Special Cards Layout Fix */
.special-cards-container {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.special-cards-container::before {
    content: "Special Cards";
    width: 100%;
    font-size: 0.9rem;
    opacity: 0.8;
    margin-bottom: 0.5rem;
}

.card.special {
    width: 50px;
    height: 70px;
    margin: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Discard Pile Layout */
.discard-pile {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    min-height: 100px;
}

.status-info {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.player-summary .scores {
    display: flex;
    gap: 1rem;
    margin-left: auto;
}

/* Freeze popup styling */
.freeze-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.freeze-popup .popup-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: linear-gradient(135deg, #2980b9, #3498db) !important;
    box-shadow: 0 8px 32px rgba(52, 152, 219, 0.4);
    padding: 2.5rem;
    border: none;
    padding-bottom: 80px; /* Increase bottom padding for button space */
    position: relative; /* Ensure proper positioning of absolute elements */
}

.freeze-popup h3 {
    color: var(--ink) !important;
    margin: 0;
    text-align: center;
    font-size: 1.4rem;
    text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.freeze-popup .freeze-targets {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 1rem 0;
    background: rgba(var(--ink-rgb), 0.1);
    border: 1px solid rgba(var(--ink-rgb), 0.2);
    margin-bottom: 30px; /* Added space below target buttons */
}

.freeze-popup .freeze-target {
    background: rgba(var(--ink-rgb), 0.15);
    color: var(--ink);
    border: 1px solid rgba(var(--ink-rgb), 0.2);
    padding: 1rem;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s ease;
    font-size: 1.1rem;
    font-family: 'Poppins', sans-serif;
    font-weight: 500;
}

.freeze-popup .freeze-target:hover {
    background: rgba(var(--ink-rgb), 0.25);
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.2);
}

.card.special.second-chance::before {
  content: "" !important;
}

.card.special.freeze::before {
  content: "" !important;
}

.draw-three-indicator {
    background: rgba(241, 196, 15, 0.2);
    color: #f39c12;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  margin-top: 0.5rem;
  font-weight: bold;
  animation: pulse 1.5s infinite;
}

/* Draw Three Popup */
.draw-three-popup {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  min-width: 100vw;
  min-height: 100vh;
  background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-popup);
  padding: 20px;
  pointer-events: auto;
  overflow: auto;
  box-sizing: border-box;
}

.draw-three-popup .popup-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: linear-gradient(135deg, #f1c40f, #f39c12) !important;
    box-shadow: 0 8px 32px rgba(241, 196, 15, 0.4);
  padding: 2.5rem;
  border: none;
  padding-bottom: 80px; /* Increase bottom padding for button space */
  position: relative; /* Ensure proper positioning of absolute elements */
}

.draw-three-popup h3 {
    color: #2c3e50 !important;
  margin: 0 0 1rem 0;
  text-align: center;
  font-size: 1.4rem;
  text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.draw-three-popup .draw-three-targets {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 1rem 0;
    background: rgba(var(--ink-rgb), 0.2);
    border: 1px solid rgba(var(--shadow-rgb), 0.1);
    margin-bottom: 30px; /* Added space below target buttons */
}

.draw-three-popup .draw-three-target {
    background: rgba(var(--ink-rgb), 0.35);
    color: #2c3e50;
    border: 1px solid rgba(var(--shadow-rgb), 0.1);
  padding: 1rem;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  font-size: 1.1rem;
  font-family: 'Poppins', sans-serif;
  font-weight: 500;
}

.draw-three-popup .draw-three-target:hover {
    background: rgba(var(--ink-rgb), 0.5);
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.2);
}

@keyframes pulse {
  0% { opacity: 0.6; }
  50% { opacity: 1; }
  100% { opacity: 0.6; }
}

/* Enhanced Menu Styling */
.menu-container {
    background: rgba(var(--surface-rgb), 0.8);
    border-radius: 20px;
    padding: 2.5rem;
    margin: 2rem auto;
    max-width: 400px;
    box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.2);
    -webkit-backdrop-filter: var(--material-thick);
    backdrop-filter: var(--material-thick);
    border: 1px solid rgba(204, 51, 80, 0.2);
}

.menu-buttons {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 1.5rem;
    width: 100%;
}

.join-game {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    width: 100%;
}

.lobby-button,
.lobby-input {
    width: 100%;
    max-width: none;
    height: 50px;
    box-sizing: border-box;
    margin: 0;
}

.tutorial-button {
    align-self: stretch;
    margin: 0;
}

.tutorial-button:hover {
    transform: translateY(-2px);
}

/* Update Regular Cards */
.card:not(.special) {
    font-weight: bold;
    border: 2px solid var(--secondary);
    box-shadow: 0 4px 15px rgba(var(--shadow-rgb), 0.2);
}

.card:not(.special):hover {
    transform: translateY(-5px);
    box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.3);
}

.share-link-input {
    background: rgba(var(--ink-rgb), 0.1);
    border: 1px solid rgba(204, 51, 80, 0.2);
    border-radius: 8px;
    padding: 0.8rem;
    color: var(--ink);
    width: 300px;
    margin-right: 0.5rem;
    font-family: 'Roboto', sans-serif;
}

.copy-link-btn {
    background: transparent;
    color: var(--ink);
    border: 2px solid rgba(var(--ink-rgb), 0.35);
    box-shadow: none;
    border-radius: 8px;
    padding: 0.8rem 1.5rem;
    cursor: pointer;
    transition: all 0.3s ease;
    font-family: 'Roboto', sans-serif;
    font-weight: 500;
}

.copy-link-btn:hover {
    background: rgba(var(--ink-rgb), 0.08);
    border-color: rgba(var(--ink-rgb), 0.6);
    box-shadow: none;
    transform: translateY(-2px);
}

/* Update share link styles */
.share-link {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.5rem;
    background: rgba(var(--ink-rgb), 0.1);
    border-radius: 8px;
    background: transparent; /* Remove gray background */
    padding: 0;            /* Remove extra padding */
    border: none;
}

/* Add this new class */
.hidden {
    display: none !important;
}

/* Waiting Screen Styles */
.waiting-screen {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--surface);
    padding: 2rem;
    border-radius: 15px;
    box-shadow: 0 0 30px rgba(var(--shadow-rgb), 0.5);
    z-index: var(--z-controls);
    width: 90%;
    max-width: 500px;
    text-align: center;
    border: 3px solid var(--highlight);
    -webkit-backdrop-filter: var(--material-thick);
    backdrop-filter: var(--material-thick);
}

.waiting-screen h2 {
    color: var(--highlight);
    margin-bottom: 1.5rem;
    font-size: 1.8rem;
}

.waiting-screen .players-list {
    background: rgba(var(--shadow-rgb), 0.2);
    padding: 1rem;
    border-radius: 10px;
    margin: 1rem 0;
    max-height: 200px;
    overflow-y: auto;
}

.waiting-screen .player-item {
    padding: 0.8rem;
    margin: 0.5rem 0;
    background: rgba(var(--ink-rgb), 0.1);
    border-radius: 8px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* The name takes the slack so every badge and the remove button sit hard right,
   lined up down the list instead of drifting with the length of each name. */
.waiting-screen .player-item .player-item-name {
    flex: 1;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Destructive and permanent, so it is deliberately quiet until you go looking for it -
   but sized for a thumb, because on a phone a small × next to a name is a misfire
   waiting to happen. A confirmation stands behind it either way. */
.waiting-screen .player-item .lobby-kick-button {
    flex: none;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid rgba(var(--ink-rgb), 0.24);
    border-radius: 50%;
    background: rgba(var(--ink-rgb), 0.08);
    color: var(--ink);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.7;
    transition: background 0.2s ease, opacity 0.2s ease, border-color 0.2s ease;
}

.waiting-screen .player-item .lobby-kick-button:hover,
.waiting-screen .player-item .lobby-kick-button:focus-visible {
    opacity: 1;
    background: rgba(220, 53, 69, 0.85);
    border-color: rgba(220, 53, 69, 0.9);
}

/* Its own row under everything else. Sharing the start button's row would put "Cancel
   Game" a thumb's width from "Start Game", which is the one neighbour it must not have. */
.waiting-screen .lobby-exit-group {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid rgba(var(--ink-rgb), 0.12);
}

.waiting-screen .lobby-exit-group .game-button {
    font-size: 0.95rem;
    padding: 0.6rem 1.2rem;
    opacity: 0.85;
}

.waiting-screen .player-item .host-badge {
    background: var(--highlight);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.8rem;
}

/* A lobby seat is held for a few minutes after somebody's phone drops the connection,
   so the row stays in the list. Dimmed and badged, or the rest of the table would sit
   there waiting to start on a player who has wandered off. */
.waiting-screen .player-item.is-away {
    opacity: 0.55;
}

.waiting-screen .player-item .away-badge {
    background: rgba(var(--ink-rgb), 0.12);
    border: 1px solid rgba(var(--ink-rgb), 0.24);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

/* Nobody should have to guess which of these are people. The lobby badge names
   the personality as well, because it is the only place with room to say it. */
.waiting-screen .player-item .bot-badge {
    background: rgba(var(--ink-rgb), 0.16);
    border: 1px solid rgba(var(--ink-rgb), 0.28);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

/* On the board there is only room for the mark itself. */
.player .bot-mark {
    font-size: 0.9em;
    opacity: 0.85;
    margin-right: 0.1em;
}

.waiting-screen .button-group {
    display: flex;
    gap: 1rem;
    justify-content: center;
    margin-top: 1.5rem;
}

.waiting-screen .share-section {
    margin: 1.5rem 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

.waiting-screen .share-text {
    font-size: 1.1rem;
    color: var(--ink);
    opacity: 0.9;
}

/* Hangs just under the copy button, over the top of whatever is next. It
   used to sit 40px below the whole panel's bottom edge, which put 40px of
   invisible overflow on a panel that scrolls - so the waiting room drew a
   scrollbar even when everything you could see fit on the screen. */
.waiting-screen .share-section {
    position: relative;
}

.waiting-screen .copied-message {
    position: absolute;
    bottom: -36px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--highlight);
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-size: 0.9rem;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.waiting-screen .copied-message.show {
    opacity: 1;
}

/* Loading spinner animation */
.loading-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 3px solid rgba(var(--ink-rgb), .3);
    border-radius: 50%;
    border-top-color: var(--highlight);
    animation: spin 1s ease-in-out infinite;
    margin-left: 10px;
}

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

/* Remove cancel button styles */
.cancel-freeze,
.cancel-draw-three,
.remove-card-popup .cancel-button {
  display: none !important;
}

/* Remove Card Popup */
.remove-card-popup {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  min-width: 100vw;
  min-height: 100vh;
  background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-popup);
  padding: 20px;
  pointer-events: auto;
  overflow: auto;
  box-sizing: border-box;
}

/* Steal Card Popup */
.steal-card-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.remove-card-popup .popup-content {
  display: flex;
  flex-direction: column;
  gap: 1rem;
    background: linear-gradient(135deg, #9b59b6, #8e44ad) !important;
    box-shadow: 0 8px 32px rgba(155, 89, 182, 0.35) !important;
  padding: 0;
  border: none;
  padding-bottom: 80px; /* Increase bottom padding for button space */
  position: relative; /* Ensure proper positioning of absolute elements */
}

.steal-card-popup .popup-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
        background: linear-gradient(135deg, #e67e22, #d35400) !important;
        box-shadow: 0 8px 32px rgba(230, 126, 34, 0.35) !important;
    padding: 0;
    border: none;
    padding-bottom: 80px; /* Increase bottom padding for button space */
    position: relative; /* Ensure proper positioning of absolute elements */
}

.remove-card-popup .players-list {
    background: rgba(155, 89, 182, 0.2) !important;
    border-color: rgba(155, 89, 182, 0.35) !important;
}

.remove-card-popup .player-section {
    background: rgba(155, 89, 182, 0.18) !important;
    border-color: rgba(155, 89, 182, 0.35) !important;
}

.remove-card-popup .cards-list {
    background: rgba(155, 89, 182, 0.18) !important;
    border-color: rgba(155, 89, 182, 0.35) !important;
}

.steal-card-popup .players-list {
    background: rgba(230, 126, 34, 0.2) !important;
    border-color: rgba(230, 126, 34, 0.35) !important;
}

.steal-card-popup .player-section {
    background: rgba(230, 126, 34, 0.18) !important;
    border-color: rgba(230, 126, 34, 0.35) !important;
}

.steal-card-popup .cards-list {
    background: rgba(230, 126, 34, 0.18) !important;
    border-color: rgba(230, 126, 34, 0.35) !important;
}

.remove-card-popup h3 {
  color: var(--ink);
  text-align: center;
  margin: 0 0 1rem 0;
  font-size: 1.4rem;
  text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.steal-card-popup h3 {
    color: var(--ink);
    text-align: center;
    margin: 0 0 1rem 0;
    font-size: 1.4rem;
    text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.remove-card-popup .players-list,
.steal-card-popup .players-list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  background: rgba(var(--ink-rgb), 0.1);
  border: 1px solid rgba(var(--ink-rgb), 0.2);
}

.remove-card-popup .player-section,
.steal-card-popup .player-section {
  background: rgba(var(--ink-rgb), 0.1);
  border: 1px solid rgba(var(--ink-rgb), 0.2);
  padding: 1rem;
  border-radius: 12px;
}

.remove-card-popup .player-section h4,
.steal-card-popup .player-section h4 {
  color: var(--ink);
  text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
  font-size: 1.2rem;
  margin: 0 0 1rem 0;
  font-family: 'Cairo Play', sans-serif;
  text-transform: uppercase;
}

.remove-card-popup .cards-list,
.steal-card-popup .cards-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
  background: rgba(var(--ink-rgb), 0.1);
  border: 1px solid rgba(var(--ink-rgb), 0.2);
}

.remove-card-popup .card-button,
.steal-card-popup .card-button {
  width: 50px;
  height: 70px;
  border-radius: 8px;
  border: none;
  cursor: pointer;
  font-size: 1.2rem;
  font-weight: bold;
  transition: transform 0.2s;
  color: var(--text-dark);
  background: var(--primary);
}

/* Minus cards (- cards) */
.card.special.minus,
.remaining-card.special.minus {
    text-shadow: none !important;
}

/* Divide card styling */
.card.special.divide,
.remaining-card.special.divide {
    text-shadow: none !important;
}

/* Update remove card popup card styles */
.remove-card-popup .card-button.special,
.steal-card-popup .card-button.special {
    font-weight: bold;
    text-shadow: none;}

/* Swap Card Popup Styles */
.swap-card-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    min-width: 100vw;
    min-height: 100vh;
    background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-popup);
    padding: 20px;
    pointer-events: auto;
    overflow: auto;
    box-sizing: border-box;
}

.swap-card-popup .popup-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: linear-gradient(135deg, #42ae5d, #3a9a50) !important;
    box-shadow: 0 8px 32px rgba(66, 174, 93, 0.35) !important;
    padding: 2.5rem !important;
    border: none;
    padding-bottom: 140px !important;
    position: relative;
}

.swap-card-popup h3 {
    color: var(--ink);
    text-align: center;
    margin: 0 0 1rem 0;
    font-size: 1.4rem;
    text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.swap-card-popup .players-list {
    background: rgba(66, 174, 93, 0.2) !important;
    border-color: rgba(66, 174, 93, 0.35) !important;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    border: 1px solid rgba(var(--ink-rgb), 0.2);
}

.swap-card-popup .player-section {
    background: rgba(66, 174, 93, 0.18) !important;
    border-color: rgba(66, 174, 93, 0.35) !important;
    border: 1px solid rgba(var(--ink-rgb), 0.2);
    padding: 1rem;
    border-radius: 12px;
}

.swap-card-popup .player-section h4 {
    color: var(--ink);
    text-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
    font-size: 1.2rem;
    margin: 0 0 1rem 0;
    font-family: 'Cairo Play', sans-serif;
    text-transform: uppercase;
}

.swap-card-popup .cards-list {
    background: rgba(66, 174, 93, 0.18) !important;
    border-color: rgba(66, 174, 93, 0.35) !important;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.5rem;
    border: 1px solid rgba(var(--ink-rgb), 0.2);
}

.swap-card-popup .card-button {
    width: 50px;
    height: 70px;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    font-size: 1.2rem;
    font-weight: bold;
    transition: all 0.2s;
    color: var(--text-dark);
    background: var(--primary);
}

.swap-card-popup .card-button.special {
    font-weight: bold;
    text-shadow: none;}

.swap-card-popup .card-button.swap-selectable.selected {
    transform: scale(1.1);
    box-shadow: 0 0 15px 3px rgba(var(--ink-rgb), 0.8);
    border: 3px solid var(--ink) !important;
}

.swap-card-popup .card-button.same-player-disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.confirm-swap-button {
    position: absolute;
    bottom: 15px;
    left: 50%;
    transform: translateX(-50%);
    padding: 12px 30px;
    /* The loud half of its pair, so it takes the same red as HIT. It used to be a
       white pill with green Cairo Play text, and Cairo Play is a colour font whose
       palette is flattened to the page ink - so the text was white on white. */
    background: var(--highlight);
    color: var(--on-accent);
    border: none;
    border-radius: 25px;
    font-size: 1.1rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.3s;
    box-shadow: 0 4px 15px rgba(204, 51, 80, 0.3);
    font-family: 'Roboto', sans-serif;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    width: auto;
    min-width: 200px;
}

.confirm-swap-button:hover:not(:disabled) {
    background: #b02a44;
    transform: translateX(-50%) translateY(-2px);
    box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.4);
}

.confirm-swap-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: var(--surface-2);
    color: var(--ink-muted);
}

.swap-card-popup .view-game-button {
    bottom: 85px;
}

/* Update remaining pile sort order */
/* Add styles for self-targeting buttons */
.freeze-target.self-target,
.draw-three-target.self-target {
    border: 2px solid rgba(var(--ink-rgb), 0.5) !important;
    position: relative;
    background: rgba(var(--ink-rgb), 0.1) !important;
}

.freeze-target.self-target:hover,
.draw-three-target.self-target:hover {
    background: rgba(var(--ink-rgb), 0.2) !important;
}

.cards-section {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: 0;
    flex-shrink: 1;
    min-width: 0;
}

.cards-container {
    display: flex;
    flex-direction: column;
}

.cards-label {
    font-family: 'Cairo Play', sans-serif;
    color: var(--highlight);
    font-size: 0.9rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: var(--space-2);
    background: rgba(var(--surface-2-rgb), 0.5);
    border-radius: var(--radius-md);
    border: 1px solid rgba(204, 51, 80, 0.2);
    margin-bottom: var(--space-2);
    text-align: center;
}

.card-grid {
    --cols: 7;
    --cell-gap: var(--space-2);
    --cell: calc((100% - (var(--cols) - 1) * var(--cell-gap)) / var(--cols));
    display: grid;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    gap: var(--cell-gap);
    padding: var(--space-2);
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: var(--radius-md);
    border: 1px solid rgba(204, 51, 80, 0.2);
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
}

/* A card is one grid cell, same as an empty slot. The 45x63 the first block
   above hands it is a floor for the old fixed-column layout only; in the 1fr
   grid the two have to agree or the cards sit narrower than the gaps between
   the slots they replace. */
.card-grid .card {
    width: auto;
    height: auto;
    aspect-ratio: 5 / 7;
    min-width: 0;
    /* .card.special carries `margin: 0 3px` for the contexts where it is laid
       out inline; inside a grid track that just makes the special cards 6px
       narrower than the slots they sit next to. */
    margin: 0;
}

/* Special cards top up to four placeholders, not seven — nothing about the game
   caps them at seven, and drawing a full regular-sized row of empties left a
   tall dead box under every hand (two ragged rows of it on a phone). auto-fit
   collapses the tracks the four do not use, so the row stays centred and the
   cells stay exactly the size of a regular card. */
.card-grid.special {
    background: rgba(var(--surface-2-rgb), 0.2);
    grid-template-columns: repeat(auto-fit, var(--cell));
    justify-content: center;
}

.empty-slot {
    width: auto;
    aspect-ratio: 5/7;
    border-radius: 8px;
    background: rgba(var(--ink-rgb), 0.05);
    border: 2px dashed rgba(var(--ink-rgb), 0.1);
}

.empty-slot.special {
    border: 2px dashed rgba(204, 51, 80, 0.2);
}

/* Common Popup Content Styling - Update this section */
.freeze-popup .popup-content,
.draw-three-popup .popup-content,
.remove-card-popup .popup-content,
.steal-card-popup .popup-content,
.round-summary-popup .popup-content,
.winner-popup .popup-content {
    background: var(--surface);
    padding: 2.5rem;
    border-radius: 15px;
    box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.3);
    max-width: 600px;
    width: 90%;
    margin: 20px;
    -webkit-backdrop-filter: var(--material-thick);
    backdrop-filter: var(--material-thick);
    padding-bottom: 80px; /* Increase bottom padding for button space */
    position: relative; /* Ensure proper positioning of absolute elements */
}

/* Popup Headers */
.freeze-popup h3,
.draw-three-popup h3,
.remove-card-popup h3,
.steal-card-popup h3 {
    color: var(--ink);
    text-align: center;
    font-size: 1.6rem;
    margin: 0 0 1.5rem 0;
    font-family: 'Cairo Play', sans-serif;
    text-transform: uppercase;
    letter-spacing: -0.01em;
}

/* Popup Targets Container */
.freeze-targets,
.draw-three-targets,
.remove-card-popup .players-list {
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: 12px;
    padding: 1.5rem;
    border: 1px solid rgba(204, 51, 80, 0.2);
    margin: 1rem 0;
    margin-bottom: 30px; /* Added space below target buttons */
}

/* Popup Target Buttons */
.freeze-target,
.draw-three-target,
.remove-card-popup .card-button.regular {
    width: 100%;
    padding: 1.2rem;
    margin: 0.5rem 0;
    border: none;
    border-radius: 12px;
    font-size: 1.1rem;
    font-family: 'Roboto', sans-serif;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: all 0.3s ease;
    background: var(--highlight);
    color: var(--on-accent);
    box-shadow: 0 4px 15px rgba(204, 51, 80, 0.3);
}

/* Button Hover States */
.freeze-target:hover,
.draw-three-target:hover,
.remove-card-popup .card-button:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(204, 51, 80, 0.4);
}

/* Self Target Button Styling */
.freeze-target.self-target,
.draw-three-target.self-target {
    background: rgba(var(--ink-rgb), 0.1);
    border: 2px solid rgba(204, 51, 80, 0.3);
}

.freeze-target.self-target:hover,
draw-three-target.self-target:hover {
    background: rgba(var(--ink-rgb), 0.15);
    border-color: var(--highlight);
}

/* Remove/Steal Card Popup Specific */
.remove-card-popup .player-section,
.steal-card-popup .player-section {
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: 12px;
    padding: 1.5rem;
    margin: 1rem 0;
    border: 1px solid rgba(204, 51, 80, 0.2);
}

.remove-card-popup .player-section h4,
.steal-card-popup .player-section h4 {
    color: var(--ink);
    font-size: 1.2rem;
    margin: 0 0 1rem 0;
    font-family: 'Cairo Play', sans-serif;
    text-transform: uppercase;
}

.remove-card-popup .cards-list,
.steal-card-popup .cards-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
    gap: 0.8rem;
    padding: 1rem;
    background: rgba(var(--surface-2-rgb), 0.2);
    border-radius: 8px;
    border: 1px solid rgba(204, 51, 80, 0.1);
}

/* Special Card Buttons in Remove Card Popup */
.remove-card-popup .card-button.special,
.steal-card-popup .card-button.special {
    padding: 0;
    width: 50px;
    height: 70px;
    border: none;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;}

/* Regular cards in remove-card popup */
.remove-card-popup .card-button.regular,
.steal-card-popup .card-button.regular {
    background: var(--primary) !important;
    color: var(--text-dark) !important;
    border: 2px solid var(--secondary);
    font-size: 1.6rem;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

/* Remove Card Popup - Update card alignment and busted state */
.remove-card-popup .card-button,
.steal-card-popup .card-button {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    font-weight: bold;
}

.remove-card-popup .player-section.busted,
.steal-card-popup .player-section.busted {
    opacity: 0.7;
    position: relative;
}

.remove-card-popup .player-section.busted::before,
.steal-card-popup .player-section.busted::before {
    content: "BUSTED";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(-15deg);
    background: #cc3350;
    color: var(--on-accent);
    padding: 0.5rem 2rem;
    border-radius: 5px;
    font-weight: bold;
    font-size: 1.2rem;
    z-index: 1;
    letter-spacing: 0.01em;
    box-shadow: 0 2px 10px rgba(var(--shadow-rgb), 0.3);
}

.remove-card-popup .player-section.busted .cards-list,
.steal-card-popup .player-section.busted .cards-list {
    pointer-events: none;
    filter: grayscale(0.8);
}

.remove-card-popup .player-section.busted .card-button,
.steal-card-popup .player-section.busted .card-button {
    cursor: not-allowed;
}

/* Round Summary Popup */

.round-summary-popup .popup-content {
    background: linear-gradient(135deg, var(--surface), var(--surface-2));
    padding: 2.5rem;
    border-radius: 20px;
    max-width: 800px;
    width: 95%;
    border: 3px solid var(--highlight);
    box-shadow: 0 0 50px rgba(204, 51, 80, 0.2);
    -webkit-backdrop-filter: var(--material-thick);
    backdrop-filter: var(--material-thick);
}

.round-summary-popup h2 {
    color: var(--ink);
    text-align: center;
    margin-bottom: 2rem;
    font-size: 2.5rem;
    font-weight: 700;
    font-family: 'Cairo Play', sans-serif;
    text-transform: uppercase;
    letter-spacing: -0.02em;
    text-shadow: 0 2px 10px rgba(204, 51, 80, 0.5);
    background: var(--card-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.round-summary-header {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    background: rgba(var(--surface-2-rgb), 0.5);
    border-radius: 12px 12px 0 0;
    border: 1px solid rgba(204, 51, 80, 0.2);
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ink);
    font-weight: 600;
    align-items: center;
    text-align: center;
}

.round-summary-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 2rem;
}

.player-summary-row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: 12px;
    border: 1px solid rgba(204, 51, 80, 0.2);
    align-items: center;
}

.points-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
}

.points-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    color: var(--ink);
    opacity: 0.7;
    letter-spacing: 0.06em;
}

.points {
    font-size: 1.4rem;
    font-weight: 700;
    font-family: 'Cairo Play', sans-serif;
    color: var(--highlight);
    text-shadow: 0 0 10px rgba(204, 51, 80, 0.3);
}

/* Player List - Horizontal Scroll */
.player-list {
    display: block;
    overflow-x: visible;
    gap: 0;
    padding-bottom: 0;
}

.player-summary {
    flex: 0 0 auto; /* Prevent items from shrinking */
    width: 300px; /* Adjust as needed */
    min-width: 300px;
    background: rgba(var(--surface-rgb), 0.9);
    border-radius: 15px;
    padding: 1.5rem;
    border: 1px solid rgba(204, 51, 80, 0.2);
    transition: transform 0.3s ease;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.player-summary::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--highlight);
    opacity: 0.5;
}

.player-summary:hover {
    transform: translateY(-5px);
}

.player-name {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--ink);
    text-align: center;
    margin-bottom: 1rem;
    font-family: 'Cairo Play', sans-serif;
    letter-spacing: -0.01em;
}

.status-info {
    display: flex;
    justify-content: center;
    gap: 0.8rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.status-badge {
    padding: 0.5rem 1.2rem;
    border-radius: 20px;
    color: var(--on-accent);
    font-size: 0.9rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    min-width: 100px;
    text-align: center;
    box-shadow: 0 2px 10px rgba(var(--shadow-rgb), 0.2);
}

.status-badge.active { 
    background: linear-gradient(135deg, #3498db, #2980b9);
}
.status-badge.stood { 
    background: linear-gradient(135deg, #2ecc71, #27ae60);
}
.status-badge.busted { 
    background: linear-gradient(135deg, #cc3350, #b02a44);
}
.status-badge.frozen { 
    background: linear-gradient(135deg, #95a5a6, #7f8c8d);
}
.status-badge.finished { 
    background: linear-gradient(135deg, #9b59b6, #8e44ad);
}

.summary-scores {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    background: rgba(var(--surface-2-rgb), 0.3);
    border-radius: 12px;
    border: 1px solid rgba(204, 51, 80, 0.2);
}

.score-item {
    background: rgba(var(--shadow-rgb), 0.2);
    padding: 1rem;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    transition: transform 0.3s ease;
}

.score-item:hover {
    transform: translateY(-2px);
}

.score-label {
    color: var(--ink);
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    opacity: 0.8;
}

.score-value {
    font-size: 1.8rem;
    font-weight: 700;
    color: var(--highlight);
    text-shadow: 0 0 10px rgba(204, 51, 80, 0.3);
    font-family: 'Cairo Play', sans-serif;
}

.bonus-badge {
    background: linear-gradient(135deg, #9b59b6, #8e44ad);
    color: var(--on-accent);
    padding: 0.5rem 1.2rem;
    border-radius: 20px;
    font-size: 0.9rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-top: 0.5rem;
    box-shadow: 0 2px 10px rgba(155, 89, 182, 0.3);
}

.countdown {
    text-align: center;
    font-size: 1.3rem;
    color: var(--ink);
    margin-top: 2rem;
    font-weight: 500;
    background: rgba(204, 51, 80, 0.1);
    padding: 1rem;
    border-radius: 12px;
    border: 1px solid rgba(204, 51, 80, 0.2);
    font-family: 'Cairo Play', sans-serif;
    letter-spacing: 0;
}

.countdown span {
    color: var(--highlight);
    font-weight: 700;
    font-size: 1.5rem;
}

.player-summary .busted-card {
    text-align: center;
    background: rgba(204, 51, 80, 0.2);
    color: #cc3350;
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-size: 0.9rem;
    font-weight: bold;
    margin: 0.5rem 0;
    letter-spacing: 0.05em;
    box-shadow: 0 2px 10px rgba(204, 51, 80, 0.2);
}

/* Select Card Styling - Updated with more subtle gradient */
.card.special.select-card,
.remaining-card.special.select-card {
  position: relative;
}

.card.special.select-card::before,
.remaining-card.special.select-card::before {
  content: "🃏" !important;
  font-size: 1.8rem;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Select Card Popup - Updated to match the style of remove-card popup */
.select-card-popup {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  min-width: 100vw;
  min-height: 100vh;
  background: rgba(var(--scrim-rgb), calc(0.95 * var(--scrim-mul)));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-popup);
  padding: 20px;
  pointer-events: auto;
  overflow: auto;
  box-sizing: border-box;
}

.select-card-popup .popup-content {
  background: var(--surface);
  padding: 2.5rem;
  border-radius: 15px;
  max-width: 800px;
  width: 95%;
  overflow-y: auto;
  max-height: 80vh;
  border: 3px solid;
  border-image: linear-gradient(135deg, #cc3350, #9b59b6, #3498db) 1;
  box-shadow: 0 0 50px rgba(204, 51, 80, 0.3);
  padding-bottom: 80px; /* Increase bottom padding for button space */
  position: relative; /* Ensure proper positioning of absolute elements */
}

.select-card-popup h3 {
  color: var(--ink);
  text-align: center;
  margin-bottom: 2rem;
  font-size: 1.8rem;
  font-weight: 700;
  font-family: 'Cairo Play', sans-serif;
  text-transform: uppercase;
  letter-spacing: -0.015em;
  background: linear-gradient(to right, #cc3350, #9b59b6, #3498db);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.select-card-popup .cards-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
  gap: 0.8rem;
  padding: 1rem;
  background: rgba(var(--surface-2-rgb), 0.2);
  border-radius: 8px;
  border: 1px solid rgba(204, 51, 80, 0.1);
}

.select-card-popup .card-button {
  width: 50px;
  height: 70px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 1.4rem;
  cursor: pointer;
  transition: all 0.3s ease;
  margin: 0 auto;
  border: none;
}

.select-card-popup .card-button:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 12px rgba(var(--shadow-rgb), 0.3);
}

.select-card-popup .card-button.regular {
  background: var(--primary) !important;
  color: var(--text-dark) !important;
  border: 2px solid var(--secondary);
}

.select-card-popup .card-count {
  position: absolute;
  bottom: 4px;
  right: 4px;
  background: rgba(var(--shadow-rgb), 0.7);
  color: var(--on-accent);
  font-size: 0.8rem;
  padding: 2px 6px;
  border-radius: 8px;
  line-height: 1;
  font-weight: bold;
  box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
}

.select-card-popup .card-section {
  margin-bottom: 1.5rem;
}

.select-card-popup .section-title {
  color: var(--highlight);
  font-size: 1.2rem;
  margin-bottom: 1rem;
  padding: 0.5rem;
  background: rgba(var(--surface-2-rgb), 0.5);
  border-radius: 8px;
  text-align: center;
}

/* Mobile adjustments for Select Card popup */
@media screen and (max-width: 430px) {
  .select-card-popup .popup-content {
    padding: 1.5rem;
    width: 90%;
  }
  
  .select-card-popup h3 {
    font-size: 1.4rem;
    margin-bottom: 1rem;
  }
  
  .select-card-popup .cards-list {
    grid-template-columns: repeat(auto-fill, minmax(45px, 1fr));
    gap: 0.6rem;
  }
  
  .select-card-popup .card-button {
    width: 40px;
    height: 56px;
    font-size: 1.2rem;
  }
}

/* Fix for emojis in popup headers - ensure they display properly */
.freeze-popup h3 span.emoji,
.draw-three-popup h3 span.emoji,
.remove-card-popup h3 span.emoji,
.select-card-popup h3 span.emoji {
    display: inline-block;
    margin-right: 10px;
    color: var(--ink) !important;
    background: none !important;
    -webkit-background-clip: initial !important;
    background-clip: initial !important;
    text-shadow: none;
    position: relative;
    z-index: 2;
}

/* Fix popup header text color from background-clip gradient */
.freeze-popup h3,
.draw-three-popup h3,
.remove-card-popup h3 {
    color: var(--ink) !important;
    background: none !important;
    -webkit-background-clip: initial !important;
    background-clip: initial !important;
}

/* Specifically fix select-card-popup which uses gradient text */
.select-card-popup h3 {
    position: relative;
}

.select-card-popup h3 span.emoji {
    color: initial !important;
    z-index: 1;
}

/* Fix round summary alignment - make grid headers align with content */
.round-summary-header {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    text-align: center;
    align-items: center;
}

/* Align individual column content */
.round-summary-header span:first-child,
.player-summary-row .name {
    text-align: left;
    padding-left: 0.5rem;
}

.round-summary-header span:nth-child(2),
.player-summary-row .status {
    text-align: center;
}

/* Add styles to make the player-summary-row align properly */
.player-summary-row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 1rem;
    padding: 1rem;
    align-items: center;
}

.player-summary-row .name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.player-summary-row .status {
    display: flex;
    justify-content: center;
    align-items: center;
    text-transform: uppercase;
    font-weight: bold;
    font-size: 0.9rem;
    letter-spacing: 0.05em;
}

/* Override any styles using -webkit-background-clip for emoji elements */
h3 span.emoji {
    background: none !important;
    -webkit-background-clip: initial !important;
    background-clip: initial !important;
    color: inherit !important;
}

/* Fix for emojis in popup titles being masked by color */
.freeze-popup h3::before,
.draw-three-popup h3::before,
.remove-card-popup h3::before,
.select-card-popup h3::before {
  content: ""; /* Remove any potential before content */
}

.freeze-popup h3 span.emoji,
.draw-three-popup h3 span.emoji,
.remove-card-popup h3 span.emoji,
.select-card-popup h3 span.emoji {
  display: inline-block;
  margin-right: 5px;
  filter: none;
  position: relative;
  z-index: 2;
}

/* Fix for Select Card popup styling to match remaining pile */
.select-card-popup .card-button {
  position: relative;
  width: 50px;
  height: 70px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 1.4rem;
  cursor: pointer;
  transition: all 0.3s ease;
  margin: 0 auto;
  border: 2px solid rgba(var(--ink-rgb), 0.1);
  box-shadow: 0 4px 8px rgba(var(--shadow-rgb), 0.2);
  font-family: 'Roboto', sans-serif;
}

.select-card-popup .card-button:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 12px rgba(var(--shadow-rgb), 0.3);
}

.select-card-popup .card-button.regular {
  background: white !important;
  color: var(--text-dark) !important;
  border: 2px solid var(--secondary);
}

/* Special card styling within select popup */
.select-card-popup .card-button.special { /* Ensure text is white for most special cards */
  border-width: 2px;}

.select-card-popup .card-count {
  position: absolute;
  bottom: 4px;
  right: 4px;
  background: rgba(var(--shadow-rgb), 0.7);
  color: var(--on-accent);
  font-size: 0.8rem;
  padding: 2px 6px;
  border-radius: 8px;
  line-height: 1;
  font-weight: bold;
  box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.2);
  -webkit-backdrop-filter: var(--material-thin);
  backdrop-filter: var(--material-thin);
}

/* HOLD TO VIEW GAME button styling - updated position */
.view-game-button {
    position: absolute;
    bottom: 25px; /* Increased from 20px to create more space */
    left: 50%;
    transform: translateX(-50%);
    background: rgba(var(--ink-rgb), 0.15);
    color: var(--ink);
    border: 2px solid rgba(204, 51, 80, 0.5);
    border-radius: 30px;
    padding: 12px 24px;
    font-size: 1rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: 'Roboto', sans-serif;
    box-shadow: 0 4px 12px rgba(var(--shadow-rgb), 0.2);
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: var(--z-overlay);
    margin-top: 20px; /* Add top margin for spacing */
}

/* Make the popups semi-transparent when holding the view button */
.popup-hiding {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

/* Mobile adjustments for the view game button */
@media screen and (max-width: 430px) {
    .view-game-button {
        padding: 10px 18px;
        font-size: 0.9rem;
        bottom: 15px;
    }
}

/* Update Regular Cards */
.card:not(.special) {
    font-weight: bold;
    border: 2px solid var(--secondary);
    box-shadow: 0 4px 15px rgba(var(--shadow-rgb), 0.2);
}

.card:not(.special):hover {
    transform: translateY(-5px);
    box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.3);
}

/* Game notifications (swap announcements and other non-blocking messages) */
.game-notification {
    position: fixed;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-overlay);
    max-width: min(90%, 480px);
    padding: 0.9rem 1.4rem;
    border-radius: 10px;
    background: var(--surface);
    color: var(--ink);
    border: 2px solid var(--highlight);
    box-shadow: 0 6px 20px rgba(var(--shadow-rgb), 0.4);
    font-weight: 500;
    text-align: center;
    animation: notificationIn 0.3s ease-out;
    opacity: 1;
    transition: opacity 0.5s ease, transform 0.5s ease;
}

.game-notification.fade-out {
    opacity: 0;
    transform: translateX(-50%) translateY(-12px);
}

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

/* ------------------------------------------------------------------ */
/* Game history log                                                    */
/* ------------------------------------------------------------------ */

.history-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(var(--scrim-rgb), calc(0.85 * var(--scrim-mul)));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-controls);
    padding: 1rem;
}

.history-popup .popup-content {
    background: var(--surface);
    width: 100%;
    max-width: 560px;
    height: min(80vh, 700px);
    display: flex;
    flex-direction: column;
    border: 2px solid var(--highlight);
    border-radius: 16px;
    padding: 0;
    position: relative;
    overflow: hidden;
    box-shadow: 0 10px 40px rgba(var(--shadow-rgb), 0.5);
    -webkit-backdrop-filter: var(--material-thick);
    backdrop-filter: var(--material-thick);
}

.history-popup .close-button {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    background: var(--highlight);
    color: var(--ink);
    width: 38px;
    height: 38px;
    border-radius: 50%;
    font-size: 1.6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    cursor: pointer;
    box-shadow: 0 4px 15px rgba(204, 51, 80, 0.5);
    z-index: 2;
    transition: all 0.2s ease;
    padding: 0;
    line-height: 1;
}

.history-popup .close-button:hover {
    transform: scale(1.1) rotate(90deg);
    background: #b02a44;
}

.history-popup .history-title {
    text-align: center;
    font-size: 1.5rem;
    margin: 1.1rem 3rem 0.8rem 3rem;
    font-family: 'Cairo Play', sans-serif;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    background: var(--card-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    flex-shrink: 0;
}

.history-popup .history-content {
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0 1rem 1.2rem 1rem;
}

.history-empty {
    text-align: center;
    color: rgba(var(--ink-rgb), 0.6);
    padding: 2rem 1rem;
    font-size: 0.95rem;
}

.history-round-divider {
    position: sticky;
    top: 0;
    background: var(--surface);
    color: var(--highlight);
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0.6rem 0 0.4rem 0;
    border-bottom: 1px solid rgba(204, 51, 80, 0.3);
    margin-bottom: 0.4rem;
    z-index: 1;
}

.history-entry {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.6rem;
    margin: 0.25rem 0;
    border-radius: 8px;
    background: rgba(var(--surface-2-rgb), 0.35);
    border-left: 3px solid rgba(var(--ink-rgb), 0.12);
    font-size: 0.9rem;
    line-height: 1.35;
}

.history-entry .history-icon {
    flex-shrink: 0;
    font-size: 1.05rem;
    width: 1.4rem;
    text-align: center;
}

/* Normal inline flow, not flex - the line is a sentence with card chips sitting
   inside it, so it has to wrap like prose. */
.history-entry .history-text {
    color: rgba(var(--ink-rgb), 0.85);
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}

.history-player {
    font-weight: 700;
    color: var(--ink);
}

.history-good {
    color: #4caf50;
    font-weight: 700;
}

.history-bad {
    color: var(--highlight);
    font-weight: 700;
}

/* Colour-code the entries that change the state of the round */
.history-entry.action-bust { border-left-color: var(--highlight); }
.history-entry.action-second-chance { border-left-color: #cc3350; }
.history-entry.action-stand { border-left-color: #ff9800; }
.history-entry.action-seven-bonus { border-left-color: #f1c40f; }
.history-entry.action-freeze { border-left-color: #3498db; }
.history-entry.action-draw-three { border-left-color: #f1c40f; }
.history-entry.action-remove { border-left-color: #9b59b6; }
.history-entry.action-steal { border-left-color: #e67e22; }
.history-entry.action-swap { border-left-color: #42ae5d; }
.history-entry.action-game-over { border-left-color: #4caf50; }

.history-entry.action-round-start,
.history-entry.action-round-end,
.history-entry.action-reshuffle,
.history-entry.action-left {
    background: rgba(var(--ink-rgb), 0.05);
    font-style: italic;
    color: rgba(var(--ink-rgb), 0.7);
}

/* Card chips inside a log line, matching the colours used on the board */
.history-card {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.7rem;
    height: 1.7rem;
    padding: 0 0.35rem;
    margin: 0 0.15rem;
    border-radius: 5px;
    font-weight: 700;
    font-size: 0.85rem;
    background: var(--primary);
    color: var(--text-dark);
    box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.35);
    vertical-align: middle;
}

/* ---------------------------------------------------------------------------
   Disconnects: the round is held open until everyone is back
   --------------------------------------------------------------------------- */

/* Above every other popup on purpose. A targeting popup someone already had open stays
   in the DOM while the game is paused, and this has to cover it - the server rejects
   whatever they would click until play resumes. */
.disconnect-popup,
.connection-lost-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(var(--scrim-rgb), calc(0.9 * var(--scrim-mul)));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-toast);
    padding: 1rem;
}

.disconnect-popup .popup-content,
.connection-lost-popup .popup-content {
    background: var(--surface);
    border: 2px solid var(--highlight);
    border-radius: 16px;
    padding: 2rem 1.5rem;
    width: 100%;
    max-width: 480px;
    text-align: center;
    box-shadow: 0 10px 40px rgba(var(--shadow-rgb), 0.6);
}

.disconnect-popup h2,
.connection-lost-popup h2 {
    color: var(--highlight);
    margin: 0.75rem 0 0.5rem;
    font-size: 1.4rem;
    letter-spacing: -0.01em;
}

.disconnect-popup .loading-spinner,
.connection-lost-popup .loading-spinner {
    width: 34px;
    height: 34px;
    border-width: 4px;
    margin: 0;
}

.disconnect-lead,
.connection-lost-popup p {
    color: rgba(var(--ink-rgb), 0.75);
    font-size: 0.95rem;
    line-height: 1.5;
    margin: 0 0 1.25rem;
}

.disconnect-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.disconnect-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    justify-content: center;
    background: rgba(var(--surface-2-rgb), 0.55);
    border: 1px solid rgba(204, 51, 80, 0.35);
    border-radius: 12px;
    padding: 0.75rem;
}

.disconnect-name {
    font-weight: 700;
    color: var(--ink);
    font-size: 1.05rem;
}

.disconnect-elapsed {
    /* Fixed width so the row does not jitter as the seconds tick over. */
    min-width: 5.5rem;
    font-variant-numeric: tabular-nums;
    color: rgba(var(--ink-rgb), 0.6);
    font-size: 0.85rem;
}

/* Two answers now, and on a phone they wrap onto their own line rather than
   squeezing the name out of the row. */
.disconnect-row .kick-button,
.disconnect-row .botify-button {
    font-size: 0.8rem;
    padding: 0.5rem 0.75rem;
    white-space: nowrap;
}

.disconnect-hint {
    color: rgba(var(--ink-rgb), 0.5);
    font-size: 0.8rem;
    line-height: 1.4;
    margin: 0;
}

/* Marks the empty seat on the board itself, so it is obvious who everyone is waiting on
   once the popup is behind a round summary or the history log. */
.player.disconnected {
    opacity: 0.55;
    border-color: rgba(204, 51, 80, 0.5) !important;
}

.away-indicator {
    background: var(--highlight);
    color: var(--on-accent);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 0.2rem 0.45rem;
    border-radius: 6px;
    white-space: nowrap;
}

.restart-notice {
    position: fixed;
    top: 1rem;
    left: 50%;
    transform: translateX(-50%);
    background: var(--surface);
    border: 2px solid var(--highlight);
    border-radius: 12px;
    padding: 0.85rem 1.25rem;
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    text-align: center;
    max-width: min(92vw, 420px);
    box-shadow: 0 8px 24px rgba(var(--shadow-rgb), 0.5);
    animation: notificationIn 0.3s ease;
}

.restart-notice strong {
    color: var(--highlight);
    font-size: 0.95rem;
}

.restart-notice span {
    color: rgba(var(--ink-rgb), 0.75);
    font-size: 0.8rem;
    line-height: 1.4;
}

/* ---------------------------------------------------------------------------
   Landing page form: name + game code, and the ways back into a game
   --------------------------------------------------------------------------- */

.lobby-form {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
    width: 100%;
}

.lobby-form .field {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.4rem;
    text-align: left;
}

.lobby-form label {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: rgba(var(--ink-rgb), 0.6);
}

.lobby-form input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.9rem 1rem;
    border: 2px solid rgba(204, 51, 80, 0.35);
    border-radius: 12px;
    background: rgba(var(--ink-rgb), 0.08);
    color: var(--ink);
    /* 16px minimum: anything smaller and iOS Safari zooms the page on focus. */
    font-size: 1rem;
    font-family: inherit;
    transition: border-color 0.2s ease, background 0.2s ease;
}

.lobby-form input::placeholder {
    color: rgba(var(--ink-rgb), 0.35);
}

.lobby-form input:focus {
    outline: none;
    border-color: var(--highlight);
    background: rgba(var(--ink-rgb), 0.14);
}

/* Codes are five characters and read as a unit, so they get the spacing to match. */
.lobby-form .code-input {
    text-transform: uppercase;
    letter-spacing: 0.35em;
    text-align: center;
    font-weight: 700;
    font-size: 1.35rem;
    padding: 0.8rem 0.5rem;
}

.lobby-form .code-input::placeholder {
    letter-spacing: 0.35em;
    font-weight: 400;
}

.lobby-button.quiet {
    background: transparent;
    color: var(--ink);
    border: 2px solid rgba(var(--ink-rgb), 0.35);
    box-shadow: none;
}

.lobby-button.quiet:hover {
    background: rgba(var(--ink-rgb), 0.08);
    border-color: rgba(var(--ink-rgb), 0.6);
    box-shadow: none;
}

.lobby-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0.25rem 0;
    color: rgba(var(--ink-rgb), 0.4);
    font-size: 0.75rem;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.lobby-divider::before,
.lobby-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: rgba(var(--ink-rgb), 0.15);
}

.lobby-footer {
    margin: 1.25rem 0 0;
    color: rgba(var(--ink-rgb), 0.45);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    line-height: 1.6;
}

/* The one link on the lobby. It is only a shade brighter than the text around
   it — loud enough to look clickable, quiet enough not to compete with the
   buttons, which are the thing anybody actually came here to press. */
.lobby-footer a {
    color: rgba(var(--ink-rgb), 0.7);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.lobby-footer a:hover,
.lobby-footer a:focus-visible {
    color: var(--ink);
}

.lobby-error {
    margin: 0;
    padding: 0.7rem 0.9rem;
    border-radius: 10px;
    background: rgba(204, 51, 80, 0.15);
    border: 1px solid rgba(204, 51, 80, 0.45);
    color: var(--highlight-text-soft);
    font-size: 0.85rem;
    line-height: 1.4;
    text-align: left;
}

/* The browser hides [hidden] elements with `display: none`, but that rule is a bare
   attribute selector - the same specificity as a class, so any `display` set on the
   same element would win just by being defined later, and the element would never
   hide. Declaring the guard once here, after the component layer, covers every
   element the JS toggles instead of relying on each component to remember. The
   compound selectors match a class as well, so they out-rank a single class. */
[hidden],
.card[hidden],
.lobby-error[hidden],
.game-container[hidden],
.controls[hidden] {
    display: none;
}

.field-hint {
    color: rgba(var(--ink-rgb), 0.45);
    font-size: 0.75rem;
    line-height: 1.4;
}

/* ---------------------------------------------------------------------------
   Card appearance
   ---------------------------------------------------------------------------
   Colour and geometry are independent, so they are set independently:

     colour   <- [data-card-type="<type>"]   assigned by client.js (el.dataset.cardType)
     geometry <- the context class      .card / .remaining-card / .history-card /
                                        .card-button

   Adding a card type means adding one block here. Nothing else in this file and
   nothing in client.js needs to know about it.

   This block sits at the end of the file on purpose: the context rules above set
   `border` as a shorthand, which would otherwise reset the border-color set here.
   --------------------------------------------------------------------------- */

/* The defaults live in the var() fallbacks rather than as declarations here, so
   that this rule can carry the specificity needed to beat the context rules
   without also out-ranking the per-type blocks below. A number card matches no
   per-type block and lands on the fallbacks. */
.card[data-card-type],
.remaining-card[data-card-type],
.history-card[data-card-type],
.card-button[data-card-type],
.htp-c[data-card-type] {
    background: var(--card-face, var(--primary));
    border-color: var(--card-edge, var(--secondary));
    color: var(--card-ink, var(--text-dark));
}

[data-card-type="second-chance"] { --card-face: #cc3350; --card-face-2: #b02a44; --card-edge: #b02a44; --card-ink: #fff; }
[data-card-type="freeze"]        { --card-face: #3498db; --card-face-2: #2980b9; --card-edge: #2980b9; --card-ink: #fff; }
[data-card-type="draw-three"]    { --card-face: #f1c40f; --card-face-2: #f39c12; --card-edge: #f39c12; --card-ink: #2c3e50; }
[data-card-type="remove-card"]   { --card-face: #9b59b6; --card-face-2: #8e44ad; --card-edge: #8e44ad; --card-ink: #fff; }
[data-card-type="steal-card"]    { --card-face: #e67e22; --card-face-2: #d35400; --card-edge: #d35400; --card-ink: #fff; }
[data-card-type="swap-card"]     { --card-face: #42ae5d; --card-face-2: #3a9a50; --card-edge: #3a9a50; --card-ink: #fff; }
[data-card-type="adder"]         { --card-face: #fbb03a; --card-face-2: #e9a232; --card-edge: #e9a232; --card-ink: #fff; }
[data-card-type="multiplier"]    { --card-face: #fbb03a; --card-face-2: #e9a232; --card-edge: #e9a232; --card-ink: #fff; }
[data-card-type="minus"]         { --card-face: #f1624f; --card-face-2: #d9574a; --card-edge: #d9574a; --card-ink: #fff; }
[data-card-type="divide"]        { --card-face: #f1624f; --card-face-2: #d9574a; --card-edge: #d9574a; --card-ink: #fff; }

/* The one type whose face is a gradient. */
[data-card-type="select-card"] {
    --card-face: linear-gradient(135deg, #cc3350 0%, #9b59b6 50%, #3498db 100%);
    --card-edge: #cc3350;
    --card-ink: #fff;
}

/* A white card on a white light-mode panel has only its navy edge to say where
   it ends; a little shadow underneath lifts it off. `none` in dark mode. */
.card[data-card-type="number"],
.history-card[data-card-type="number"],
.card-button[data-card-type="number"],
.htp-c[data-card-type="number"] {
    box-shadow: var(--number-card-shadow);
}


/* ===========================================================================
   RESPONSIVE
   ---------------------------------------------------------------------------
   Merged from the former mobile.css. That file was linked after this one, so
   its rules won ties on source order; appending them here in the same order
   preserves that exactly while removing a stylesheet and a request.

   Breakpoints in use:
     max-width: 430px                      phones
     431px - 767px                         large phones / small tablets
     max-width: 932px and (landscape)      phones held sideways
     min-width: 768px                      tablet and up
   =========================================================================== */
/* Mobile-specific styles (max-width: 430px for iPhone 14 Pro Max) */
@media screen and (max-width: 430px) {
    /* Reset body for mobile */
    body {
        padding: 0;
        margin: 0;
        width: 100vw;
        min-height: 100vh;
        overflow-x: hidden;
        position: relative;
        align-items: stretch; /* let containers fill width to avoid centering offsets */
    }

    /* Lobby Screen Adjustments */
    .lobby-screen {
        padding: 1rem;
        margin-top: 1rem;
        width: 100%;
        box-sizing: border-box;
    }

    .game-logo {
        margin: 1rem 0;
    }

    .logo-image {
        width: 80px;
        height: 80px;
    }

    .game-logo .hit {
        font-size: 4rem;
    }

    /* Menu Container */
    .menu-container {
        padding: 1.5rem;
        margin: 1rem;
        width: auto;
    }

    .header-left {
        flex: 0 0 auto;
        min-width: 80px;
        display: flex !important;
        align-items: center;
    }

    .header-left .game-logo {
        font-size: 1.5rem;
        display: flex !important;
        justify-content: flex-start;
    }

    .header-left .logo-image {
        height: 48px;
        width: auto;
    }

    /* Ensure header is visible and sized correctly on mobile */
    .game-header {
        position: sticky;
        top: 0;
        z-index: var(--z-sticky);
        padding: 0.5rem 0.75rem;
        display: flex !important;
        align-items: center;
        justify-content: space-between;
    }

    /* Make logo smaller and centered on very small screens */
    .header-left .logo-image {
        height: 44px;
    }

    .header-right {
        flex: 1 1 100%;
        width: 100%;
        justify-content: flex-end; /* keep buttons on the right */
        gap: 0.5rem;
        padding-top: 0.5rem;
        display: flex !important;
        align-items: center;
        flex-wrap: wrap; /* Allow buttons to wrap to next line instead of hiding */
        z-index: var(--z-sticky); /* ensure buttons sit above other header layers */
    }

    .header-right .game-button {
        padding: 0.5rem 0.7rem;
        min-width: auto;
        font-size: 0.75rem;
        height: 35px;
        white-space: nowrap;
        gap: 0.35rem;
    }

    /* The header is down to the deck count and the gear, but the word next to the
       gear still costs more room than a phone has, and a wrapped row spills past
       the header background. The glyph carries it on its own. */
    .header-right .game-button .button-label {
        display: none;
    }

    .game-header .game-code-display {
        /* Keep the game-code display available on mobile but compact it */
        display: flex;
        align-items: center;
        gap: 0.4rem;
        margin-right: 0.25rem;
        font-size: 0.9rem;
        opacity: 0.95;
    }

    /* Ensure header buttons remain visible and usable on small screens */
    .header-right .game-button {
        display: inline-flex !important;
        box-sizing: border-box;
    }

    /* Game Container */
    .game-container {
        /* Horizontal only. This used to be `padding: 0 !important`, which also beat the
           phone layout's padding-bottom - the one reserving the height of the fixed
           control bar - so the last row of the board sat underneath the buttons. */
        padding-left: 0 !important;
        padding-right: 0 !important;
        margin: 0 auto !important;
        width: 100% !important;
        box-sizing: border-box;
        height: calc(100vh - 70px); /* Account for fixed controls */
        overflow-y: auto;
        max-height: calc(100vh - 70px); /* Account for header and controls */
    }

    .game-board {
        padding: 0.5rem;
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
        overflow: visible;
        max-height: none;
    }

    /* Deck Area */
    .deck-area {
        flex-direction: column;
        gap: 1rem;
        margin: 0.5rem 0;
        align-items: stretch;
        width: 100%;
    }

    .deck-count {
        width: 100%;
        box-sizing: border-box;
        font-size: 1.1rem;
    }

    /* Players Container */
    .players-container {
        flex-direction: column;
        gap: 0.5rem;
        margin-bottom: 80px;
        width: 100% !important;
        max-width: 100% !important;
        overflow-y: visible;
        padding: 0.5rem 0 !important;
        max-height: none;
        align-items: center !important; /* center player boxes horizontally */
        margin-left: auto !important;
        margin-right: auto !important;
    }

    .player {
        min-width: unset;
        width: calc(100% - 1rem);
        max-width: 520px; /* constrain width on larger phones */
        margin: 0.4rem auto; /* center each player card */
        box-sizing: border-box;
        padding: 0.8rem;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: stretch;
        height: fit-content;
        gap: 0.6rem;
    }

    .player.current-turn {
        border: 2px solid var(--turn) !important;
        animation: border-pulse 2s infinite;
    }

    /* Card Grid */
    .card-grid {
        --cell-gap: 0.3rem;
        padding: 0.3rem;
        width: 100%;
        box-sizing: border-box;
        min-width: 0;
    }

    .card-grid.special {
        background: rgba(var(--surface-2-rgb), 0.2);
    }

    .cards-section {
        display: flex;
        flex-direction: column;
        gap: 0.8rem;
        margin: 0.5rem 0;
    }

    .cards-label {
        font-size: 0.8rem;
        padding: 0.4rem;
        margin: 0;
    }

    .card, .empty-slot {
        width: 40px;
        height: 56px;
        font-size: 1rem;
    }

    /* Special Cards */
    .special-cards-container {
        gap: 0.3rem;
        padding: 0.5rem;
        min-height: 40px; /* Ensure space for special cards */
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        overflow: visible;
    }

    .card.special {
        width: 40px;
        height: 56px;
        font-size: 1rem;
    }

    /* Controls */
    .controls {
        height: 60px;
        padding: 0.5rem;
        gap: 0.8rem;
    }

    .game-button {
        padding: 0.8rem 1.5rem;
        font-size: 1rem;
        min-width: 100px;
        height: 40px;
    }

    /* Popups */
    .winner-popup,
    .round-summary-popup,
    .freeze-popup,
    .draw-three-popup,
    .info-popup {
        width: 90%;
        max-height: 80vh;
        overflow-y: auto;
        padding: 1.5rem;
    }

    .popup-content {
        padding: 1rem;
    }


    /* Waiting Screen */
    .waiting-screen {
        width: 90%;
        max-height: 80vh;
        padding: 1rem;
    }

    /* History Log - full screen on mobile like the tutorial */
    .history-popup {
        padding: 0;
    }

    .history-popup .popup-content {
        width: 100%;
        max-width: 100%;
        height: 100%;
        border: none;
        border-radius: 0;
    }

    .history-popup .history-title {
        font-size: 1.25rem;
        margin: max(0.9rem, env(safe-area-inset-top)) 3.5rem 0.6rem 3.5rem;
    }

    .history-popup .history-content {
        padding: 0 0.75rem 4rem 0.75rem;
    }

    .history-entry {
        font-size: 0.82rem;
        padding: 0.45rem 0.5rem;
    }

    .history-card {
        min-width: 1.5rem;
        height: 1.5rem;
        font-size: 0.78rem;
    }

    /* Round Summary */
    .round-summary-popup .popup-content {
        padding: 1rem;
    }

    .player-summary {
        flex-direction: column;
        padding: 1rem;
    }

    .summary-scores {
        width: 100%;
    }

    /* Remaining Pile */
    .remaining-pile {
        padding: 0.8rem;
    }

    .remaining-card {
        width: 40px;
        height: 56px;
        font-size: 1rem;
    }

    /* Share Link */
    .share-link-input {
        width: 100%;
        margin: 0.5rem 0;
    }

    /* Scores Section */
    .scores {
        grid-template-columns: repeat(2, 1fr);
        gap: 0.3rem;
        padding: 0.5rem;
    }

    .score-box {
        padding: 0.5rem;
        font-size: 0.8rem;
    }

    .score-value {
        font-size: 1rem;
    }

    /* Status Badges */
    .status-badge {
        padding: 0.3rem 0.8rem;
        font-size: 0.7rem;
    }

    /* Player Header */
    .player-header {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    .player-header h3 {
        font-size: 1.1rem;
        margin: 0;
    }

    /* Player Status */
    .player-status {
        padding: 0.8rem;
        margin: 0.5rem 0;
        flex-wrap: wrap;
    }

    .status-icon {
        font-size: 1.4rem;
        width: 30px;
        height: 30px;
    }

    /* Freeze and Draw Three Indicators */
    .draw-three-indicator,
    .second-chance-indicator {
        font-size: 0.8rem;
        padding: 0.3rem 0.8rem;
    }

    /* Fixed positioning for Safari notch */
    @supports (padding-top: env(safe-area-inset-top)) {
        body {
            padding-top: env(safe-area-inset-top);
            padding-bottom: env(safe-area-inset-bottom);
        }

        .controls {
            padding-bottom: calc(env(safe-area-inset-bottom) + 0.5rem);
        }
    }

    /* Remove Card Popup Mobile Styles */
    .remove-card-popup {
        width: 95%;
        padding: 1rem;
    }

    .remove-card-popup .card-button {
        width: 40px;
        height: 56px;
        font-size: 1rem;
    }

    .remove-card-popup .player-section {
        padding: 0.8rem;
    }

    .remove-card-popup .cards-list {
        gap: 0.3rem;
    }

    .remove-card-popup h3 {
        font-size: 1.2rem;
    }

    .cards-section {
        gap: 0.5rem;
        margin: 0.5rem 0;
    }

    .cards-label {
        font-size: 0.8rem;
        padding: 0.5rem;
    }

    .cards-section {
        gap: 0.8rem;
        margin: 0.8rem 0;
    }

    .card-grid {
        --cell-gap: 0.3rem;
        padding: 0.8rem;
    }

    .card-grid .card,
    .card-grid .empty-slot {
        font-size: 0.9rem;
    }

    .player {
        padding: 0.8rem;
    }

    .player-header h3 {
        font-size: 1rem;
    }

    .scores {
        gap: 0.3rem;
        padding: 0.5rem;
    }

    .score-box {
        padding: 0.3rem;
        font-size: 0.8rem;
    }

    .score-value {
        font-size: 1rem;
    }
}
@media screen and (min-width: 431px) and (max-width: 767px) {
    /* Inherit most styles from smaller phones but adjust some dimensions */
    .player {
        min-width: unset;
        width: calc(100% - 2rem);
        margin: 1rem;
    }

    .card, .empty-slot, .card.special {
        width: 45px;
        height: 63px;
    }

    .controls {
        height: 70px;
    }

    .game-button {
        height: 50px;
    }

    .game-header {
        height: auto;
        min-height: 90px;
        padding: 0.75rem;
    }

    .header-left .logo-image {
        height: 60px;
    }

    .header-right {
        flex-wrap: nowrap;
    }
}

/* Landscape mode adjustments */
@media screen and (max-width: 932px) and (orientation: landscape) {
    .game-container {
        height: auto;
        min-height: calc(100vh - 60px);
    }

    .players-container {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: center;
        gap: 1rem;
        padding: 1rem;
    }

    .player {
        width: calc(50% - 1.5rem);
        min-width: unset;
    }

    .controls {
        position: sticky;
        bottom: 0;
    }

    .cards-section {
        flex-direction: row;
        gap: 0.8rem;
    }

    .cards-container {
        flex: 1;
    }

    .card-grid {
        --cols: 4;
    }

    .game-header {
        height: auto;
        min-height: 70px;
    }

    .header-left .logo-image {
        height: 45px;
    }

    .header-right {
        flex: 1;
        justify-content: flex-end;
    }
}
/* ==================================================================== */
/* MATERIALS                                                            */
/* Blur alone drains the colour out of whatever is behind the glass and */
/* leaves grey haze. saturate() puts it back, which is what makes a     */
/* translucent surface read as glass instead of fog.                    */
/* Three weights, because a full-screen sheet should feel thicker than  */
/* a small chip - same material, different amount of it.                */
/* ==================================================================== */

:root {
    --material-thin: blur(8px) saturate(160%);
    --material-regular: blur(16px) saturate(180%);
    --material-thick: blur(28px) saturate(180%);
}

/* ==================================================================== */
/* MOTION SYSTEM                                                        */
/* Appended last on purpose: these rules must win over the older        */
/* scattered transitions above without needing !important.              */
/* ==================================================================== */

:root {
    --dur-tap: 110ms;
    --dur-fast: 160ms;
    --dur-base: 220ms;
    --dur-slow: 320ms;
    --ease-out: cubic-bezier(.22, .75, .28, 1);
    --ease-in: cubic-bezier(.5, 0, .85, .4);
    --ease-back: cubic-bezier(.2, 1.25, .4, 1);
}

/* ---------- keyframes ---------- */

@keyframes deal {
    from { opacity: 0; transform: translateY(-22px) scale(.86) rotate(-5deg); }
    to   { opacity: 1; transform: translateY(0) scale(1) rotate(0); }
}

@keyframes special-pop {
    0%   { opacity: 0; transform: scale(.5); }
    60%  { opacity: 1; transform: scale(1.14); }
    100% { opacity: 1; transform: scale(1); }
}

@keyframes card-shake {
    0%, 100% { transform: translateX(0); }
    15% { transform: translateX(-7px) rotate(-3deg); }
    35% { transform: translateX(6px) rotate(3deg); }
    55% { transform: translateX(-4px) rotate(-2deg); }
    75% { transform: translateX(3px); }
}

@keyframes bust-ring {
    0%, 100% { box-shadow: 0 0 0 0 rgba(244, 67, 54, 0); }
    30% { box-shadow: 0 0 0 6px rgba(244, 67, 54, .45); }
}

@keyframes card-leave {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to   { opacity: 0; transform: translateY(-14px) scale(.9); }
}

@keyframes sheet-in {
    from { opacity: 0; transform: scale(.93) translateY(14px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes sheet-in-centered {
    from { opacity: 0; transform: translate(-50%, -50%) scale(.93); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@keyframes scrim-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes turn-breathe {
    0%, 100% { box-shadow: 0 0 0 3px rgba(var(--turn-rgb), .18); }
    50%      { box-shadow: 0 0 0 5px rgba(var(--turn-rgb), .06); }
}

@keyframes toast-in {
    from { opacity: 0; transform: translateX(-24px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* ---------- cards ---------- */

/* Only cards the reconciler just added carry .is-new, so the six cards
   already on the table never re-animate when the board updates. */
.card.is-new {
    animation: deal var(--dur-base) var(--ease-back) backwards;
}

/* Special cards change the game, so they get the bigger entrance. */
.card.special.is-new {
    animation: special-pop var(--dur-slow) var(--ease-back) backwards;
}

.card.is-leaving {
    animation: card-leave var(--dur-fast) var(--ease-in) forwards;
    pointer-events: none;
}

.card.is-bust {
    animation: card-shake 420ms var(--ease-out), bust-ring 420ms var(--ease-out);
}

.card:not(.special) {
    transition: transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}

/* ---------- turn highlight ---------- */

.player {
    transition: border-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                opacity var(--dur-base) var(--ease-out);
}

.player.current-turn {
    animation: turn-breathe 2.4s var(--ease-out) var(--dur-base) infinite;
}

/* ---------- score roll ---------- */

.score-value {
    font-variant-numeric: tabular-nums;
    /* 1.8rem is display size - letters read too far apart as they grow. */
    letter-spacing: -0.015em;
    transition: color var(--dur-base) var(--ease-out);
}

.score-value.is-rolling {
    color: var(--highlight);
}

/* ---------- popups ---------- */

/* Every popup shell in the game, entering. The centered ones translate
   themselves, so they need the variant that preserves translate(-50%,-50%). */
.winner-popup,
.info-popup,
.settings-confirm-popup,
.round-summary-popup,
.freeze-popup,
.draw-three-popup,
.htp,
.remove-card-popup,
.steal-card-popup,
.swap-card-popup,
.select-card-popup,
.history-popup,
.disconnect-popup,
.connection-lost-popup {
    animation: scrim-in var(--dur-fast) var(--ease-out) backwards;
}

.winner-popup .popup-content,
.info-popup .popup-content,
.settings-confirm-popup .popup-content,
.round-summary-popup .popup-content,
.freeze-popup .popup-content,
.draw-three-popup .popup-content,
.htp .htp-card,
.remove-card-popup .popup-content,
.steal-card-popup .popup-content,
.swap-card-popup .popup-content,
.select-card-popup .popup-content,
.history-popup .popup-content,
.disconnect-popup .popup-content,
.connection-lost-popup .popup-content {
    animation: sheet-in var(--dur-base) var(--ease-back) backwards;
}

/* Shells that position their own content with translate(-50%, -50%) would
   have it clobbered by the plain sheet-in transform. */
.info-popup .popup-content,
.settings-confirm-popup .popup-content,
.round-summary-popup .popup-content {
    animation-name: sheet-in-centered;
}

/* Closing: faster than opening. Getting out of the way must not feel slow. */
.popup-closing {
    opacity: 0;
    transition: opacity var(--dur-fast) var(--ease-in);
}

.popup-closing .popup-content {
    opacity: 0;
    transform: scale(.97) translateY(6px);
    transition: opacity var(--dur-fast) var(--ease-in),
                transform var(--dur-fast) var(--ease-in);
}

.info-popup.popup-closing .popup-content,
.settings-confirm-popup.popup-closing .popup-content,
.round-summary-popup.popup-closing .popup-content {
    transform: translate(-50%, -50%) scale(.97);
}

/* ---------- notices ---------- */

.restart-notice {
    animation: toast-in var(--dur-base) var(--ease-back) backwards;
}

/* ---------- buttons ---------- */

.game-button,
.lobby-button,
.card-button {
    transition: transform var(--dur-tap) var(--ease-out),
                background var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}

.game-button:active:not(:disabled),
.lobby-button:active:not(:disabled),
.card-button:active:not(:disabled) {
    transform: translateY(0) scale(.96);
}

/* ---------- accessibility ---------- */

/* Reduced motion is not "no feedback" - it is feedback that does not move you.
   Sliding, scaling, spinning and looping all go; opacity and colour stay, so a
   card still announces itself as new and a button still answers a press. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        /* No travel, no overshoot, no bounce - whatever the rule above asked for. */
        transform: none !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
        transition-property: opacity, color, background-color, border-color, box-shadow !important;
        transition-duration: var(--dur-fast) !important;
        transition-timing-function: var(--ease-out) !important;
    }

    /* Entrances and exits become plain cross-fades rather than vanishing. */
    .card.is-new,
    .card.special.is-new,
    .restart-notice {
        animation: scrim-in var(--dur-fast) var(--ease-out) backwards !important;
    }

    .card.is-leaving {
        animation: none !important;
        opacity: 0;
        transition: opacity var(--dur-fast) var(--ease-in) !important;
    }

    /* Ambient loops carry no information, so they simply stop. */
    .status-icon,
    .player.current-turn,
    [class*="pulse"],
    .last-action.is-new {
        animation: none !important;
    }
}

/* Some people turn transparency off because blurred backgrounds make text hard
   to read. Frost the glass solid rather than leaving them squinting at it. */
@media (prefers-reduced-transparency: reduce) {
    :root {
        --material-thin: none;
        --material-regular: none;
        --material-thick: none;
    }

    .game-header,
    .controls,
    .menu-container,
    .deck-stats-container,
    .waiting-screen,
    .popup-content {
        background: var(--surface);
    }
}

/* Higher contrast means a defined edge, not a hint of one. */
@media (prefers-contrast: more) {
    :root {
        --material-thin: none;
        --material-regular: none;
        --material-thick: none;
    }

    .game-header,
    .controls,
    .menu-container,
    .deck-stats-container,
    .popup-content,
    .score-box,
    .card {
        background: var(--surface);
        border-color: currentColor;
    }
}


/* ==========================================================================
   PHONE LAYOUT
   ==========================================================================

   Lives at the end of style.css because mobile.css was retired in PR #11 and
   this has to win over the consolidated responsive rules above it.

   What this replaces was not merely cramped, it was unplayable: `body {
   overflow: hidden; height: 100vh }` plus a 766px remaining-deck grid stacked
   above the players left 1,251px of the board unreachable by any gesture —
   your own hand sat at y=1389 on an 812px screen.

   The shape:

     shell        fixed to the dynamic viewport, never scrolls itself
       header     one row, sticky
       turn strip whose turn it is
       rail       opponents, horizontal scroll, tap to open a sheet
       hand       YOUR cards — the only thing that scrolls
       thumb bar  Hit / Stand, above the home indicator

   Two rules worth keeping in mind before editing:

   1. Size with dvh, never vh. `vh` resolves to the *largest* viewport, which is
      the height with the browser toolbar hidden — so a bottom-pinned bar sized
      in vh ends up underneath that toolbar.

   2. Only .my-hand and .opponent-rail scroll. Browser chrome collapses in
      response to *page* scroll, so a shell that never scrolls keeps the chrome
      still and the height constant.
   ========================================================================== */

/* Desktop-side hiding of the phone-only chrome. Outside the media query so it
   applies at every width above the breakpoint. The deck button and the
   last-move strip are not here: both layouts have them in the header now. */
.turn-strip,
.opponent-rail,
.my-hand {
    display: none;
}

/* A phone turned sideways is 852px wide but only ~390px tall, so width alone
   would hand it the desktop board and hide the rail and hand entirely. The
   second condition catches every landscape phone regardless of width, while
   `pointer: coarse` keeps a merely-short desktop window out of it. */
@media screen and (max-width: 767px),
       screen and (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {

    /* ---------------------------------------------------------------- shell */

    html {
        /* Stops iOS bumping font sizes in landscape. */
        -webkit-text-size-adjust: 100%;
    }

    body {
        height: 100dvh;
        min-height: 0;
        width: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
        overscroll-behavior: none;
        display: block;
    }

    /* Older engines without dvh still get a usable, if slightly tall, shell. */
    @supports not (height: 100dvh) {
        body { height: 100vh; }
    }

    .game-container {
        display: flex;
        flex-direction: column;
        height: 100dvh;
        max-height: 100dvh;
        width: 100%;
        margin: 0;
        overflow: hidden;
        gap: 0;
        border-radius: 0;
        /* Without border-box the safe-area and thumb-bar padding get *added* to
           100dvh and the shell grows taller than the screen it is meant to fit. */
        box-sizing: border-box;
        /* Horizontal padding here costs 32px of board width on every phone;
           the inner regions do their own padding instead. */
        padding-left: 0;
        padding-right: 0;
        padding-top: env(safe-area-inset-top);
    }

    @supports not (height: 100dvh) {
        .game-container { height: 100vh; max-height: 100vh; }
    }

    /* ---------------------------------------------------------------- header */

    .game-header {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        gap: 0.4rem;
        padding: 0.4rem 0.6rem;
        margin: 0;
        border-radius: 0;
        border-bottom: 1px solid rgba(var(--ink-rgb), 0.1);
        background: var(--surface);
        /* One row. The old layout wrapped a fourth button onto a second row and
           spent 36px of every screen on it. style.css also pins a 72px
           min-height that has nothing to do with the content. */
        flex-wrap: nowrap;
        min-height: 0;
        overflow: hidden;
        box-sizing: border-box;
    }

    /* Both of these are opaque on a phone - the header takes var(--surface) just
       above, the control bar is 98% - so the frosted glass behind them draws nothing
       whatsoever. All it does is ask the phone to composite two full-width blur layers
       on every frame of every animation. The desktop bars stay frosted; they are
       genuinely translucent. */
    .game-header,
    .controls {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }

    .header-left {
        flex: 0 0 auto;
    }

    /* The <=430px block sets `min-width: 80px`, and min-width beats max-width,
       so without this reset the logo column eats 80px and pushes the last
       header button off the right edge. */
    .header-left {
        min-width: 0;
        max-width: 34px;
        overflow: hidden;
    }

    .header-left .logo-image {
        height: 28px;
        width: auto;
        max-width: 34px;
        margin: 0;
    }

    .header-left .game-logo {
        margin: 0;
    }

    .header-right {
        flex: 0 0 auto;
        /* The <=430px block gives this `width: 100%`, which with the strip in
           the row would push the gear off the right edge of the screen. */
        width: auto;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 0.35rem;
        flex-wrap: nowrap;
        min-width: 0;
    }

    .game-code-display {
        flex: 0 1 auto;
        min-width: 0;
        margin: 0;
        padding: 0;
        background: none;
        border: 0;
    }

    .share-link {
        font-size: 0.72rem;
        letter-spacing: 0.06em;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
        max-width: 8ch;
    }

    /* Reset / History / How-to-play collapse to icon-width squares. Their text
       labels are what forced the second header row. */
    .header-right .game-button {
        flex: 0 0 auto;
        width: 38px;
        min-width: 38px;
        height: 40px;
        min-height: 40px;
        padding: 0;
        font-size: 1rem;
        line-height: 1;
        margin: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Settings keeps its glyph and drops its word. Nothing else is left to hide:
       sound and the tutorial moved into the settings menu, and History moved on
       to the last-action strip, which is why the row fits now. */
    .header-right .button-label {
        display: none;
    }

    /* ------------------------------------------- deck button and the gear */

    /* The same box as the desktop bar, a size down: chip and gear share one
       height, border, fill and corner, so the row reads as one set. */
    .deck-button,
    .header-right #settingsButton {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        flex: 0 0 auto;
        height: 40px;
        min-height: 0;
        min-width: 0;
        padding: 0 10px;
        margin: 0;
        box-sizing: border-box;
        border-radius: 10px;
        border: 1px solid rgba(var(--ink-rgb), 0.38);
        background: rgba(var(--ink-rgb), 0.05);
        box-shadow: none;
        color: var(--ink);
        font-family: 'Roboto', sans-serif;
        font-size: 1rem;
        white-space: nowrap;
        cursor: pointer;
        transition: background var(--dur-fast) var(--ease-out),
                    border-color var(--dur-fast) var(--ease-out),
                    transform var(--dur-tap) var(--ease-out);
    }

    .header-right #settingsButton {
        width: 40px;
        padding: 0;
    }

    .deck-button:active,
    .header-center .last-action:active,
    .header-right #settingsButton:active {
        transform: scale(0.96);
    }

    .header-right #settingsButton.is-open {
        background: rgba(var(--ink-rgb), 0.1);
        border-color: rgba(var(--ink-rgb), 0.6);
    }

    .deck-button[aria-expanded="true"] {
        border-color: var(--highlight);
        background: rgba(204, 51, 80, 0.14);
    }

    .deck-button-count {
        font-family: 'Cairo Play', sans-serif;
        font-size: 1.05rem;
        font-weight: 700;
        line-height: 1;
        font-variant-numeric: tabular-nums;
    }

    .deck-button-label {
        font-size: 0.58rem;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        opacity: 0.6;
    }

    /* ------------------------------------------------------ last-move strip */

    /* The same bar as desktop: the strip sits between the logo and the chip,
       and takes whatever width the three fixed things leave it. A long line
       (a Swap names two players and two cards) ends in an ellipsis rather
       than wrapping the header. Two classes deep because the base
       .last-action rule sits later in the file. */
    .header-center {
        display: flex;
        align-items: center;
        flex: 1 1 auto;
        min-width: 0;
    }

    .header-center .last-action {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
        height: 40px;
        box-sizing: border-box;
        padding: 0 10px;
        gap: 6px;
        /* The same edge as the chip and the gear beside it, so the three read as
           one set; a fainter line here made the strip look like a different box. */
        border: 1px solid rgba(var(--ink-rgb), 0.38);
        border-radius: 10px;
        font-size: 0.76rem;
    }

    .header-center .last-action-more {
        font-size: 1rem;
    }

    /* ------------------------------------------------------------ turn strip */

    .turn-strip {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 6px 14px;
        font-size: 0.72rem;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        background: rgba(var(--ink-rgb), 0.04);
        color: rgba(var(--ink-rgb), 0.65);
        border-bottom: 1px solid rgba(var(--ink-rgb), 0.08);
    }

    .turn-strip .turn-pip {
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: rgba(var(--ink-rgb), 0.4);
        flex: none;
    }

    .turn-strip.is-mine {
        background: rgba(204, 51, 80, 0.16);
        color: var(--highlight-text);
        border-bottom-color: rgba(204, 51, 80, 0.3);
    }

    .turn-strip.is-mine .turn-pip {
        background: var(--highlight);
        animation: turn-pip 1.8s var(--ease-out) infinite;
    }

    @keyframes turn-pip {
        0%, 100% { opacity: 1; transform: scale(1); }
        50%      { opacity: 0.45; transform: scale(0.8); }
    }

    /* ------------------------------------------------------------ game board */

    /* Drawn for a 1600x900 window. On anything bigger client.js sets a
       `zoom` on this element so the whole table scales up with the screen
       rather than sitting small in the middle of it - see fitBoardToScreen. */
    .game-board {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        gap: 0;
        padding: 0;
        margin: 0;
        overflow: hidden;
        background: none;
        border: 0;
    }

    /* Desktop's equal-panel container is unused on phones. */
    .players-container {
        display: none;
    }

    /* --------------------------------------------------------- opponent rail */

    .opponent-rail {
        flex: 0 0 auto;
        display: flex;
        gap: 8px;
        padding: 8px 10px;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        border-bottom: 1px solid rgba(var(--ink-rgb), 0.07);
    }

    .opponent-rail::-webkit-scrollbar { display: none; }

    .opponent-rail:empty { display: none; }

    .opp-tile {
        flex: 0 0 auto;
        width: 88px;
        padding: 7px 9px;
        border-radius: 11px;
        background: var(--surface-2);
        border: 1px solid rgba(var(--ink-rgb), 0.1);
        color: var(--ink);
        font-family: inherit;
        text-align: left;
        cursor: pointer;
        display: flex;
        flex-direction: column;
        gap: 1px;
        transition: border-color var(--dur-fast) var(--ease-out),
                    transform var(--dur-tap) var(--ease-out);
    }

    .opp-tile:active { transform: scale(0.96); }

    .opp-tile.turn-now {
        border-color: var(--highlight);
        background: rgba(204, 51, 80, 0.18);
    }

    .opp-tile.is-out { opacity: 0.55; }
    .opp-tile.is-away { opacity: 0.4; }

    .opp-name {
        font-size: 0.72rem;
        font-weight: 700;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        text-transform: uppercase;
        letter-spacing: 0.03em;
    }

    .opp-score {
        font-size: 1.15rem;
        font-weight: 700;
        line-height: 1.1;
        font-variant-numeric: tabular-nums;
    }

    .opp-status {
        font-size: 0.58rem;
        opacity: 0.7;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .opp-pips {
        display: flex;
        gap: 2px;
        margin-top: 4px;
    }

    .opp-pips i {
        flex: 1;
        height: 3px;
        border-radius: 2px;
        background: rgba(var(--ink-rgb), 0.16);
    }

    .opp-pips i.on { background: var(--highlight); }

    /* ---------------------------------------------------------- my own hand */

    /* The only scrolling region in the game. */
    .my-hand {
        display: block;   /* undoes the desktop hide at the top of this file */
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        padding: 10px;
        scrollbar-width: none;
    }

    .my-hand::-webkit-scrollbar { display: none; }

    .my-hand .player {
        width: 100%;
        min-width: 0;
        max-width: none;
        margin: 0;
        padding: 12px;
        border-radius: 14px;
        /* content-box (the default the 431-767px block leaves it at) adds the
           24px of padding on top of width:100%, so the right edge of your own
           hand was clipped by the scroller. */
        box-sizing: border-box;
    }

    /* The breathing ring is for spotting your seat among many. On a phone your
       hand is the whole screen, so it is just noise. */
    .my-hand .player.current-turn {
        animation: none;
    }

    .my-hand .player-header h3 {
        font-size: 0.95rem;
        margin: 0;
    }

    .my-hand .scores {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 6px;
        margin: 10px 0;
    }

    .my-hand .score-box {
        padding: 7px 8px;
        min-width: 0;
    }

    .my-hand .score-value {
        font-size: 1.3rem;
    }

    /* Four columns instead of seven. At 360px that takes a card from 41px to
       74px, which is the difference between guessing and reading. */
    .my-hand .card-grid {
        --cols: 4;
        --cell-gap: 7px;
        padding: 8px;
        width: 100%;
        /* The base rule's `margin: 0.5rem` plus `width: 100%` pushed the grid
           8px past its own box, so the right-hand column was clipped while the
           left had a double gap. */
        margin: 0;
        box-sizing: border-box;
    }

    .my-hand .card,
    .my-hand .empty-slot {
        width: auto;
        height: auto;
        aspect-ratio: 5 / 7;
        min-width: 0;
        font-size: clamp(1rem, 5.5vw, 1.7rem);
        border-radius: 9px;
    }

    .my-hand .card.special {
        width: auto;
        height: auto;
        font-size: clamp(0.8rem, 4vw, 1.2rem);
    }

    .my-hand .cards-label {
        font-size: 0.58rem;
        letter-spacing: 0.14em;
        margin-bottom: 2px;
    }

    /* --------------------------------------------------------- the thumb bar */

    .controls {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        /* 200, below --z-popup (400): at 500 the bar painted over every popup
           and swallowed the bottom ~60px of each bottom sheet, including the
           Hold-to-view pill. The buttons are disabled while a popup is open
           anyway, so nothing is lost by letting the sheet cover them. */
        z-index: var(--z-controls);
        /* client.js sets an inline `display: flex` on this element, and inline
           wins over any stylesheet — so the proportions come from flex-grow
           rather than grid columns, which that inline style would defeat. */
        display: flex;
        gap: 10px;
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
        margin: 0;
        background: var(--surface);
        border-top: 1px solid rgba(var(--ink-rgb), 0.1);
        width: 100%;
        box-sizing: border-box;
        /* Not the 60px an older breakpoint still asks for. With border-box, a phone that
           has a home indicator spends 44px of that on bottom padding and leaves 6px for
           a 54px button - so the buttons hung above their own bar with the board showing
           behind them. Sized by its contents, the bar is exactly the 74px + inset that
           .game-container reserves below. */
        height: auto;
    }

    /* The bar is fixed, so the shell has to reserve its height or it covers the
       last row of cards. 54px button + 20px padding + the home indicator. */
    .game-container {
        padding-bottom: calc(74px + env(safe-area-inset-bottom));
    }

    .controls .game-button {
        height: 54px;              /* comfortably over the 44px tap minimum */
        min-height: 54px;
        width: auto;
        flex: 1 1 0;
        margin: 0;
        padding: 0;
        border-radius: 13px;
        font-size: 1rem;
        letter-spacing: 0.09em;
    }

    /* Hit is the action you reach for most, so it gets the wider half. */
    .controls #flipCard {
        flex-grow: 1.35;
    }

    /* ------------------------------------------------- deck as a bottom sheet */

    /* Open/closed is a display switch, not a fade. If visibility depended on a
       transition finishing, a stalled or reduced-motion browser would leave the
       sheet permanently invisible — the animation decorates, it never gates. */
    .deck-area {
        display: none;
    }

    body.deck-sheet-open .deck-area {
        position: fixed;
        inset: 0;
        z-index: 900;
        display: flex;
        /* The base rule makes this a *column*, so the main axis is vertical:
           `align-items: flex-end` only pushed the sheet to the right, and
           `justify-content: stretch` is not a thing on a main axis, so it fell
           back to flex-start and the bottom sheet sat at the top of the screen. */
        flex-direction: column;
        justify-content: flex-end;
        align-items: stretch;
        padding: 0;
        margin: 0;
        background: rgba(var(--scrim-rgb), calc(0.66 * var(--scrim-mul)));
        opacity: 1;
        pointer-events: auto;
        animation: scrim-in var(--dur-fast) var(--ease-out);
    }

    .deck-area .discard-info {
        width: 100%;
        max-width: none;
        /* Without this the base rule's 1.5rem padding is *added* to width:100%
           and the sheet ends up 417px wide on a 393px screen, hanging off both
           edges. */
        box-sizing: border-box;
        max-height: 72dvh;
        margin: 0;
        padding: 10px 12px calc(18px + env(safe-area-inset-bottom));
        border-radius: 20px 20px 0 0;
        background: var(--surface);
        border: 0;
        border-top: 1px solid rgba(var(--ink-rgb), 0.12);
        display: flex;
        flex-direction: column;
        gap: 8px;
        overflow: hidden;
        /* Resting position is on-screen; the keyframe only slides it in. */
        transform: none;
        animation: sheet-up var(--dur-base) var(--ease-back);
    }

    @keyframes sheet-up {
        from { transform: translateY(100%); }
        to   { transform: none; }
    }

    /* Grab handle, so the sheet reads as a sheet. */
    .deck-area .discard-info::before {
        content: "";
        width: 36px;
        height: 4px;
        border-radius: 2px;
        background: rgba(var(--ink-rgb), 0.22);
        margin: 0 auto 2px;
        flex: none;
    }

    .deck-stats-container {
        flex: 0 0 auto;
        display: flex;
        /* "Cards left" and "Last card drawn" are two labels at 1.4rem with
           nowrap and a 3rem gap — 411px of content in a 391px box. Wrapping is
           what keeps the last card on screen instead of half off it. */
        flex-wrap: wrap;
        align-items: center;
        gap: 6px 12px;
        justify-content: space-between;
        margin: 0;
        padding: 6px 8px;
        box-sizing: border-box;
        width: 100%;
        max-width: 100%;
    }

    .deck-area .deck-stat-item {
        gap: 0.4rem;
        min-width: 0;
    }

    .deck-area .stat-label {
        font-size: 0.7rem;
        letter-spacing: 0.04em;
    }

    .deck-area .stat-value {
        font-size: 1rem;
    }

    .remaining-pile {
        flex: 1 1 auto;
        min-height: 0;
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        padding: 4px 0;
        margin: 0;
        display: flex;
        flex-direction: column;
        gap: 10px;
    }

    .remaining-pile .regular-cards,
    .remaining-pile .special-cards {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
        gap: 5px;
        margin: 0;
        padding: 0;
    }

    .remaining-card {
        width: auto;
        height: auto;
        aspect-ratio: 5 / 7;
        min-width: 0;
        font-size: 0.8rem;
        border-radius: 6px;
    }

    /* ---------------------------------------------------- opponent hand sheet */

    .player-sheet {
        position: fixed;
        inset: 0;
        z-index: 950;
        display: flex;
        align-items: flex-end;
        background: rgba(var(--scrim-rgb), calc(0.66 * var(--scrim-mul)));
    }

    .player-sheet .popup-content {
        position: relative;
        width: 100%;
        max-height: 80dvh;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding: 10px 12px calc(18px + env(safe-area-inset-bottom));
        border-radius: 20px 20px 0 0;
        background: var(--surface);
        border: 0;
        border-top: 1px solid rgba(var(--ink-rgb), 0.12);
        transform: none;
        left: auto;
        top: auto;
    }

    .player-sheet .sheet-grab {
        width: 36px;
        height: 4px;
        border-radius: 2px;
        background: rgba(var(--ink-rgb), 0.22);
        margin: 0 auto 10px;
    }

    .player-sheet .close-button {
        position: absolute;
        top: 12px;
        right: 12px;
        width: 34px;
        height: 34px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .player-sheet .player {
        width: 100%;
        margin: 0;
        padding: 10px 0 0;
        background: none;
        border: 0;
        box-shadow: none;
        animation: none;
    }

    .player-sheet .card-grid {
        --cols: 7;
        --cell-gap: 5px;
    }

    .player-sheet .card,
    .player-sheet .empty-slot {
        width: auto;
        height: auto;
        aspect-ratio: 5 / 7;
        min-width: 0;
        font-size: 0.85rem;
    }

    /* ------------------------------------------------------- popups on phones */

    /* Every popup shell becomes a bottom sheet: reachable by thumb, and it
       cannot overflow a short viewport the way a centred box does. */
    .winner-popup .popup-content,
    .round-summary-popup .popup-content,
    .freeze-popup .popup-content,
    .draw-three-popup .popup-content,
    .remove-card-popup .popup-content,
    .steal-card-popup .popup-content,
    .swap-card-popup .popup-content,
    .select-card-popup .popup-content,
    .history-popup .popup-content {
        width: 100%;
        max-width: none;
        max-height: 82dvh;
        overflow-y: auto;
        overscroll-behavior: contain;
        border-radius: 18px 18px 0 0;
        padding: 16px 14px calc(20px + env(safe-area-inset-bottom));
        box-sizing: border-box;
        /* The shared desktop rule puts `margin: 20px` on every popup body. On a
           full-width sheet that leaves a 20px gutter down each side, so the
           sheet reads as a floating box with cropped corners instead. */
        margin: 0;
    }

    .winner-popup,
    .round-summary-popup,
    .freeze-popup,
    .draw-three-popup,
    .remove-card-popup,
    .steal-card-popup,
    .swap-card-popup,
    .select-card-popup,
    .history-popup {
        display: flex;
        align-items: flex-end;
        justify-content: center;
        padding: 0;
        /* The <=430px block puts `width: 90%`, `height: 100vh` and
           `max-height: 80vh` on the *scrims* rather than on the boxes inside
           them, so a scrim ended 171px short of the bottom of the screen and
           took the sheet anchored to it along. */
        width: 100%;
        height: 100%;
        max-width: none;
        max-height: none;
        /* The sheet scrolls; the scrim behind it never does. */
        overflow: hidden;
        /* A popup shell that carries its own border for a centred box would
           show it here as a hairline around the whole phone. */
        border: 0;
        z-index: var(--z-popup);
    }

    /* These shells centre their content with translate(-50%, -50%); as a bottom
       sheet that would drag it back off-screen. */
    .round-summary-popup .popup-content,
    .winner-popup .popup-content {
        position: relative;
        left: auto;
        top: auto;
        transform: none;
        animation-name: sheet-in;
    }

    /* Card pickers inside popups need thumb-sized targets. */
    .card-button {
        min-height: 52px;
        min-width: 44px;
    }

    /* Hold-to-view is absolutely positioned at `bottom: 25px` on desktop, which
       inside a scrolling sheet lands it on top of the target buttons. In the
       flow it is just the last row of the sheet. */
    .view-game-button {
        /* Sticky, not static: in a tall picker the last row of the sheet is two
           screens down, and the whole point of this button is that it is there
           when you want to check the board. */
        position: sticky;
        bottom: 0;
        z-index: 1;
        transform: none;
        width: 100%;
        margin: 4px 0 0;
        padding: 14px 18px;
        min-height: 52px;
        justify-content: center;
        box-sizing: border-box;
    }

    /* Two classes beat one, so the desktop rule that lifts this pill 85px off
       the bottom of the swap picker would otherwise win here and leave it
       stranded mid-sheet. */
    .swap-card-popup .view-game-button {
        bottom: 0;
    }

    /* The swap sheet pads itself with !important, 140px of it at the bottom to
       clear two absolutely positioned buttons. Both are in the flow here, so
       that reservation is just empty space at the end of the card list. */
    .swap-card-popup .popup-content {
        padding: 16px 14px calc(20px + env(safe-area-inset-bottom)) !important;
    }

    /* Confirm is the primary action, and absolutely positioned it floated over
       the middle of the card list. Sticky above the peek pill keeps both
       reachable however far down the list you are. */
    .confirm-swap-button {
        position: sticky;
        bottom: 56px;
        left: auto;
        transform: none;
        width: 100%;
        min-height: 52px;
        margin: 4px 0 0;
        box-sizing: border-box;
        z-index: 2;
    }

    .confirm-swap-button:hover:not(:disabled) {
        transform: none;
    }

    /* -------------------------------------------------------------- the lobby */

    /* The lobby scrolls inside itself, same rule as the hand — the page never
       scrolls, so the browser chrome never collapses. */
    .lobby-screen {
        padding: 1rem 1rem calc(2rem + env(safe-area-inset-bottom));
        margin: 0;
        width: 100%;
        max-width: none;
        box-sizing: border-box;
        overflow-y: auto;
        max-height: 100dvh;
    }

    .lobby-screen .logo-image {
        max-width: 96px;
    }

    .lobby-screen .game-logo {
        margin: 0.75rem 0;
    }

    .menu-container {
        padding: 1.25rem;
        margin: 0;
        width: 100%;
        box-sizing: border-box;
    }

    .lobby-button {
        min-height: 52px;
        width: 100%;
        font-size: 1rem;
    }

    /* 16px is the threshold below which iOS zooms the page on focus. */
    .lobby-form input[type="text"] {
        font-size: 16px;
        min-height: 48px;
        width: 100%;
        box-sizing: border-box;
    }

    /* ---------------------------------------------------------- notifications */

    .game-notification,
    .restart-notice {
        top: calc(env(safe-area-inset-top) + 8px);
        left: 8px;
        right: 8px;
        max-width: none;
        transform: none;
        font-size: 0.85rem;
    }

    .game-notification.fade-out {
        transform: translateY(-12px);
    }
}

/* ==========================================================================
   Very small phones — folded Galaxy Fold is 280px, older Androids 320px.
   ========================================================================== */

@media screen and (max-width: 340px) {
    .opp-tile { width: 76px; }

    /* At 280px the deck pill and the logo meet with nothing between them. The
       count and the last card carry the meaning; the word "left" does not. */
    .deck-button { padding: 0 6px; gap: 3px; }
    .deck-button-label { display: none; }

    .my-hand .card-grid { --cell-gap: 5px; padding: 6px; }

    .share-link { display: none; }

    .controls .game-button { font-size: 0.85rem; letter-spacing: 0.05em; }
}

/* ==========================================================================
   Landscape — a phone on its side has roughly 380px of height, so the rail
   moves alongside the hand instead of stacking above it.
   ========================================================================== */

@media screen and (max-width: 950px) and (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
    .game-board {
        flex-direction: row;
        gap: 0;
    }

    .opponent-rail {
        flex: 0 0 108px;
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: auto;
        border-bottom: 0;
        border-right: 1px solid rgba(var(--ink-rgb), 0.07);
        padding: 8px;
    }

    .opp-tile {
        width: 100%;
    }

    .my-hand {
        flex: 1 1 auto;
        padding: 8px;
    }

    /* Height is the scarce axis here, so spend width instead of stacking — but
       a fixed 7 columns squeezed cards to 33px once the two grids sat side by
       side. auto-fill holds a floor and wraps instead of shrinking past it. */
    .my-hand .card-grid,
    .my-hand .card-grid.special {
        grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
    }

    /* Regular and special grids share the row; without this they split the
       width evenly regardless of how many cards each is actually holding. */
    .my-hand .cards-section {
        display: flex;
        flex-direction: row;
        gap: 8px;
        align-items: flex-start;
    }

    .my-hand .cards-container {
        flex: 1 1 0;
        min-width: 0;
    }

    .my-hand .scores {
        margin: 6px 0;
    }

    .turn-strip {
        padding: 4px 12px;
        font-size: 0.65rem;
    }

    /* Side-by-side keeps the buttons out of the middle of a short screen. */
    .controls {
        grid-template-columns: 1fr 1fr;
        padding: 6px 10px calc(6px + env(safe-area-inset-bottom));
    }

    .controls .game-button {
        height: 44px;
        min-height: 44px;
    }

    .game-container {
        padding-bottom: calc(56px + env(safe-area-inset-bottom));
    }

    .game-header {
        padding: 0.25rem 0.6rem;
    }

    .header-left .logo-image {
        height: 24px;
    }
}

/* ==========================================================================
   Peek mode — the touch counterpart of hold-to-view.
   Last in the file on purpose: it has to outrank each popup's own background,
   several of which are already !important.
   ========================================================================== */

.popup-peeking {
    background: transparent !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    /* The board underneath stays look-only; the one exception is the pill. */
    pointer-events: none;
}

.popup-peeking .popup-content {
    background: transparent !important;
    box-shadow: none !important;
    border-color: transparent !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
}

/* visibility, not display: the sheet keeps its height so the pill does not
   jump to a new place between taps. */
.popup-peeking .popup-content > *:not(.view-game-button) {
    visibility: hidden;
}

.popup-peeking .view-game-button {
    pointer-events: auto;
    background: var(--surface);
    border-color: var(--highlight);
    box-shadow: 0 6px 18px rgba(var(--shadow-rgb), 0.45);
}

/* While peeking, this pill is the only thing on screen you can touch - it is the
   way back to the picker. Sticky at the foot of the sheet put it 29px off the
   bottom of the phone, which is inside the strip iOS Safari's toolbar slides
   back into and where the home indicator lives: the first tap summons the
   toolbar instead of pressing the button. Reported from real play as "very low,
   almost unclickable".

   Fixed rather than sticky because while peeking the sheet is invisible, so the
   pill should be placed for the thumb, not for a box nobody can see. It clears
   the safe area and the toolbar strip, and lands in the same spot every time
   regardless of how tall the picker behind it happens to be. */
.popup-peeking .view-game-button {
    /* Sticky, not fixed: .popup-content carries a transform through its entrance
       animation, which makes it the containing block for a fixed child - the pill
       would anchor to the sheet instead of the screen and land lower still. The
       sheet is bottom-anchored, so lifting the sticky offset moves the pill up
       the screen just as reliably and cannot be re-parented.
       Plain px first as the fallback for anything without env(). */
    /* Two cases, and the lift has to survive both. When the picker is short
       enough to fit, nothing scrolls and sticky does nothing at all - the margin
       is what raises the pill. When it is tall enough to scroll, the margin is
       out of view below and the sticky offset is what holds the pill up. */
    margin-bottom: 84px;
    margin-bottom: calc(84px + env(safe-area-inset-bottom));
    bottom: 84px;
    bottom: calc(84px + env(safe-area-inset-bottom));
}

/* ==========================================================================
   Big phones and small tablet windows still get the phone layout, but not the
   phone's card size. Four columns was sized for a 360px screen; at 600px it
   inflates every card to 128px and pushes the special row off the first
   screenful. Comes after the phone block on purpose — same specificity, so
   source order is what lets it win.
   ========================================================================== */

@media screen and (min-width: 431px) and (max-width: 767px) {
    .my-hand .card-grid {
        --cols: 7;
    }
}

/* ==========================================================================
   Lobby settings, and the end-of-game highlights
   ========================================================================== */

/* Both panels grew taller than the screen once they had content in them, and
   neither had anywhere to put the overflow. */
.waiting-screen {
    max-height: calc(100vh - 2rem);
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
}

/* One column of link, settings, players and buttons is about 1160px tall -
   taller than any laptop screen - so on a wide screen it becomes two: how to
   set the game up on the left, who is here and the start button on the right.
   That is about 720px, and the panel stops needing to scroll. */
@media screen and (min-width: 900px) and (min-height: 501px) {
    .waiting-screen {
        max-width: 960px;
        display: grid;
        grid-template-columns: 1fr 1fr;
        /* The settings box is the tallest thing and sets the height. The
           players box stretches to meet the two buttons, which sit level
           with the bottom of the settings box, so both columns end together. */
        grid-template-rows: auto auto 1fr auto auto;
        grid-template-areas:
            "title    title"
            "share    players"
            "settings players"
            "settings start"
            "settings exit";
        gap: 1rem 1.5rem;
        align-items: start;
    }

    .waiting-screen .players-list {
        align-self: stretch;
        box-sizing: border-box;
    }

    /* The same box the players list and the settings wear, so the two
       columns start with matching corners. */
    .waiting-screen .share-section {
        background: rgba(var(--shadow-rgb), 0.2);
        padding: 1rem;
        border-radius: 10px;
        box-sizing: border-box;
    }

    /* Six bot counts in one row: at 72px each they were five and a lone 5. */
    .waiting-screen .setting-option {
        min-width: 56px;
    }

    .waiting-screen > h2,
    .waiting-screen .share-section,
    .waiting-screen .lobby-settings,
    .waiting-screen .players-list,
    .waiting-screen .button-group,
    .waiting-screen > p {
        margin: 0;
    }

    .waiting-screen > h2 { grid-area: title; }
    .waiting-screen .share-section { grid-area: share; }
    .waiting-screen .lobby-settings { grid-area: settings; }
    .waiting-screen .players-list { grid-area: players; }
    .waiting-screen .button-group,
    .waiting-screen > p { grid-area: start; }
    .waiting-screen .lobby-exit-group { grid-area: exit; }

    /* A guest has no link to share, so the settings take the whole column. */
    .waiting-screen:not(:has(.share-section)) .lobby-settings {
        grid-row: share-start / settings-end;
    }

    /* Ten names is a tall list; let it run rather than scroll inside a
       panel that no longer scrolls itself. */
    .waiting-screen .players-list {
        max-height: none;
    }
}

/* The overlay centres its child, which clips the top of anything taller than the
   viewport. auto margins centre it without doing that. */
.winner-popup .popup-content {
    margin: auto;
}

.lobby-settings {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    background: rgba(var(--shadow-rgb), 0.2);
    padding: var(--space-4);
    border-radius: var(--radius-md);
    margin: var(--space-4) 0;
    text-align: left;
}

.setting-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.setting-label {
    color: var(--highlight);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.setting-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* One rule for both, because the non-host copy has to read as the same control,
   just not pressable. */
.setting-option {
    flex: 1 1 auto;
    min-width: 72px;
    /* Thumb-sized, because the score row is four small buttons on a phone. */
    min-height: 44px;
    justify-content: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    border: 2px solid rgba(204, 51, 80, 0.25);
    background: rgba(var(--ink-rgb), 0.06);
    color: var(--ink);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
}

button.setting-option {
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out),
                transform var(--dur-tap) var(--ease-out);
}

button.setting-option:hover {
    border-color: rgba(204, 51, 80, 0.6);
    background: rgba(var(--ink-rgb), 0.1);
}

button.setting-option:active {
    transform: scale(0.97);
}

.setting-option.selected {
    border-color: var(--highlight);
    background: rgba(204, 51, 80, 0.18);
}

.setting-sub {
    font-size: 0.7rem;
    font-weight: 400;
    color: rgba(var(--ink-rgb), 0.6);
}

.setting-blurb {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.4;
    color: rgba(var(--ink-rgb), 0.6);
}

/* Says what game you are in without costing a row of its own. */

.awards {
    margin: 2rem 0 0;
    text-align: left;
}

.awards h3 {
    color: var(--highlight);
    text-align: center;
    margin-bottom: 1rem;
}

.awards-container {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.award-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: rgba(var(--surface-rgb), 0.9);
    border: 1px solid rgba(204, 51, 80, 0.2);
    border-radius: var(--radius-sm);
}

.award-icon {
    font-size: 1.5rem;
    line-height: 1;
    flex: 0 0 auto;
}

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

.award-title {
    color: rgba(var(--ink-rgb), 0.6);
    font-size: 0.72rem;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.award-holder {
    color: var(--ink);
    font-weight: 700;
    overflow-wrap: anywhere;
}

.award-value {
    flex: 0 0 auto;
    max-width: 40%;
    text-align: right;
}

.award-value strong {
    display: block;
    color: var(--success);
    font-size: 1.25rem;
    line-height: 1.1;
}

.award-value span {
    color: rgba(var(--ink-rgb), 0.5);
    font-size: 0.68rem;
    line-height: 1.2;
}

@media screen and (max-width: 430px) {
    .setting-option {
        min-width: 64px;
        font-size: 0.85rem;
    }

    .award-row {
        gap: var(--space-2);
        padding: var(--space-2);
    }

    .award-value span {
        display: none;
    }
}

/* Small enough to ignore, findable enough to ask about. See BUILD in client.js. */
.htp-build {
    margin: var(--space-5) 0 0;
    text-align: center;
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    color: rgba(var(--ink-rgb), 0.35);
}

/* ---------------------------------------------------------------------------
   Settings menu

   Replaces the Reset, Sound and How to Play buttons that used to sit across the
   header. Three buttons became one, which is most of the reason the phone header
   stopped being a scrum.
   --------------------------------------------------------------------------- */

.settings-menu-wrap {
    position: relative;
    display: inline-flex;
}

/* The gear is chrome, not an action, so it does not wear the pink the play
   buttons use. */
#settingsButton {
    background: var(--surface-2);
    box-shadow: none;
}

#settingsButton:hover:not(:disabled),
#settingsButton.is-open {
    background: rgba(var(--ink-rgb), 0.16);
}

/* With the menu shut there is nothing else to say the game is muted - the
   speaker that used to say it is inside the menu now. */
#settingsButton.is-muted::after {
    content: '';
    position: absolute;
    top: 6px;
    right: 6px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--warning);
    border: 2px solid var(--surface);
    box-sizing: content-box;
}

/* Fixed, not absolute, and placed by placeSettingsMenu(). `.game-header` is
   `overflow: hidden` and only as tall as one button, so an absolutely positioned
   dropdown inside it is clipped to nothing - it measures the right size and paints
   none of it.

   Escaping that overflow needs both halves: fixed positioning AND no ancestor that
   is a containing block for it. A transform, a filter or a backdrop-filter on any
   ancestor makes that ancestor the containing block, and the escape quietly stops
   working - which is exactly what the header's glass backdrop-filter did to this menu.
   wireSettingsMenu() moves the element to <body> for that reason; do not put it back
   inside the header on the strength of `position: fixed` alone. */
.settings-menu {
    position: fixed;
    z-index: var(--z-popup);
    width: 266px;
    max-width: calc(100vw - 24px);
    background: var(--surface);
    border: 1px solid rgba(var(--ink-rgb), 0.14);
    border-radius: var(--radius-md, 12px);
    box-shadow: 0 12px 32px rgba(var(--shadow-rgb), 0.45);
    overflow: hidden;
    text-align: left;
}

/* The deck and target score, which used to be a badge in the header. A caption, not
   a control: it is the one thing in this menu nobody can change mid-game. */
.settings-mode {
    margin: 0;
    padding: 0.55rem 0.9rem;
    background: rgba(204, 51, 80, 0.12);
    border-bottom: 1px solid rgba(var(--ink-rgb), 0.08);
    color: rgba(var(--ink-rgb), 0.8);
    font-size: 0.75rem;
    letter-spacing: 0.03em;
}

.settings-item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    width: 100%;
    padding: 0.75rem 0.9rem;
    background: transparent;
    border: none;
    border-bottom: 1px solid rgba(var(--ink-rgb), 0.08);
    color: var(--ink);
    font-family: inherit;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}

.settings-menu > .settings-item:last-child,
.settings-group .settings-item:last-child {
    border-bottom: none;
}

.settings-item:hover,
.settings-item:focus-visible {
    background: rgba(var(--ink-rgb), 0.07);
}

.settings-icon {
    font-size: 1rem;
    line-height: 1;
    flex: 0 0 auto;
}

.settings-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1;
    min-width: 0;
}

.settings-label {
    line-height: 1.2;
}

.settings-hint {
    font-size: 0.75rem;
    color: rgba(var(--ink-rgb), 0.55);
    line-height: 1.3;
}

.settings-state {
    flex: 0 0 auto;
    font-size: 0.7rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: var(--success);
    color: var(--on-accent);
}

.settings-state.is-off {
    background: rgba(var(--ink-rgb), 0.18);
    color: rgba(var(--ink-rgb), 0.7);
}

/* A value that is neither on nor off - the Theme row says System, Light or Dark. */
.settings-state.is-neutral {
    background: rgba(var(--ink-rgb), 0.1);
    border: 1px solid var(--line-strong);
    color: var(--ink);
}

/* The two that end or unwind the game. Kept behind a labelled divider so neither
   is ever the neighbour of a harmless one. */
.settings-group {
    border-top: 1px solid rgba(var(--ink-rgb), 0.12);
}

.settings-group-title {
    margin: 0;
    padding: 0.4rem 0.9rem;
    background: rgba(var(--ink-rgb), 0.04);
    color: rgba(var(--ink-rgb), 0.4);
    font-size: 0.65rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.settings-item.is-danger .settings-label {
    color: var(--highlight-text);
}

/* ---------------------------------------------------------------------------
   Last-action strip

   What just happened, directly under the header, on every screen - unlike the turn
   strip above it, which is phone-only. It is also the only way into the full log:
   the History button that used to sit in the header did the same job from further
   away, so this took it over and the header lost a button.
   --------------------------------------------------------------------------- */

.last-action {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    flex: 0 0 auto;
    padding: 8px 16px;
    background: rgba(var(--ink-rgb), 0.05);
    border: none;
    border-bottom: 1px solid rgba(var(--ink-rgb), 0.08);
    border-radius: 0;
    color: rgba(var(--ink-rgb), 0.75);
    font-family: 'Roboto', sans-serif;
    font-size: 0.82rem;
    text-align: left;
    cursor: pointer;
    /* Same fade as the chip and the gear it shares the bar with. */
    transition: background var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                transform var(--dur-tap) var(--ease-out);
}

.last-action:hover,
.last-action:focus-visible {
    background: rgba(var(--ink-rgb), 0.1);
}

.last-action-icon {
    flex: 0 0 auto;
    font-size: 0.95rem;
    line-height: 1;
}

/* One line. A Swap names two players and two cards, which would otherwise wrap the
   strip to three rows and push the board down every time somebody played one. */
.last-action-text {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The whole row is the button; this is what says so. */
.last-action-more {
    flex: 0 0 auto;
    font-size: 1.1rem;
    line-height: 1;
    color: rgba(var(--ink-rgb), 0.35);
}

.last-action:hover .last-action-more {
    color: rgba(var(--ink-rgb), 0.7);
}

/* A move you were not watching for should catch your eye for one second and
   then stop. client.js strips is-new afterwards, so the flash can never be
   replayed by a later reflow or display toggle. */
.last-action.is-new {
    animation: last-action-flash 500ms var(--ease-out) 2;
}

@keyframes last-action-flash {
    0%, 100% { background: rgba(var(--ink-rgb), 0.05); }
    50%      { background: rgba(204, 51, 80, 0.22); }
}

@media (prefers-reduced-motion: reduce) {
    .last-action.is-new {
        animation: none;
    }
}

@media screen and (max-width: 430px) {
    .last-action {
        padding: 7px 14px;
        font-size: 0.76rem;
        gap: 8px;
    }
}


/* ---------------------------------------------------------------------------
   How to play

   Replaces the single scrolling wall of rules with a deck of pages: one idea
   per page, a hero built from real cards, chapters across the top for anyone
   who opened this to check one thing, and Back / Next either way.

   The strip is moved by JS - it tracks the finger 1:1 and then springs - so
   there is deliberately no `transition` on .htp-strip. A transition here would
   fight the spring and make a grabbed page snap instead of follow.
   --------------------------------------------------------------------------- */

.htp {
    position: fixed;
    inset: 0;
    z-index: var(--z-popup);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: rgba(var(--scrim-rgb), calc(0.72 * var(--scrim-mul)));
    -webkit-backdrop-filter: var(--material-thin);
    backdrop-filter: var(--material-thin);
}

.htp-card {
    display: flex;
    flex-direction: column;
    width: min(460px, 100%);
    height: min(700px, 88dvh);
    padding: var(--space-3) var(--space-4) var(--space-4);
    box-sizing: border-box;
    overflow: hidden;
    border: 1px solid rgba(var(--ink-rgb), 0.09);
    border-radius: var(--radius-xl);
    background:
        radial-gradient(120% 70% at 50% -10%, rgba(204, 51, 80, 0.18), transparent 62%),
        linear-gradient(160deg, var(--surface-0), var(--surface));
    box-shadow: 0 24px 60px rgba(var(--shadow-rgb), 0.55);
}

/* Top bar: back, chapters, close */

.htp-bar {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 0 0 auto;
}

.htp-back,
.htp-close {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--radius-circle);
    background: rgba(var(--ink-rgb), 0.09);
    color: rgba(var(--ink-rgb), 0.75);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out),
                opacity var(--dur-fast) var(--ease-out);
}

.htp-back:hover,
.htp-close:hover {
    background: rgba(var(--ink-rgb), 0.16);
}

.htp-back:active,
.htp-close:active {
    transform: scale(0.94);
}

/* Disabled rather than hidden, so the chapter row never shifts sideways
   between page 1 and page 2. */
.htp-back:disabled {
    opacity: 0.25;
    cursor: default;
}

.htp-chapters {
    flex: 1 1 auto;
    display: flex;
    gap: var(--space-1);
    justify-content: center;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.htp-chapters::-webkit-scrollbar {
    display: none;
}

.htp-chapter {
    flex: 0 0 auto;
    padding: var(--space-1) var(--space-3);
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: rgba(var(--ink-rgb), 0.5);
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out);
}

.htp-chapter:hover {
    color: rgba(var(--ink-rgb), 0.85);
}

.htp-chapter.is-on {
    background: rgba(204, 51, 80, 0.9);
    color: var(--on-accent);
    box-shadow: 0 3px 12px rgba(204, 51, 80, 0.32);
}

/* Hero */

.htp-hero {
    flex: 0 0 auto;
    height: clamp(150px, 30dvh, 260px);
    margin-top: var(--space-3);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    border: 1px solid rgba(var(--ink-rgb), 0.08);
    border-radius: var(--radius-lg);
    background: linear-gradient(150deg, rgba(204, 51, 80, 0.14), rgba(var(--surface-2-rgb), 0.5));
    opacity: 1;
    transition: opacity var(--dur-fast) var(--ease-out);
}

.htp-hero.is-swapping {
    opacity: 0;
}

/* Geometry only - the face colour arrives from [data-card-type]. */
.htp-c {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 56px;
    height: 79px;
    border: 1px solid rgba(var(--shadow-rgb), 0.2);
    border-radius: var(--radius-sm);
    font-size: 1.4rem;
    font-weight: 700;
    box-shadow: 0 6px 16px rgba(var(--shadow-rgb), 0.4), inset 0 1px 0 rgba(var(--ink-rgb), 0.3);
}

.htp-c.sm {
    width: 42px;
    height: 60px;
    font-size: 1.05rem;
    border-radius: var(--radius-xs);
}

.htp-deal {
    animation: htp-deal 500ms var(--ease-back) both;
}

@keyframes htp-deal {
    from { transform: translateY(-44px) rotate(-8deg) scale(0.86); opacity: 0; }
    to   { transform: none; opacity: 1; }
}

/* Pages */

.htp-track {
    flex: 1 1 auto;
    position: relative;
    overflow: hidden;
    margin-top: var(--space-2);
    /* Claim the horizontal axis for the drag and leave the vertical one to the
       page, which scrolls when a long note pushes it past the sheet. */
    touch-action: pan-y;
}

.htp-strip {
    display: flex;
    height: 100%;
    will-change: transform;
}

.htp-page {
    flex: 0 0 100%;
    display: flex;
    flex-direction: column;
    padding: var(--space-3) var(--space-1) 0;
    box-sizing: border-box;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* The text sits directly under the hero and the slack falls to the bottom,
   above the controls - centring it in a tall sheet leaves it floating with a
   void on both sides. */
.htp-page-inner {
    margin: 0 0 auto;
}

.htp-pill {
    display: inline-block;
    margin-bottom: var(--space-3);
    padding: var(--space-1) var(--space-3);
    border: 1px solid rgba(204, 51, 80, 0.3);
    border-radius: var(--radius-pill);
    background: rgba(204, 51, 80, 0.16);
    color: var(--highlight-text);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.02em;
}

.htp-title {
    margin: 0 0 var(--space-2);
    font-family: 'Cairo Play', sans-serif;
    font-size: clamp(1.35rem, 5.5vw, 1.6rem);
    line-height: 1.1;
    /* Display sizes read too loose at their default tracking. */
    letter-spacing: -0.025em;
    color: var(--ink);
}

.htp-body {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.62;
    color: rgba(var(--ink-rgb), 0.68);
}

.htp-body b {
    color: var(--ink);
    font-weight: 500;
}

.htp-list {
    margin: 0;
    padding-left: 1.1rem;
}

.htp-list li {
    margin-bottom: var(--space-2);
}

.htp-note {
    margin: var(--space-3) 0 0;
    padding-left: var(--space-3);
    border-left: 2px solid rgba(204, 51, 80, 0.55);
    font-size: 0.83rem;
    line-height: 1.55;
    color: rgba(var(--ink-rgb), 0.5);
}

/* Foot */

.htp-foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-top: var(--space-3);
}

.htp-dots {
    display: flex;
    gap: var(--space-1);
}

.htp-dot {
    width: 6px;
    height: 6px;
    border-radius: var(--radius-pill);
    background: rgba(var(--ink-rgb), 0.24);
    transition: width var(--dur-base) var(--ease-out),
                background var(--dur-base) var(--ease-out);
}

.htp-dot.is-on {
    width: 20px;
    background: var(--highlight);
}

.htp-next {
    flex: 0 0 auto;
    padding: var(--space-3) var(--space-5);
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--card-gradient);
    color: var(--on-accent);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    cursor: pointer;
    box-shadow: 0 8px 20px rgba(204, 51, 80, 0.32);
    transition: transform var(--dur-fast) var(--ease-out);
}

.htp-next:active {
    transform: scale(0.96);
}

.htp-build {
    flex: 0 0 auto;
    margin: var(--space-2) 0 0;
    text-align: center;
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    color: rgba(var(--ink-rgb), 0.22);
}

/* The shared close animation targets .popup-content, which this sheet does not
   use; without this the card would sit still while the scrim faded. */
.htp.popup-closing .htp-card {
    opacity: 0;
    transform: scale(0.97) translateY(6px);
    transition: opacity var(--dur-fast) var(--ease-in),
                transform var(--dur-fast) var(--ease-in);
}

/* Phones: the sheet is the screen. */
@media screen and (max-width: 430px) {
    .htp {
        padding: 0;
        align-items: stretch;
    }

    .htp-card {
        width: 100%;
        height: 100%;
        border: 0;
        border-radius: 0;
        padding-top: max(var(--space-3), env(safe-area-inset-top));
        padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
    }
}

/* Small phones: four chapters plus two round buttons stop fitting, so the
   chips give up their padding before the row starts scrolling. */
@media screen and (max-width: 360px) {
    .htp-chapter {
        padding: var(--space-1) var(--space-2);
        font-size: 0.75rem;
    }
}

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

    .htp-hero,
    .htp-dot,
    .htp-next {
        transition: none;
    }
}


/* ==========================================================================
   DESKTOP ONE-BAR HEADER
   ---------------------------------------------------------------------------
   The exact complement of the phone query at the top of the PHONE LAYOUT block:
   phone = (width <= 767) OR (landscape AND height <= 500 AND coarse), so
   desktop = width >= 768 AND (height >= 501 OR pointer fine). Keep the two in
   step with PHONE_QUERY in client.js, which moves the deck chip and the
   last-move strip between their phone and desktop slots.

   Four boxes became one bar: logo | last move | cards left + gear - the phone
   header, a size up. The grid gives the outer columns equal width so the
   strip is centred on the screen. Every box in the bar is the same height,
   border and fill, the gear included. The remaining pile is a dialog behind
   the deck chip, as it is a sheet on phones - same markup, same body class,
   same close paths. There is no "last card drawn" any more: the strip already
   says who drew what.
   ========================================================================== */
@media screen and (min-width: 768px) and (min-height: 501px),
       screen and (min-width: 768px) and (pointer: fine) {

    .game-header {
        display: grid;
        /* 180px holds the deck chip and the gear; the logo side gets the same
           so the strip stays centred on the screen at every width. */
        grid-template-columns: minmax(180px, 1fr) minmax(0, 920px) minmax(180px, 1fr);
        align-items: center;
        gap: 1rem;
        min-height: 0;
        padding: 0.55rem 1.25rem;
        margin-bottom: 0.75rem;
        /* .game-container is a flex column the height of the screen; without
           this the bar gives up its own height to the board and clips. */
        flex: 0 0 auto;
    }

    .header-left {
        justify-self: start;
        min-width: 0;
        max-width: 100%;
        height: auto;
    }

    .header-left .logo-image {
        height: 48px;
        margin-right: 0;
    }

    .header-right {
        justify-self: end;
        flex: 0 0 auto;
        height: auto;
        gap: 0.75rem;
    }

    .header-center {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        min-width: 0;
    }

    /* ---- the chip and the gear: one box, so the bar reads as one thing ---- */

    .deck-button,
    .header-right #settingsButton {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        flex: 0 0 auto;
        height: 44px;
        min-height: 0;
        min-width: 0;
        padding: 0 12px;
        margin: 0;
        box-sizing: border-box;
        border-radius: 12px;
        border: 1px solid rgba(var(--ink-rgb), 0.38);
        background: rgba(var(--ink-rgb), 0.05);
        box-shadow: none;
        color: var(--ink);
        font-family: 'Roboto', sans-serif;
        font-size: 1rem;
        white-space: nowrap;
        cursor: pointer;
        transition: background var(--dur-fast) var(--ease-out),
                    border-color var(--dur-fast) var(--ease-out),
                    transform var(--dur-tap) var(--ease-out);
    }

    /* Icon only, a square, so it weighs about the same as the logo. */
    .header-right #settingsButton {
        width: 44px;
        padding: 0;
    }

    .header-right #settingsButton .button-label {
        display: none;
    }

    .deck-button:hover,
    .deck-button:focus-visible,
    .header-center .last-action:hover,
    .header-center .last-action:focus-visible,
    .header-right #settingsButton:hover:not(:disabled),
    .header-right #settingsButton.is-open {
        background: rgba(var(--ink-rgb), 0.1);
        border-color: rgba(var(--ink-rgb), 0.6);
    }

    /* The gear is a .game-button, so it already lifts 2px on hover like every
       other button in the app. The chip and the strip are not, so they get
       the same lift here - three boxes in one bar, one hover, one press. */
    .deck-button:hover,
    .header-center .last-action:hover {
        transform: translateY(-2px);
    }

    .deck-button:active,
    .header-center .last-action:active,
    .header-right #settingsButton:active {
        transform: translateY(0) scale(0.97);
    }

    .deck-button[aria-expanded="true"] {
        border-color: var(--highlight);
        background: rgba(204, 51, 80, 0.14);
    }

    .deck-button-count {
        font-family: 'Cairo Play', sans-serif;
        font-size: 1.3rem;
        font-weight: 700;
        line-height: 1;
        font-variant-numeric: tabular-nums;
    }

    .deck-button-label {
        font-size: 0.66rem;
        font-weight: 700;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        opacity: 0.6;
    }

    /* ---- the strip becomes a pill in the middle of the bar ---- */

    .header-center .last-action {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
        height: 44px;
        box-sizing: border-box;
        padding: 0 14px;
        /* The same edge as the chip and the gear beside it, so the three read as
           one set; a fainter line here made the strip look like a different box. */
        border: 1px solid rgba(var(--ink-rgb), 0.38);
        border-radius: 12px;
        font-size: 0.86rem;
    }

    /* ---- the remaining pile is a dialog behind the chips ---- */

    /* Same rule as the phone sheet: open/closed is a display switch, never the
       end of an animation. */
    .deck-area {
        display: none;
    }

    body.deck-sheet-open .deck-area {
        position: fixed;
        inset: 0;
        z-index: var(--z-popup);
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: flex-start;
        margin: 0;
        padding: 88px 24px 24px;
        box-sizing: border-box;
        background: rgba(var(--scrim-rgb), calc(0.62 * var(--scrim-mul)));
        animation: scrim-in var(--dur-fast) var(--ease-out);
    }

    body.deck-sheet-open .deck-area .discard-info {
        width: min(960px, 100%);
        max-height: calc(100vh - 112px);
        box-sizing: border-box;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin: 0;
        padding: 14px;
        display: flex;
        flex-direction: column;
        gap: 12px;
        border-radius: 16px;
        border: 1px solid rgba(204, 51, 80, 0.28);
        background: var(--surface);
        box-shadow: 0 24px 60px rgba(var(--shadow-rgb), 0.5);
        animation: deck-dialog-in var(--dur-base) var(--ease-back);
    }

    @keyframes deck-dialog-in {
        from { transform: translateY(-10px) scale(0.98); opacity: 0; }
        to   { transform: none; opacity: 1; }
    }

    /* Inside the dialog the stats row is a heading, not a panel of its own. */
    body.deck-sheet-open .deck-stats-container {
        padding: 6px 10px;
        gap: 2rem;
        background: none;
        border: 0;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }

    body.deck-sheet-open .stat-label {
        font-size: 1rem;
    }

    body.deck-sheet-open .stat-value {
        font-size: 1.2rem;
    }

    body.deck-sheet-open .remaining-pile {
        min-height: 0;
        padding: 0;
        gap: 10px;
        background: none;
    }

    /* ---- the card table: opponents in a row up top, your hand big below ----

       Before this the board was one equal panel per player in a grid: with six
       players the bottom half of the screen was empty, with two the panels sat
       in the far corners. Now the other players are compact panels across the
       top and your own hand is the one big panel, sat down by the HIT / STAND
       bar. It is the same shape the phone layout has, with the rail showing
       the whole hand instead of pips because there is room for it. */

    /* Drawn for a 1600x900 window. On anything bigger client.js sets a
       `zoom` on this element so the whole table scales up with the screen
       rather than sitting small in the middle of it - see fitBoardToScreen. */
    .game-board {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        gap: 12px;
        /* The HIT / STAND bar is fixed over the bottom 88px of the window;
           the container's own 16px covers the rest. */
        padding-bottom: 72px;
        box-sizing: border-box;
    }

    /* Only a spectator uses the equal board; for everyone else it is empty. */
    .players-container:empty {
        display: none;
    }

    /* Wraps so a tablet with five opponents gets two short rows rather than
       five panels too narrow for their seven slots. */
    .opponent-rail {
        display: flex;   /* undoes the desktop hide above the phone block */
        flex: 0 0 auto;
        flex-wrap: wrap;
        justify-content: center;
        align-items: stretch;
        gap: 12px;
        padding: 4px;
        overflow: visible;
    }

    .opponent-rail:empty,
    .my-hand:empty {
        display: none;
    }

    /* The hand keeps to the bottom of whatever room the rail leaves, but the
       auto margin gives way when the panel is taller than the room - so on a
       short window the panel scrolls rather than losing its top. */
    .my-hand {
        display: flex;
        flex-direction: column;
        align-items: center;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        padding: 4px;
        /* Safety net only. The panel is built not to outgrow the room (see
           .my-hand .player); on a window shorter than any rule here plans
           for it still wheel-scrolls, without a bar down the whole board. */
        scrollbar-width: none;
    }

    .my-hand::-webkit-scrollbar {
        display: none;
    }

    /* 60px is what fits two rows of under a five-seat rail in a 900px-tall
       window. Bigger windows do not get bigger cards here: client.js zooms
       the whole board to the window instead, so everything grows together. */
    .my-hand {
        --hand-card: 60px;
    }

    /* The hand is sized to fit the room under the rail with a few pixels
       to spare, so nothing in it may grow a row: the name line is one line
       that never wraps, and the "draw N more" strip sits on that line in a
       second column instead of under the cards. */
    .my-hand .player {
        /* The base rule's flex: 1 would grow the panel to fill the column on
           a tall screen - a hand with 300px of nothing under the cards. */
        flex: 0 0 auto;
        width: min(max(640px, calc(var(--hand-card) * 7 + 140px)), 100%);
        min-width: 0;
        max-width: none;
        margin: auto 0 0;
        padding: 14px 16px;
        box-sizing: border-box;
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 10px;
    }

    .my-hand .player-header { grid-column: 1; }
    .my-hand .draw-three-slot { grid-column: 2; grid-row: 1; align-self: center; }
    .my-hand .scores,
    .my-hand .cards-section { grid-column: 1 / -1; }

    .my-hand .draw-three-slot:empty {
        display: none;
    }

    .my-hand .draw-three-indicator {
        margin: 0;
        padding: 3px 10px;
        font-size: 0.72rem;
        letter-spacing: 0.06em;
        white-space: nowrap;
    }

    /* Trimmed so that the whole hand - two rows of 60px cards included - fits
       under a five-seat rail in a 900px-tall window without scrolling. */
    .my-hand .scores {
        padding: 6px;
        gap: 8px;
    }

    .my-hand .score-box {
        padding: 6px 8px;
    }

    /* Cairo Play's normal line box is nearly twice its cap height; at this
       size that was 54px of box for 29px of digits. */
    .my-hand .score-value {
        margin-top: 2px;
        line-height: 1.1;
    }

    .my-hand .cards-label {
        padding: 5px;
        margin-bottom: 6px;
        line-height: 1.2;
    }

    /* Name on the left, state on the right, one line - the same head the
       compact panels have, so the two read as one family. The boxed status
       strip it replaces cost 60px the cards below wanted. */
    .my-hand .player-header {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        min-width: 0;
    }

    .my-hand .player-header h3 {
        margin: 0;
        min-width: 0;
        flex: 0 1 auto;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .my-hand .player-status {
        margin: 0;
        padding: 0;
        gap: 6px;
        background: none;
        border: 0;
        flex: 0 0 auto;
        flex-wrap: nowrap;
        white-space: nowrap;
        justify-content: flex-end;
    }

    .my-hand .status-icon {
        width: auto;
        height: auto;
        font-size: 1.1rem;
    }

    .my-hand .busted-card,
    .my-hand .second-chance-indicator,
    .my-hand .away-indicator {
        margin: 0;
        padding: 2px 8px;
        font-size: 0.72rem;
    }

    /* Cards at a fixed 60px, not one seventh of the panel: at 640px wide a
       1fr track made them 77px, and the two rows together would not fit the
       height a 900px window leaves under the rail. */
    .my-hand .card-grid {
        grid-template-columns: repeat(7, var(--hand-card));
        justify-content: center;
    }

    .my-hand .card-grid.special {
        grid-template-columns: repeat(auto-fit, var(--hand-card));
    }

    .my-hand .card,
    .my-hand .empty-slot {
        width: var(--hand-card);
        height: auto;
        aspect-ratio: 5 / 7;
        min-width: 0;
        font-size: calc(var(--hand-card) * 0.42);
    }

    .my-hand .card.special {
        font-size: calc(var(--hand-card) * 0.3);
    }

    /* ---- one compact panel per opponent ---- */

    .opponent-rail .player {
        /* 200px holds the name, both scores and seven 24px slots. */
        flex: 1 1 200px;
        width: auto;
        min-width: 0;
        max-width: 300px;
        margin: 0;
        padding: 10px 12px;
        gap: 8px;
        border-radius: 10px;
    }

    /* The lift is for a panel you are about to read closely; six of them
       bobbing in a row is noise. */
    .opponent-rail .player:hover {
        transform: none;
    }

    .opponent-rail .player.busted {
        opacity: 0.55;
    }

    /* Name on the left, state on the right, one line. It must stay one
       line: a seat that grows a row takes that row from the hand below. */
    .opponent-rail .player-header {
        display: flex;
        flex-wrap: nowrap;
        align-items: baseline;
        justify-content: space-between;
        gap: 8px;
        min-width: 0;
    }

    .opponent-rail .player-header h3 {
        margin: 0;
        min-width: 0;
        font-size: 0.9rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .opponent-rail .player-status {
        margin: 0;
        padding: 0;
        gap: 4px;
        background: none;
        border: 0;
        flex: 0 0 auto;
        flex-wrap: nowrap;
        white-space: nowrap;
        justify-content: flex-end;
    }

    /* Both say what the seat already shows - the card that busted them is in
       their row and the shield is in their special row - and at this width
       either one would wrap the head onto a second line. */
    .opponent-rail .busted-card,
    .opponent-rail .second-chance-indicator {
        display: none;
    }

    .opponent-rail .status-icon {
        width: auto;
        height: auto;
        font-size: 0.8rem;
    }

    .opponent-rail .status-text {
        font-size: 0.66rem;
        letter-spacing: 0.1em;
    }

    .opponent-rail .away-indicator {
        margin: 0;
        padding: 1px 6px;
        font-size: 0.62rem;
    }

    .opponent-rail .scores {
        padding: 0;
        gap: 6px;
        background: none;
        border: 0;
    }

    .opponent-rail .score-box {
        padding: 5px 4px;
        border-radius: 6px;
    }

    .opponent-rail .score-label {
        font-size: 0.6rem;
        letter-spacing: 0.1em;
    }

    .opponent-rail .score-value {
        margin-top: 2px;
        font-size: 1.05rem;
        line-height: 1.1;
    }

    /* The slots say "regular" and "special" by themselves. */
    .opponent-rail .cards-label {
        display: none;
    }

    .opponent-rail .cards-section {
        gap: 8px;
    }

    .opponent-rail .card-grid {
        --cell-gap: 4px;
        grid-template-columns: repeat(7, 24px);
        justify-content: center;
        padding: 0;
        background: none;
        border: 0;
        border-radius: 0;
    }

    /* A line between the two rows, centred like the row above it. */
    .opponent-rail .card-grid.special {
        grid-template-columns: repeat(auto-fit, 24px);
        padding-top: 8px;
        border-top: 1px solid rgba(var(--ink-rgb), 0.12);
    }

    /* The base rules pin a card at 45x63 with more specificity than the grid
       track can override, so the size is restated here. */
    .opponent-rail .card,
    .opponent-rail .empty-slot {
        width: 24px;
        height: auto;
        aspect-ratio: 5 / 7;
        min-width: 0;
        border-radius: 4px;
        border-width: 1px;
        font-size: 0.8rem;
    }

    .opponent-rail .card.special {
        font-size: 0.66rem;
    }

    .opponent-rail .card.special::before {
        font-size: 0.8rem;
    }

    .opponent-rail .draw-three-indicator {
        font-size: 0.62rem;
        padding: 2px 6px;
    }

    /* A 1024px tablet or a narrow window: five 200px seats do not fit in one
       row, so the seats and their slots go one size down and five fit. */
    @media (max-width: 1280px) {
        .opponent-rail {
            gap: 10px;
        }

        .opponent-rail .player {
            flex-basis: 180px;
            padding: 8px 10px;
        }

        .opponent-rail .card-grid {
            --cell-gap: 3px;
            grid-template-columns: repeat(7, 20px);
        }

        .opponent-rail .card-grid.special {
            grid-template-columns: repeat(auto-fit, 20px);
        }

        .opponent-rail .card,
        .opponent-rail .empty-slot {
            width: 20px;
            font-size: 0.7rem;
        }
    }

    /* A short window (a 768px-tall tablet, a laptop with the bar showing):
       the hand loses its two captions and a size on the cards so it still
       fits under the rail without scrolling. */
    @media (max-height: 820px) {
        .my-hand {
            --hand-card: 50px;
        }

        .my-hand .cards-label {
            display: none;
        }
    }
}

/* ---------- optical centring ----------

   A line of text is taller than its letters: the box leaves room for descenders
   (g, j, y) and accents that capitals never use. Centre that box and the capitals
   land a pixel or two low - worst with Cairo Play, whose box is almost twice its
   cap height, and next to an emoji, whose fallback font has a taller box again.
   Trim the box to the capitals so the letters get centred, not the empty room
   around them. Browsers without text-box-trim ignore it and look as they did. */
.game-button,
.status-icon,
.status-text,
.last-action-icon,
.deck-button-count,
.deck-button-label {
    text-box: trim-both cap alphabetic;
}

/* Not .last-action-text: it clips to one line with overflow: hidden, and a box
   trimmed to the capitals would cut off descenders and the card chips in it.
   It is a mixed-case sentence anyway, which the plain line box centres fine. */

/* Emoji sit low. Every colour-emoji font (Segoe, Apple, Noto) draws its glyphs
   a touch below the baseline, so next to capitals an emoji lands about 0.07em
   under the middle of the letters - and trimming to the caps above cannot see
   that, because the trim reads the text font, not the emoji font. Lift every
   emoji that is its own element by that much; in em so it scales with the
   font. Inline emoji in prose (the how-to-play text) are left alone. */
.emoji,
.status-icon,
.history-icon,
.last-action-icon,
.settings-icon,
.bot-mark,
.view-game-button .icon {
    position: relative;
    top: -0.07em;
}

/* Same cap trim as .game-button, so the lobby buttons centre their label too. */
.lobby-button {
    text-box: trim-both cap alphabetic;
}
