.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #c02d76;
}

.app { max-width: 900px; margin: 0 auto; padding: 1rem; }
.error { color: #ff8a80; }
.message { color: #86e0a3; }
.board-container { margin: 1rem 0; }

/* Canvas board (drag-and-drop). Wrapper keeps the legacy .board class for E2E, but the
   scene is drawn on <canvas>, so the old grid rules are neutralised here. */
.board.board-stage { display: block; background: none; width: auto; gap: 0; margin: 1rem 0; }
.board-canvas {
    display: block;
    width: 100%;
    max-width: 680px;
    aspect-ratio: 1 / 1;
    border-radius: 0;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    touch-action: none;
    user-select: none;
}
.board-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; max-width: 680px; }

/* Wait: a permanent part of the board (not an action chip). Shows the acting player's occupied
   count vs the opponent's; bold + clickable only when a pass is actually allowed. */
.board-topbar {
    display: flex; align-items: center; justify-content: center; gap: 0.55rem; box-sizing: border-box;
    width: 100%; max-width: 680px; min-height: 52px;
    padding: 0 1.15rem; margin-bottom: 0.4rem;
    background: url('/img/waitbar.png') center / 100% 100% no-repeat;
    color: var(--ink-dim); user-select: none; font-variant-numeric: tabular-nums; cursor: default;
}
/* #77: the numeric run ("First 0 ≤ 0") must NEVER wrap — a dangling digit on line two read as a
   bug (owner report e7512ff3, RU @360px). The word label may wrap as whole words; narrow
   viewports shrink the bar's type instead. */
.board-topbar .wait-counts { font-weight: 700; color: var(--ink); white-space: nowrap; }
.board-topbar .wait-op { padding: 0 0.15rem; }
@media (max-width: 480px) {
    .board-topbar { font-size: .85rem; gap: .4rem; padding: 0 .7rem; }
    .board-topbar .wait-label { font-size: .85rem; }
    .board-topbar.can .wait-label { font-size: .9rem; letter-spacing: .8px; }
}
.board-topbar .wait-icon { width: 20px; height: 20px; }
.board-topbar .wait-win { font-weight: 800; font-size: 1.1rem; letter-spacing: 0.5px; }
.board-topbar.win-blue .wait-win { color: #6bb0ff; text-shadow: 0 0 10px rgba(74,144,226,.6); }
.board-topbar.win-yellow .wait-win { color: #ffd84a; text-shadow: 0 0 10px rgba(246,214,63,.6); }
.board-topbar.can { background-image: url('/img/waitbar-can.png'); cursor: pointer; color: #fff; }
.board-topbar.can .wait-label { font-weight: 800; color: #fff; letter-spacing: 1.5px; font-size: 1.05rem; }
.board-topbar.can:hover { filter: brightness(1.06); }
.board-topbar:focus-visible { outline: 2px solid #1565c0; outline-offset: 2px; }

/* Clickable areas replacing native buttons/selects */
.chip {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0.5rem 1rem; border-radius: 999px; cursor: pointer; user-select: none;
    background: #eceff1; color: #263238; font-weight: 500; line-height: 1;
    border: 1px solid #cfd8dc; transition: background 0.12s, transform 0.06s;
}
/* NOTE: no :hover background rules here — legacy light-theme hover colors (#e0e5e8 etc.) used to
   lurk under the dark skin's image swap and surfaced as the infamous "stuck white button" on touch
   the moment the swap was removed. Hover styling lives ONLY in the dark-skin section below. */
.chip:active { transform: translateY(1px); }
.chip:focus-visible { outline: 2px solid #1565c0; outline-offset: 2px; }
.chip.disabled { opacity: 0.4; pointer-events: none; }
.chip-primary { background: #2e7d32; color: #fff; border-color: #2e7d32; }
.chip-wait { background: #fff3e0; border-color: #ffcc80; color: #e65100; }

.tile-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.5rem 0 1rem; }
.tile {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 4rem; padding: 0.75rem 1rem; border-radius: 10px; cursor: pointer; user-select: none;
    background: #eceff1; border: 2px solid #cfd8dc; font-weight: 600; color: #37474f;
    transition: background 0.12s, border-color 0.12s;
}
.tile.selected { background: #e8f5e9; border-color: #2e7d32; color: #1b5e20; }
.tile:focus-visible { outline: 2px solid #1565c0; outline-offset: 2px; }

.setup { max-width: 680px; }
.setup-label { font-weight: 600; color: #455a64; }
.game-page .lede { color: #546e7a; max-width: 680px; }

.game-page .moves { margin-top: 1rem; color: #607d8b; }
/* Reserve a stable line so the turn text can never change the block height and shift the
   board under the player's finger (#50 — "don't move controls under the finger"). */
.game-page .turn { color: var(--gold); font-weight: 600; min-height: 1.4em; }
.game-page .turn.over { color: #ff8a80; }

/* End-of-game result summary */
.result-summary { margin: 0.25rem 0 0.5rem; }
.result-summary .result-heading { font-weight: 700; font-size: 1.15rem; margin: 0 0 0.15rem; }
.result-summary .result-heading.res-won { color: #6ed88a; }
.result-summary .result-heading.res-lost { color: #ff8a8a; }
.result-summary .result-heading.res-draw { color: var(--ink-dim); }
.result-summary .result-sides { color: var(--ink-dim); margin: 0 0 0.15rem; }
.result-summary .result-rating { margin: 0; color: var(--ink-dim); }
/* Rematch (#90): offer/accept row under the result summary; the note text stays dim. */
.result-summary .rematch-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.5rem; }
.result-summary .rematch-note { color: var(--ink-dim); }
.result-summary .rematch-waiting { animation: ctaPulse 1.6s ease-in-out infinite; }

/* ── Game clock (#3) ──────────────────────────────────────────────────────────── */
.clocks { display: flex; gap: 0.6rem; justify-content: center; margin: 0.4rem 0 0.6rem; max-width: 460px; }
.clocks .clock {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 0.1rem;
    padding: 0.4rem 0.5rem; border-radius: 12px; border: 1px solid rgba(201,162,75,.18);
    background: rgba(18,25,37,.6); transition: border-color .15s, box-shadow .15s, opacity .15s;
}
.clocks .clock.blue { border-top: 3px solid #4a90e2; }
.clocks .clock.yellow { border-top: 3px solid var(--gold); }
.clocks .clock .clock-side { font-size: 0.72rem; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .5px; }
.clocks .clock .clock-time { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ink); }
.clocks .clock.running { border-color: var(--gold); box-shadow: 0 0 0 1px rgba(201,162,75,.35), 0 4px 14px rgba(0,0,0,.35); }
.clocks .clock.running .clock-time { color: #fff; }
.clocks .clock.mine .clock-side { color: var(--gold); }
.clocks.paused .clock { opacity: .55; }

.pause-bar { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; justify-content: center; margin: 0 0 0.7rem; max-width: 460px; }
.pause-bar .pause-badge { font-weight: 800; color: var(--gold); text-transform: uppercase; letter-spacing: .5px; }
.pause-bar .pause-msg { color: var(--ink-dim); }
.review-row { align-items: center; }
/* min-width kept small: 6rem forced the counter wide and overflowed the landscape side column
   (higher specificity than the sizing rules further down — keep these two in sync). */
.review-row .review-label { color: var(--ink-dim); font-variant-numeric: tabular-nums; min-width: 34px; text-align: center; }
.review-row .chip.disabled { opacity: .4; pointer-events: none; }
.game-chat { margin-top: 1.5rem; border: 1px solid #ccc; border-radius: 4px; padding: 0.75rem; max-width: 400px; }
.game-chat h2 { margin: 0 0 0.5rem 0; font-size: 1rem; }
.chat-messages { max-height: 200px; overflow-y: auto; margin-bottom: 0.5rem; }
.chat-line { margin-bottom: 0.25rem; word-break: break-word; }
.chat-send { display: flex; gap: 0.5rem; }
.chat-send input { flex: 1; padding: 0.35rem; }
.chat-send button { padding: 0.35rem 0.75rem; }

/* ===================== Premium modern theme (Phase 2 shell) ===================== */
:root {
    --ink: #f2efe6;
    --ink-dim: #9fb0c3;
    --gold: #c9a24b;
    --sheet: #f6f7f9;
    --sheet-ink: #1f2733;
}

html, body {
    min-height: 100%;
    margin: 0;
    font-family: "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
    color: var(--ink);
    background: #141822 url('/img/bg-app.jpg') center top / cover fixed no-repeat;
}

.app { max-width: 1040px; margin: 0 auto; padding: 1rem 1.25rem 2rem; }

/* --- top nav as a graphical bar --- */
.topnav {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    padding: 0.4rem 0 1rem; margin-bottom: 1rem; border: none;
}
.topnav .brand { padding: 0; display: inline-flex; align-items: center; gap: 0.55rem; text-decoration: none; }
.topnav .brand .brand-mark { height: 42px; width: 42px; object-fit: contain; display: block; border-radius: 9px; filter: drop-shadow(0 2px 6px rgba(0,0,0,.5)); }
.topnav .brand .brand-word { font-size: 1.5rem; font-weight: 800; letter-spacing: 2.5px; color: #eef2f8; }
.nav-links { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.spacer { flex: 1 1 auto; }

.navpill {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.55rem 0.95rem; min-height: 40px; color: var(--ink); text-decoration: none;
    background: url('/img/pill.png') center / 100% 100% no-repeat;
    font-weight: 600; font-size: 0.92rem; white-space: nowrap;
    transition: transform 0.08s;
}
.navpill:hover { filter: brightness(1.14); }
.navpill:active { transform: translateY(1px); }
.navpill.primary { background-image: url('/img/pill-primary.png'); }
.navpill img { width: 18px; height: 18px; }

.badge { display: inline-flex; align-items: center; padding: 0.35rem 0.7rem; border-radius: 999px; font-size: 0.78rem; font-weight: 700; }
.badge.guest { background: rgba(255,255,255,.12); color: var(--ink); }
.badge.premium { background: linear-gradient(#e5c57a, #c9a24b); color: #3a2d06; }
.userid { color: var(--ink-dim); font-size: 0.78rem; max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userbar { display: inline-flex; align-items: center; gap: .5rem; }
.userbar-id { display: inline-flex; align-items: center; gap: .4rem; text-decoration: none; color: var(--ink); }
.userbar-icon { width: 24px; height: 24px; border-radius: 999px; }
/* #75: the userbar can carry the #61 initials disc — same look, bar-sized. */
.userbar-icon.initials-avatar { width: 24px; height: 24px; font-size: .68rem; }
/* #82: rename a stored local game right on its replay header. */
.local-rename-btn { margin-inline-start: .4rem; }
.local-rename-row { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.local-rename-input {
    flex: 1 1 160px; min-width: 120px; max-width: 320px; padding: .35rem .6rem;
    border-radius: 8px; border: 1px solid rgba(255,255,255,.25);
    background: rgba(255,255,255,.06); color: var(--ink);
}
.userbar-name { font-weight: 700; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userbar-signout { display: inline-flex; align-items: center; padding: .3rem; border-radius: 8px; }
.userbar-signout img { width: 20px; height: 20px; }
.userbar-signout:hover { background: rgba(255,255,255,.08); }

/* --- everything on the dark shell now (Phase 2.2) --- */
main { display: block; color: var(--ink); }
main h1, main h2, main h3 { color: var(--ink); }
main h1:focus { outline: none; }   /* programmatic focus ring on heading */
main a { color: #86b7ff; }
main a:hover { color: #a9ccff; }

/* ad slot styled for the dark shell */
.ad-slot { display: flex; align-items: center; gap: 0.5rem; margin-top: 1rem; padding: 0.5rem 0.9rem;
    background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08); border-radius: 10px;
    font-size: 0.82rem; color: var(--ink-dim); max-width: max-content; }
.ad-slot .ad-label { font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; opacity: 0.7; }
.ad-slot a { color: var(--gold); text-decoration: none; }
.ad-slot a:hover { text-decoration: underline; }

/* --- Home menu tiles (text on image plates) --- */
.home-hero { padding-top: 0.5rem; }
.menu { display: flex; flex-direction: column; gap: 0.9rem; max-width: 460px; margin: 0.5rem 0 1.25rem; }
.menu-tile {
    display: flex; align-items: center; gap: 1rem; text-decoration: none; color: var(--ink);
    padding: 0.9rem 1.2rem; min-height: 84px;
    background: url('/img/tile.png') center / 100% 100% no-repeat;
    transition: transform 0.1s;
}
.menu-tile:hover { filter: brightness(1.1); transform: translateY(-2px); }
.menu-tile.primary { background-image: url('/img/tile-primary.png'); }
.menu-tile.primary:hover { background-image: url('/img/tile-primary.png'); }
.menu-icon { width: 40px; height: 40px; flex: 0 0 auto; filter: drop-shadow(0 2px 3px rgba(0,0,0,.4)); }
.menu-tile.soon { opacity: .6; cursor: default; }
.menu-tile.soon:hover { transform: none; filter: none; }
/* min-width:0 — a flex item's default min-width:auto refuses to shrink below the text's
   min-content, which blew the ja puzzles tile past 390px viewports (gate 20260731-135141). */
.menu-text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.menu-title { font-size: 1.2rem; font-weight: 800; letter-spacing: 0.3px; overflow-wrap: anywhere; }
.menu-sub { color: var(--ink-dim); font-size: 0.9rem; overflow-wrap: anywhere; }
.home-note { color: var(--ink-dim); max-width: 620px; }
.home-note a { color: var(--gold); }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ===================== Phase 2.2: dark form / panel / card system ===================== */

/* glass surfaces for forms and content groups */
.auth-form, .form, .panel {
    max-width: 460px; margin: 0.5rem 0 1rem;
    padding: 1.5rem 1.6rem; border-radius: 16px;
    background: linear-gradient(180deg, rgba(52,64,82,.55), rgba(28,37,51,.62));
    border: 1px solid rgba(201,162,75,.30);
    box-shadow: 0 12px 30px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.06);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.panel-wide { max-width: 880px; }

/* fields + inputs */
.field { margin-bottom: 0.9rem; }
.field label { display: block; margin-bottom: 0.35rem; color: var(--ink-dim); font-weight: 600; font-size: 0.88rem; }
input, select, textarea {
    width: 100%; box-sizing: border-box; padding: 0.6rem 0.7rem;
    background: #1b2430; color: var(--ink); font-size: 0.95rem;
    border: 1px solid rgba(255,255,255,.15); border-radius: 9px;
}
input::placeholder { color: #6b7a8c; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 2px rgba(201,162,75,.25); }
input[type=checkbox] { width: auto; }

/* buttons -> image plates (text on image) */
main button, .btn, .provider,
.auth-form button, .form button {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
    width: auto; padding: 0.6rem 1.2rem; min-height: 44px; margin: 0.25rem 0;
    border: none; cursor: pointer; color: var(--ink); font-weight: 700; font-size: 0.95rem;
    background: url('/img/pill.png') center / 100% 100% no-repeat; transition: transform 0.08s, filter 0.1s;
}
/* Hover = a subtle brightness lift, NEVER a different skin: an image swap that sticks after a touch
   tap reads as a third button state (repeated user reports) — brightness cannot be mistaken for one. */
main button:hover, .btn:hover, .provider:hover { filter: brightness(1.13); }
main button:active { transform: translateY(1px); }
main button:disabled { filter: grayscale(.4) brightness(.75); cursor: default; }
main button[type=submit], .btn-primary { background-image: url('/img/pill-primary.png'); }
main button[type=submit]:hover { filter: brightness(1.08); }

/* chips + pickers -> plates (override the earlier light rules) */
.chip { background: url('/img/pill.png') center / 100% 100% no-repeat; color: var(--ink); border: none; }
.chip:hover { filter: brightness(1.13); }
.chip-primary { background-image: url('/img/pill-primary.png'); }
.chip-wait { background-image: url('/img/pill.png'); color: #ffcf8f; box-shadow: inset 0 0 0 2px rgba(230,120,20,.55); }
.tile { background: url('/img/pill.png') center / 100% 100% no-repeat; color: var(--ink); border: none; position: relative; }
.tile:hover { filter: brightness(1.13); }
/* Full shorthand on purpose: the legacy light rule `.tile.selected { background: #e8f5e9 }`
   (higher specificity than the `.tile` plate above) otherwise resets size/position/repeat,
   drawing the pill unstretched + repeating over a pale backdrop (clipped-label tiles). */
.tile.selected { background: url('/img/pill-primary.png') center / 100% 100% no-repeat; color: var(--ink); }
.tile.locked { opacity: 0.62; padding-right: 2.05rem; }
.tile.locked::after { content: "🔒"; position: absolute; top: 50%; right: 0.95rem; transform: translateY(-50%); font-size: 0.72rem; }
.tile.locked.selected { opacity: 0.62; }
.lock-note { color: #ffcf8f; font-size: 0.88rem; margin: 0.35rem 0 0.5rem; }

/* provider (external sign-in) buttons keep a brand tint */
.external-signin { margin-top: 1rem; }
.divider { color: var(--ink-dim); font-size: 0.85rem; margin: 0.5rem 0; }
.provider.google { color: #ffe08a; }
.provider.apple { color: #e6ecf3; }
/* App-styled "Continue with Google" (incident #35 replaced Google's generic button): the app pill
   plate with the brand G mark, so it matches every other button instead of Google's white box. */
.provider-ico { width: 18px; height: 18px; flex: 0 0 auto; }
.provider.google .provider-ico { background: #fff; border-radius: 50%; padding: 2px; box-sizing: border-box; }
.more { color: var(--ink-dim); font-size: 0.85rem; margin-left: 0.5rem; }

/* card lists (replace Games / Friends tables) */
.card-list { display: flex; flex-direction: column; gap: 0.6rem; max-width: 880px; margin: 0.6rem 0 1rem; }
.row-card {
    display: flex; align-items: center; gap: 0.9rem; text-decoration: none; color: var(--ink);
    padding: 0.75rem 1rem; border-radius: 12px;
    background: linear-gradient(180deg, rgba(52,64,82,.5), rgba(28,37,51,.55));
    border: 1px solid rgba(255,255,255,.10); transition: border-color 0.12s, transform 0.08s;
}
a.row-card:hover { border-color: rgba(201,162,75,.55); transform: translateY(-1px); }
.row-card .rc-icon { width: 34px; height: 34px; flex: 0 0 auto; opacity: 0.9; }
.row-card .rc-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.row-card .rc-title { font-weight: 700; }
.row-card .rc-sub { color: var(--ink-dim); font-size: 0.85rem; }
.row-card .rc-spacer { flex: 1 1 auto; }
.row-card .rc-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.status-pill { padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.78rem; font-weight: 700;
    background: rgba(255,255,255,.10); color: var(--ink-dim); }
.status-pill.live { background: rgba(76,175,80,.22); color: #a5e0ae; }
.status-pill.done { background: rgba(255,255,255,.08); color: var(--ink-dim); }
.empty-note { color: var(--ink-dim); }

/* pickers (Queue / setup) */
.picker-label { display: block; font-weight: 600; color: var(--ink-dim); margin: 0.75rem 0 0.35rem; }
.toggle-row { display: flex; align-items: center; gap: 0.6rem; margin: 0.75rem 0; color: var(--ink-dim); }
.toggle-row input { width: auto; }
.add-friend-row { display: flex; gap: 0.5rem; align-items: center; }
.add-friend-row input { flex: 1; }
main button.sm, .btn.sm { min-height: 34px; padding: 0.32rem 0.85rem; font-size: 0.85rem; }

/* content page tweaks on dark */
.scaffold-note, .hint { color: var(--ink-dim); font-size: 0.9rem; }
.game-page .lede { color: var(--ink-dim); }
.setup-label, .picker-label { color: var(--ink-dim); }
.game-chat { border: 1px solid rgba(255,255,255,.12); border-radius: 12px;
    background: linear-gradient(180deg, rgba(52,64,82,.4), rgba(28,37,51,.5)); }
.game-chat h2 { color: var(--ink); }
.chat-line { color: var(--ink); }
code { color: #ffcf8f; background: rgba(255,255,255,.06); padding: 0.05rem 0.3rem; border-radius: 4px; }

/* Resign chip */
.chip-danger { background: #b71c1c; background-image: none; color: #fff; box-shadow: none; border: none; }
.chip-danger:hover { filter: brightness(1.15); }

/* Full-screen blocking notice (ToastOverlay): dark backdrop, centred card, captures all clicks */
.toast-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    animation: toast-fade 0.15s ease-out;
}
.toast-card {
    background: #1f2937;
    color: #fff;
    padding: 1.25rem 1.75rem;
    border-radius: 12px;
    font-size: 1.15rem;
    line-height: 1.4;
    max-width: 90vw;
    text-align: center;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.55);
}
@keyframes toast-fade { from { opacity: 0; } to { opacity: 1; } }

/* Invite QR code — white quiet-zone so it scans against the dark theme */
.invite-qr-wrap { margin-top: 0.4rem; }
.invite-qr { width: 180px; height: 180px; image-rendering: pixelated; background: #fff; padding: 10px; border-radius: 10px; }
.invite-qr-id { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.5rem; max-width: 200px; }
.invite-qr-id code { font-size: 0.72rem; line-height: 1.25; word-break: break-all; opacity: 0.85; }
/* Friend code (#49): your shareable short numeric id, shown on the profile. */
.friend-code-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; flex-wrap: wrap; }
.friend-code-row .fc-label { color: var(--ink-dim); }
.friend-code-row .fc-code { display: inline-flex; align-items: center; gap: 0.4rem; }
.friend-code-row .fc-value { font-size: 1.05rem; font-weight: 700; letter-spacing: 0.06em; }
/* #61: default avatar = an initials disc when no icon is set. Same box as .icon-preview. */
.initials-avatar { display: inline-flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; border-radius: 50%; flex: 0 0 auto; font-weight: 700; font-size: 1.05rem;
    color: #eaf1ff; background: radial-gradient(circle at 35% 30%, #4a6da8, #24406e 70%); }
/* #62: account deletion — a clearly-dangerous, single-purpose button. */
.delete-account-btn { color: #ff9a9a; border-color: rgba(255, 110, 110, 0.45); }
/* #63: profile icon-button links (My games / Friends). */
.profile-links { display: flex; gap: 0.6rem; margin-top: 0.7rem; flex-wrap: wrap; }
.profile-links .icon-link { display: inline-flex; align-items: center; gap: 0.45rem; text-decoration: none; }
.profile-links .icon-link img { width: 20px; height: 20px; }
/* #64: the game share button sits at the END of the status line (RTL-safe via margin-inline-start). */
.game-status { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.game-status .share-inline { margin-inline-start: auto; }
/* Play-a-friend list (#51): pick a friend to start a game with. */
.friend-play-list { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.6rem; }
.friend-play-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.45rem 0.65rem; background: rgba(255,255,255,0.03); border: 1px solid rgba(201,162,75,0.22); border-radius: 8px; }
.friend-play-row .rc-title { font-weight: 600; }
/* ── Language switcher (globe menu in the top nav) ────────────────────────── */
.lang-switch { position: relative; display: inline-flex; }
.lang-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0;
    background: transparent; border: 1px solid rgba(255,255,255,0.15);
    border-radius: 10px; color: #cfd6e4; cursor: pointer;
}
.lang-btn:hover { background: rgba(255,255,255,0.07); color: #eef2f8; }
.lang-menu {
    position: absolute; top: calc(100% + 6px); inset-inline-start: 0; max-width: calc(100vw - 1.25rem);
    margin: 0; padding: 6px; list-style: none; min-width: 168px;
    background: #141b28; border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px; box-shadow: 0 12px 34px rgba(0,0,0,0.45); z-index: 60;
}
.lang-item {
    display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
    width: 100%; padding: 8px 11px; text-align: start;
    background: transparent; border: 0; border-radius: 8px; color: #e6ebf3; cursor: pointer;
}
.lang-item:hover { background: rgba(255,255,255,0.07); }
.lang-item.active { background: rgba(56,161,105,0.22); color: #fff; }
.lang-native { font-size: 0.95rem; line-height: 1.1; }
.lang-en { font-size: 0.72rem; opacity: 0.55; }

/* ── RTL: the switcher flips <html dir>; keep icon/text spacing symmetric ──── */
[dir="rtl"] .navpill img,
[dir="rtl"] .menu-tile .menu-icon { transform: scaleX(1); }
[dir="rtl"] .home-note,
[dir="rtl"] .auth-form { text-align: right; }
/* Language-specific brand wordmark (image swapped by LocalizationState.Img). */
.brand-word-img { height: 1.7rem; width: auto; display: block; }
/* Left-to-right fields (email, password, URLs, user IDs) must stay LTR even in an RTL (Hebrew) UI. */
[dir="rtl"] input[type="email"],
[dir="rtl"] input[type="password"],
[dir="rtl"] input[type="url"],
[dir="rtl"] input.ltr {
    direction: ltr;
    text-align: left;
}
/* Home icon lives inside the brand link (game icon | wordmark | home icon); whole brand is clickable → home. */
.brand-home { height: 1.5rem; width: auto; display: block; opacity: 0.8; margin-inline-start: 0.15rem; }
.topnav .brand:hover .brand-home { opacity: 1; }
/* 6-digit invite code shown on the invite screen (always LTR, easy to read/copy). */
.invite-code {
    font-size: 2rem; font-weight: 800; letter-spacing: 0.32em;
    text-align: center; padding: 0.5rem 0.25rem 0.5rem 0.6rem; color: #eef2f8;
    background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.12);
    border-radius: 10px; direction: ltr; user-select: all;
}
.mode-row { margin-bottom: 0.5rem; }
/* ── Wide, prominent primary action buttons (Start game, Join queue, Create invite, Sign in, …) ── */
.cta {
    display: flex; width: 100%; box-sizing: border-box;
    padding: 0.95rem 1.2rem; font-size: 1.1rem; font-weight: 800;
    margin: 1.15rem 0 0.15rem;
}
.cta-row { display: flex; flex-direction: column; gap: 0.55rem; margin-top: 1.15rem; }
.cta-row .cta { margin: 0; }

/* ── Find tabs: the active tab connects into the panel below it ─────────────────────────────────── */
.tab-strip { display: flex; gap: 0.3rem; padding: 0 0.7rem; margin: 0.5rem 0 0; max-width: 460px; }
.tab {
    flex: 1 1 0; min-width: 0; text-align: center; line-height: 1.15;
    padding: 0.55rem 0.5rem; font-weight: 700; font-size: 0.9rem; cursor: pointer; user-select: none;
    color: var(--ink-dim); background: rgba(18,25,37,.6);
    border: 1px solid rgba(201,162,75,.18); border-bottom: none;
    border-radius: 12px 12px 0 0; position: relative; top: 1px;
}
.tab:hover { color: var(--ink); }
.tab:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.tab.active {
    color: var(--ink); background: rgba(52,64,82,.62);
    border-color: rgba(201,162,75,.30); z-index: 2;
}
.panel-tabbed { margin-top: 0; border-top-left-radius: 3px; }
[dir="rtl"] .tab { border-radius: 12px 12px 0 0; }

/* ============================================================
   Admin console (web-only /admin). Bare AdminLayout, no game chrome.
   ============================================================ */
.admin-root { min-height: 100vh; background: #10141d; color: var(--ink);
    font-size: 0.9rem; }
.admin-muted { color: var(--ink-dim); }
.admin-error { color: #ff8a8a; background: rgba(255,60,60,.10); border: 1px solid rgba(255,60,60,.35);
    padding: .5rem .7rem; border-radius: 8px; margin: .5rem 0; }

/* login */
.admin-login { max-width: 360px; margin: 12vh auto; padding: 1.6rem; text-align: center;
    background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08); border-radius: 14px; }
.admin-login h1 { margin: 0 0 .4rem; }
.admin-login input { margin: .8rem 0; }

/* header + tabs */
.admin-header { position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: 1rem;
    padding: .6rem 1rem; background: #0c0f16; border-bottom: 1px solid rgba(255,255,255,.08); }
.admin-header strong { font-size: 1.05rem; color: var(--gold); }
.admin-spacer { flex: 1; }
.admin-tabs { display: flex; gap: .25rem; flex-wrap: wrap; }
.admin-tab { background: transparent; border: 1px solid transparent; color: var(--ink-dim);
    padding: .4rem .8rem; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: .88rem; }
.admin-tab:hover { color: var(--ink); }
.admin-tab.active { color: var(--ink); background: rgba(255,255,255,.07); border-color: rgba(201,162,75,.35); }

.admin-main { padding: 1.2rem 1rem 4rem; max-width: 1200px; margin: 0 auto; }

/* buttons */
.admin-btn { display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
    padding: .45rem .85rem; min-height: 34px; border-radius: 8px; cursor: pointer; font-weight: 600;
    font-size: .85rem; color: var(--ink); background: #1e2634; border: 1px solid rgba(255,255,255,.15); }
.admin-btn:hover { background: #26303f; }
.admin-btn:disabled { opacity: .5; cursor: default; }
.admin-btn.sm { padding: .25rem .55rem; min-height: 28px; font-size: .8rem; }
.admin-btn.primary { background: #2f7d4f; border-color: #38935d; }
.admin-btn.primary:hover { background: #369059; }
.admin-btn.danger { background: #7d2f2f; border-color: #a13a3a; }
.admin-btn.danger:hover { background: #953636; }
.admin-btn.ghost { background: transparent; }

/* overview cards */
.admin-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: .75rem; margin-bottom: 1.5rem; }
.admin-card { display: flex; flex-direction: column; gap: .2rem; padding: 1rem;
    background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08); border-radius: 12px; }
.admin-card .n { font-size: 1.7rem; font-weight: 800; color: var(--gold); }
.admin-card .l { color: var(--ink-dim); font-size: .8rem; }

/* toolbar */
.admin-toolbar { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-bottom: .8rem; }
.admin-toolbar input, .admin-toolbar select { width: auto; min-width: 180px; }
.admin-check { display: inline-flex; align-items: center; gap: .35rem; color: var(--ink-dim); white-space: nowrap; }
.admin-check input { width: auto; }

/* tables */
/* Wide admin tables scroll INSIDE their own box on narrow viewports (block+overflow-x) — the
   page itself must never overflow horizontally (UX-audit C1; caught live by the admin walk when
   the Feedback tab's Reason column widened the table past a phone viewport). */
.admin-table { width: 100%; border-collapse: collapse; font-size: .85rem; display: block; overflow-x: auto; }
.admin-table thead, .admin-table tbody { display: table; width: 100%; border-collapse: collapse; }
.admin-table th, .admin-table td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid rgba(255,255,255,.07);
    vertical-align: top; }
.admin-table thead th { color: var(--ink-dim); font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .03em; }
.admin-table tbody tr:hover { background: rgba(255,255,255,.03); }
.admin-table.sm th, .admin-table.sm td { padding: .3rem .5rem; }
.admin-sub { color: var(--ink-dim); font-size: .72rem; word-break: break-all; }
.admin-msg { max-width: 380px; white-space: pre-wrap; word-break: break-word; }

/* badges */
.admin-badge { display: inline-block; padding: .12rem .5rem; border-radius: 999px; font-size: .74rem; font-weight: 700;
    background: rgba(255,255,255,.10); color: var(--ink); }
.admin-badge.guest { background: rgba(255,255,255,.12); }
.admin-badge.user { background: rgba(90,140,220,.25); color: #bcd4ff; }
.admin-badge.premium { background: rgba(201,162,75,.28); color: #f0d79a; }
.admin-badge.danger { background: rgba(220,70,70,.28); color: #ffb3b3; }

.admin-pager { display: flex; align-items: center; gap: .8rem; margin-top: .8rem; }

/* modal */
.admin-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.55); display: flex; justify-content: center;
    align-items: flex-start; padding: 4vh 1rem; overflow-y: auto; z-index: 50; }
.admin-modal { width: 100%; max-width: 720px; background: #161b26; border: 1px solid rgba(255,255,255,.12);
    border-radius: 14px; padding: 1.2rem; }
.admin-modal-head { display: flex; align-items: center; justify-content: space-between; }
.admin-modal-head h2 { margin: 0; }
.admin-modal details { margin-top: .6rem; border-top: 1px solid rgba(255,255,255,.08); padding-top: .5rem; }
.admin-modal summary { cursor: pointer; color: var(--ink-dim); font-weight: 600; }
.admin-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .7rem; margin: .9rem 0; }
.admin-grid label { display: flex; flex-direction: column; gap: .25rem; color: var(--ink-dim); font-size: .82rem; }
.admin-grid label.admin-check { flex-direction: row; align-items: center; }
.admin-actions { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin: .4rem 0 .6rem; }
@media (max-width: 680px) { .admin-grid { grid-template-columns: 1fr; } }

/* ── Corner app menu (hamburger → Settings / Report / About) ───────────────── */
.app-menu { position: relative; display: inline-flex; }
.app-menu-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0;
    background: transparent; border: 1px solid rgba(255,255,255,0.15);
    border-radius: 10px; color: #cfd6e4; cursor: pointer;
}
.app-menu-btn:hover { background: rgba(255,255,255,0.07); color: #eef2f8; }
.app-menu-list {
    position: absolute; top: calc(100% + 6px); inset-inline-start: 0; max-width: calc(100vw - 1.25rem);
    margin: 0; padding: 6px; list-style: none; min-width: 190px;
    background: #141b28; border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px; box-shadow: 0 12px 34px rgba(0,0,0,0.45); z-index: 60;
}
.app-menu-item {
    display: flex; align-items: center; gap: 0.6rem;
    width: 100%; padding: 9px 12px; text-align: start; font-size: 0.95rem;
    background: transparent; border: 0; border-radius: 8px; color: #e6ebf3; cursor: pointer;
}
.app-menu-item:hover { background: rgba(255,255,255,0.07); }
.app-menu-item .ico { font-size: 1.05rem; width: 1.3rem; text-align: center; }
.app-menu-item .menu-lock { margin-inline-start: auto; font-size: 0.85rem; opacity: 0.75; }

/* ── Profile stats + ratings ──────────────────────────────────────────────── */
.stats-card { max-width: 460px; margin: 1.2rem 0; padding: 1rem 1.1rem; border-radius: 14px;
    border: 1px solid rgba(201,162,75,.18); background: rgba(18,25,37,.5); }
.stats-card h2 { margin: 0 0 .8rem; font-size: 1.15rem; }
.stats-card .muted { color: var(--ink-dim); }
.stats-record { display: flex; gap: .6rem; margin-bottom: 1rem; }
.stats-record .stat { flex: 1 1 0; min-width: 0; text-align: center; padding: .6rem .3rem;
    border-radius: 10px; background: rgba(255,255,255,.04); }
.stats-record .stat-num { display: block; font-size: 1.7rem; font-weight: 800; color: var(--ink); }
.stats-record .stat-label { display: block; font-size: .72rem; color: var(--ink-dim);
    text-transform: uppercase; letter-spacing: .5px; }
.stats-sub { margin: .4rem 0 .5rem; font-size: 1rem; color: var(--ink); }
.ratings-table { width: 100%; border-collapse: collapse; }
.ratings-table th, .ratings-table td { padding: .45rem .5rem; text-align: start;
    border-bottom: 1px solid rgba(255,255,255,.06); }
.ratings-table th { font-size: .72rem; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .4px; }
.ratings-table .rating-val { font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }

/* ── App modal dialogs (Report / Settings / About) ────────────────────────── */
.modal-overlay {
    position: fixed; inset: 0; z-index: 200; display: flex; justify-content: center; align-items: flex-start;
    padding: 6vh 1rem 2rem; overflow-y: auto; background: rgba(6,9,14,0.62);
}
.modal-card {
    width: 100%; max-width: 460px; background: #161d29; color: var(--ink);
    border: 1px solid rgba(255,255,255,0.12); border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.5); padding: 1.1rem 1.2rem 1.3rem;
}
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.6rem; }
.modal-head h2 { margin: 0; font-size: 1.2rem; }
.modal-x {
    width: 34px; height: 34px; padding: 0; font-size: 1rem; line-height: 1;
    background: transparent; border: 1px solid rgba(255,255,255,0.15); border-radius: 9px;
    color: var(--ink-dim); cursor: pointer;
}
.modal-x:hover { background: rgba(255,255,255,0.07); color: var(--ink); }
.modal-actions { display: flex; justify-content: center; margin-top: 0.4rem; }
.modal-card textarea { width: 100%; box-sizing: border-box; resize: vertical; min-height: 96px; }
.settings-langs { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
.report-shot { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.report-shot img {
    max-width: 100%; max-height: 220px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.15);
}
/* Up to two attached screenshots side by side; each shrinks to fit narrow (mobile/RTL) widths. */
.report-shots { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.4rem; }
.report-shots .report-shot { flex: 1 1 140px; min-width: 0; }
.report-shots .report-shot img { max-height: 150px; }

/* Google's rendered GIS button mounts here (issue #29); reserve its height to avoid layout shift.
   Centered and clipped to the card so the fixed-width iframe can never stick out (report 97910f31). */
.external-signin .provider-slot {
    min-height: 44px; display: flex; justify-content: center;
    max-width: 100%; overflow: hidden;
}

/* Rules-page terms gate: the ToS text scrolls inside a bounded box; Agree enables at its end. */
.terms-scroll {
    max-height: min(46vh, 340px); overflow-y: auto; margin: 0.6rem 0; padding: 0.8rem 1rem;
    border: 1px solid rgba(255,255,255,0.18); border-radius: 10px;
}
.terms-scroll h3 { font-size: 1.3rem; margin-top: 0; }
.terms-scroll h4 { font-size: 1.05rem; }
.rules-terms-gate .terms-accept-btn { margin-top: 0.4rem; }

/* "Open in the Caracri app" chip on game pages (issue #30, desktop browsers only). */
.app-banner {
    display: inline-flex; align-items: center; gap: 0.4rem; margin: 0 0 0.6rem;
    padding: 0.3rem 0.6rem; border: 1px solid rgba(255,255,255,0.18); border-radius: 999px;
}
.app-banner-link { text-decoration: none; font-weight: 600; }
.app-banner-dismiss { line-height: 1; }

/* admin feedback screenshot + action cell */
.admin-shot { max-width: 100%; max-height: 320px; border-radius: 10px; border: 1px solid rgba(255,255,255,.15); cursor: zoom-in; }
.admin-nowrap { white-space: nowrap; }

.info-body { white-space: pre-wrap; line-height: 1.55; color: var(--ink); font-size: 0.95rem; }

.menu-scrim { position: fixed; inset: 0; z-index: 55; background: transparent; }

/* admin JSON blocks (report state/telemetry) + telemetry bars */
.admin-json { max-height: 260px; overflow: auto; background: #0c0f16; border: 1px solid rgba(255,255,255,.1);
    border-radius: 8px; padding: .6rem .7rem; font-size: .74rem; line-height: 1.4; white-space: pre-wrap; word-break: break-word; color: #cbd5e6; }
.admin-bar { display: grid; grid-template-columns: 1fr auto; gap: .5rem; align-items: center; padding: .18rem 0; }
.admin-bar .lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .8rem; }
.admin-bar .track { grid-column: 1 / -1; height: 6px; background: rgba(255,255,255,.07); border-radius: 4px; overflow: hidden; }
.admin-bar .fill { height: 100%; background: var(--gold); }

.admin-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin: 1rem 0; }
@media (max-width: 640px) { .admin-cols { grid-template-columns: 1fr; } }

/* settings checkbox */
.app-check { display: inline-flex; align-items: center; gap: .45rem; color: var(--ink); cursor: pointer; }
.app-check input { width: auto; }

/* nav layout: menu (left) | brand (centre) | language (right); auth + links on a second row.
   Keeps the menu and language buttons in opposite corners so they aren't misclicked. */
.topnav { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .5rem; padding: .4rem 0 .5rem; margin-bottom: .4rem; }
.nav-corner { display: inline-flex; align-items: center; }
.nav-left { justify-self: start; }
.nav-right { justify-self: end; }
.topnav .brand { justify-self: center; }
.subnav { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .4rem; margin: 0 0 1rem; min-height: 40px; }

/* ==========================================================================
   Responsive layouts (vertical vs horizontal) + app-level Game Focus Mode.
   Breakpoint: horizontal when the viewport is both reasonably wide AND at least
   as wide as it is tall (landscape phones/tablets + desktop windows); otherwise
   vertical. It is a pure CSS @media query, so it re-evaluates live on resize /
   rotation in the browser AND the MAUI WebView with zero JS and zero game-state
   loss. The board lives in ONE stable DOM element instance (.game-board-wrap)
   that is never re-parented between layouts or focus mode, so the <canvas> + JS
   module + live game are never re-mounted.
   ========================================================================== */

/* Vertical (default): plain block flow — today's stacked design (info/clock
   above the board, moves/controls below). */
.game-layout { display: block; }
.game-board-wrap { min-width: 0; }

/* Compact player/opponent block — hidden in the narrow normal layout (keeps
   today's design), shown in the wide side panel and whenever in focus mode. */
.player-block { display: none; align-items: center; gap: .6rem; margin: .1rem 0 .55rem; }
.player-block .pb-avatar { width: 34px; height: 34px; border-radius: 999px; object-fit: cover;
    border: 1px solid rgba(201,162,75,.4); background: rgba(255,255,255,.06); }
.player-block .pb-info { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.player-block .pb-name { font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; max-width: 220px; }
.player-block .pb-side { font-size: .82rem; color: var(--ink-dim); }

/* ── Horizontal (wide / landscape): board centre-left, ONE consolidated side
      column on the inline-end (flips under RTL because it is grid + logical
      source order, not left/right). ── */
@media (min-width: 820px) and (min-aspect-ratio: 1/1) {
    /* Slim, horizontal header that uses the width: the brand row stays compact
       and the account/guest controls move to the inline-end (not centred). */
    .topnav { padding: .3rem 0 .15rem; margin-bottom: .15rem; }
    .subnav { justify-content: flex-end; margin: 0 0 .6rem; }

    .game-layout {
        display: grid;
        grid-template-columns: minmax(0, 1fr) clamp(258px, 30%, 360px);
        grid-template-areas: "board top" "board side" "board fill";
        grid-template-rows: auto auto 1fr;
        gap: .8rem 1.25rem;
        align-items: start;
        max-width: 100%;
    }
    .game-info-top { grid-area: top; }
    .game-board-wrap { grid-area: board; display: flex; justify-content: center; align-items: flex-start; }
    .game-side { grid-area: side; min-width: 0; }

    /* The two side blocks read as one consolidated panel (stacked cards, single column). */
    .game-info-top, .game-side {
        margin: 0; box-sizing: border-box;
        background: linear-gradient(180deg, rgba(52,64,82,.42), rgba(28,37,51,.5));
        border: 1px solid rgba(201,162,75,.20); border-radius: 14px; padding: .85rem 1rem;
    }
    .game-info-top:empty { display: none; }
    .game-side .moves { margin-top: 0; }
    .game-side .game-chat { max-width: none; margin-top: 1rem; }

    /* Board fills its column but is capped by viewport height so it stays fully
       visible (the wait-bar + action chips add ~130px of chrome). */
    .game-board-wrap .board.board-stage { width: 100%; max-width: min(680px, 78vh); margin: 0; }

    /* #65 (report 08fbc0d7): in the wide layout the players form a vertical rail BESIDE the board —
       first mover at the top, second at the bottom — using the column's height instead of a cramped
       row with dead space below it. Mobile keeps the horizontal strip above the board. */
    .game-board-wrap { gap: 1rem; }
    .game-board-wrap .players-bar { flex-direction: column; justify-content: space-between; align-self: stretch; margin: 0; flex: 0 0 auto; max-width: 200px; }
    .game-board-wrap .players-bar .p-card { flex: 0 0 auto; }
    .game-board-wrap .players-bar .p-card.p-right { flex-direction: row-reverse; justify-content: flex-end; }

    /* The hot-seat game lives inside a narrow (460px) .panel card meant for the
       setup pickers — let it grow wide once it holds the board, so the board is
       the large central element. Only the game panel matches (not Find/Create). */
    .panel-tabbed:has(.game-layout) { max-width: none; }

    .player-block { display: flex; }

    /* Focus mode, horizontal: give the board more room, slimmer side column. */
    .app.focus-mode .game-layout { grid-template-columns: minmax(0, 1fr) clamp(240px, 24vw, 320px); }
    .app.focus-mode .game-board-wrap .board.board-stage { max-width: min(1000px, calc(100vh - 130px)); }
}

/* ── Game Focus Mode — app-level, CSS only. NOT the Fullscreen API: there is no
      requestFullscreen / window expansion / OS-chrome hiding anywhere. MainLayout
      toggles the .focus-mode class on .app from FocusModeState; the same
      .game-layout media query above keeps focus mode itself responsive. ── */
.focus-exit { display: none; }
.app.focus-mode > .topnav,
.app.focus-mode > .subnav,
.app.focus-mode .ad-slot,
.app.focus-mode main > h1,                     /* page heading (e.g. hot-seat "Play local") */
.app.focus-mode .home-note,                    /* hot-seat "Back" home link */
.app.focus-mode .game-page > p:first-child,    /* back-to-games link */
.app.focus-mode .game-page > .lede,            /* hot-seat lede */
.app.focus-mode .game-chat,                    /* chat is non-essential during focus */
.app.focus-mode .focus-enter-chip {            /* already in focus — hide the enter button */
    display: none !important;
}
/* C18 (#77 class): the fullscreen chip's icon+label wrapped mid-pill in RU — chips are
   single-line by design. Where the un-wrapped label would instead widen the action rail past
   the viewport (long locales on phones, C1), the chip degrades to icon-only: the ⛶ glyph plus
   title/aria carry the meaning. */
.focus-enter-chip { white-space: nowrap; }
@media (max-width: 900px) { .focus-enter-label { display: none; } }
.app.focus-mode { max-width: 100%; padding: .5rem .65rem 1rem; }
.app.focus-mode .player-block { display: flex; }
/* Shed the hot-seat setup card in focus so the board gets the whole area. */
.app.focus-mode .panel-tabbed:has(.game-layout) {
    max-width: none; background: none; border: none; box-shadow: none;
    padding: 0; -webkit-backdrop-filter: none; backdrop-filter: none;
}
.app.focus-mode .focus-exit {
    display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
    position: fixed; top: 8px; inset-inline-end: 8px; z-index: 300;
    padding: .42rem .8rem; min-height: 36px; border-radius: 10px; cursor: pointer;
    background: rgba(20,26,38,.86); border: 1px solid rgba(255,255,255,.20);
    color: #eef2f8; font-size: .9rem; font-weight: 700;
}
.app.focus-mode .focus-exit:hover { background: rgba(30,38,52,.96); }

.about-meta { color: var(--ink-dim); font-size: 0.8rem; margin: 0.4rem 0 0; }
/* The About dialog renders OUTSIDE <main>, so the site link color must be repeated here —
   default browser link blue is unreadable on the dark dialog (report 40d7ea73). */
.about-legal a { color: #86b7ff; }
.about-legal a:hover { color: #a9ccff; }

/* Icon-only chips (share / QR / add-friend — reports 164d0312, 18216ca6, b8f8b06e). */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.25rem 0.55rem; }
.share-ico { width: 17px; height: 17px; display: block; }

/* Account-required lock panel (guests on /friends — report a0d85340). */
.guest-lock { text-align: center; }
.guest-lock .navpill { display: inline-flex; }

/* Sign-in methods section (account linking): label/value rows + inline password form. */
.collapsible-head { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.collapse-caret { font-size: 0.8em; opacity: 0.7; }
.signin-methods .signin-row { display: flex; align-items: center; gap: 0.6rem; margin: 0.35rem 0; flex-wrap: wrap; }
.signin-methods .signin-label { color: var(--ink-dim); min-width: 8rem; }
.signin-methods .signin-val { display: inline-flex; align-items: center; gap: 0.4rem; word-break: break-word; }
.signin-methods .signin-actions { margin-top: 0.6rem; }
.signin-pw-form { margin-top: 0.6rem; }
.signin-pw-form input { width: 100%; box-sizing: border-box; }

/* Games-list finished rows: result icon + rating change */
.row-card .rc-result { flex: 0 0 auto; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; font-weight: 900; font-size: 1.15rem; }
.rc-result.res-win { background: rgba(46,125,50,.18); color: #6ed88a; }
.rc-result.res-loss { background: rgba(200,60,60,.16); color: #ff8a8a; }
.rc-result.res-abort { background: rgba(255,255,255,.08); color: var(--ink-dim); }
.rc-rating { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.rc-rating.up { color: #6ed88a; }
.rc-rating.down { color: #ff8a8a; }

/* Profile picture upload */
.icon-upload { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.icon-preview { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; border: 2px solid rgba(201,162,75,.4); }

/* ── /rules: full illustrated rules page ─────────────────────────────────────────────────────────── */
.rules-page { max-width: 760px; }
.rules-lede { margin-top: -0.15rem; }
.rules-sec { margin: 1.7rem 0; }
.rules-sec > h2 { margin: 0 0 .5rem; font-size: 1.25rem; }
.rules-sub { margin: 1.15rem 0 .35rem; font-weight: 700; color: var(--ink); font-size: 1.02rem; }
.rules-fig { margin: .95rem 0; text-align: center; }
.rules-fig svg, .rules-figrow svg, .rules-flow svg { max-width: 100%; height: auto; }
.rules-cap { color: var(--ink-dim); font-size: .85rem; margin: .4rem 0 0; }
.rules-legend { display: flex; flex-wrap: wrap; gap: .35rem 1rem; justify-content: center; margin: .55rem 0 0; color: var(--ink-dim); font-size: .85rem; }
.rules-legend span { display: inline-flex; align-items: center; gap: .4rem; }
.rules-sw { width: 14px; height: 14px; border-radius: 4px; display: inline-block; border: 1px solid rgba(255,255,255,.15); }
.rules-actions { margin: .45rem 0 .5rem; padding-inline-start: 1.25rem; }
.rules-actions li { margin: .2rem 0; }
.rules-tag { display: inline-block; padding: .12rem .5rem; border-radius: 999px; font-size: .78rem; font-weight: 800; letter-spacing: .3px; }
.rules-tag.legal { background: rgba(46,125,50,.2); color: #6ed88a; }
.rules-tag.illegal { background: rgba(200,60,60,.18); color: #ff8a8a; }
.rules-tag.soon { background: rgba(201,162,75,.18); color: var(--gold); text-transform: uppercase; }
/* formal-distance formula (kept LTR even under RTL) */
.rules-formula { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .5rem;
    direction: ltr; font-size: 1.12rem; margin: .55rem 0 .85rem; color: var(--ink); }
.rules-frac { display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15; }
.rules-frac .num { padding: 0 .45rem .1rem; border-bottom: 2px solid var(--ink-dim); }
.rules-frac .den { padding: .1rem .45rem 0; }
/* distance table */
.rules-tablewrap { overflow-x: auto; margin: .8rem 0; }
.rules-table { border-collapse: collapse; width: 100%; font-size: .9rem; }
.rules-table th, .rules-table td { text-align: start; padding: .4rem .6rem; border-bottom: 1px solid rgba(255,255,255,.09); }
.rules-table td.d, .rules-table th.d { text-align: end; font-variant-numeric: tabular-nums; font-weight: 800; color: var(--gold); }
.rules-table thead th { color: var(--ink-dim); font-weight: 700; }
/* confirmed-rule callout */
.rules-rule { display: flex; gap: .55rem; align-items: center; margin: .7rem 0; padding: .55rem .8rem;
    background: rgba(201,162,75,.08); border-inline-start: 3px solid var(--gold); border-radius: 8px; color: var(--ink); font-weight: 600; }
/* "coming soon" placeholder for spec sections the author is still finalising */
.rules-tbd { margin: .95rem 0; padding: .75rem .9rem; border: 1px dashed rgba(201,162,75,.5); border-radius: 10px; background: rgba(201,162,75,.06); }
.rules-tbd .rules-tbd-head { display: flex; align-items: center; gap: .5rem; font-weight: 800; color: var(--ink); margin-bottom: .3rem; }
.rules-tbd p { margin: 0; color: var(--ink-dim); font-size: .9rem; }
/* example + end-state cards */
.rules-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: .7rem; margin: .95rem 0; }
.rules-card { padding: .6rem; border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(255,255,255,.03); text-align: center; }
.rules-card .rc-title { font-weight: 700; font-size: .9rem; margin-bottom: .35rem; }
.rules-card .rc-math { direction: ltr; font-variant-numeric: tabular-nums; color: var(--ink-dim); font-size: .85rem; margin-top: .35rem; }
.rules-ends { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .7rem; margin: .95rem 0; }
.rules-end { padding: .7rem; border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(255,255,255,.03);
    display: flex; flex-direction: column; align-items: center; gap: .45rem; text-align: center; }
.rules-end .re-label { font-size: .86rem; color: var(--ink); }
.rules-verdict { padding: .12rem .5rem; border-radius: 999px; font-size: .76rem; font-weight: 800; }
.rules-verdict.go { background: rgba(46,125,50,.2); color: #6ed88a; }
.rules-verdict.stop { background: rgba(200,60,60,.18); color: #ff8a8a; }
/* real-render board diagrams (StaticBoard): a square canvas + an optional cell-unit SVG overlay */
.rules-static { position: relative; margin-inline: auto; max-width: 100%; }
.rules-static .board-static { display: block; width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; }
.rules-static-ov { position: absolute; inset: 0; pointer-events: none; }
.rules-static-ov svg { width: 100%; height: 100%; display: block; }
.rules-ends .rules-static { margin-bottom: .1rem; }
/* side-by-side figure rows + the creation-lifecycle flow */
.rules-figrow { display: flex; flex-wrap: wrap; gap: 1.1rem; justify-content: center; align-items: flex-start; margin: .9rem 0; }
.rules-figrow figure { margin: 0; text-align: center; max-width: 220px; }
.rules-flow { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .55rem; margin: .95rem 0; }
.rules-flow figure { margin: 0; text-align: center; }
.rules-flow figcaption { color: var(--ink-dim); font-size: .8rem; margin-top: .3rem; }
.rules-flow .rf-arrow { color: var(--ink-dim); font-size: 1.3rem; }
/* the five-line summary box at the top of /rules */
.rules-tldr-sec { margin-top: 1.15rem; }
.rules-tldr { margin: .6rem 0 0; list-style: decimal; border: 1px solid rgba(201,162,75,.3);
    background: rgba(201,162,75,.07); border-radius: 12px; padding: .85rem 1.1rem; padding-inline-start: 2.5rem; }
.rules-tldr li { margin: .4rem 0; color: var(--ink); line-height: 1.5; }
.rules-tldr li::marker { color: var(--gold); font-weight: 800; }
/* skin-aware legend swatches (colour chip in colour skins, CB shape in colourblind) */
.rules-sw-svg { width: 16px; height: 16px; flex: 0 0 auto; border-radius: 4px; }
/* game-length ballparks */
.rules-lengths { margin: .5rem 0 0; padding-inline-start: 1.25rem; color: var(--ink); }
.rules-lengths li { margin: .2rem 0; font-variant-numeric: tabular-nums; }
/* timers table: each mode cell stacks a starting bank over the per-move increment */
.rules-timers td, .rules-timers th { text-align: center; vertical-align: top; }
.rules-timers td.tb, .rules-timers th:first-child { text-align: start; font-weight: 700; white-space: nowrap; }
.rules-timers .tc-start { display: block; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.rules-timers .tc-inc { display: block; font-size: .8rem; color: var(--ink-dim); }

/* ── Worked example: a real AI game, stepped move by move (replaces the old live sandbox) ─────────── */
.rules-example-sec { margin-top: 2.1rem; }
.rex-stage { display: flex; flex-wrap: wrap; gap: 1.1rem; align-items: flex-start; margin: 1rem 0 0; }
.rex-board { flex: 1 1 260px; min-width: 240px; text-align: center; }
.rex-board svg { max-width: 100%; height: auto; }
.rex-panel { flex: 1 1 260px; min-width: 240px; }
.rex-controls { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .7rem; }
.rex-controls .chip { padding: .3rem .7rem; font-size: .85rem; }
.rex-indicator { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .8rem; margin-bottom: .55rem; }
.rex-move-of { font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.rex-tomove { display: inline-flex; align-items: center; gap: .35rem; color: var(--ink-dim); font-size: .9rem; }
/* Fix 1: reserve a stable height for the variable parts so autoplay stepping doesn't reflow the panel
   (and shift the board beside/above it). The commentary is 1–3 paragraphs (that wrap to more lines on
   narrow panels) and the ranked list is 2–4 rows; min-height only prevents shrinking, so nothing
   overflows on mobile. Narrow panels wrap more text, so they reserve more; wide desktop reserves less. */
.rex-commentary { min-height: 10rem; }
.rex-commentary p { margin: .35rem 0; color: var(--ink); line-height: 1.5; }
.rex-options { list-style: none; margin: .75rem 0 0; padding: 0; display: flex; flex-direction: column; gap: .28rem; min-height: 8.75rem; }
@media (min-width: 960px) { .rex-commentary { min-height: 8.5rem; } }
.rex-opt { display: flex; align-items: center; gap: .5rem; padding: .3rem .55rem; border-radius: 8px;
    background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.08); font-size: .88rem; }
.rex-opt.chosen { background: rgba(46,125,50,.14); border-color: rgba(110,216,138,.5); }
.rex-rank { color: var(--ink-dim); font-variant-numeric: tabular-nums; min-width: 1.9rem; }
.rex-move { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.rex-score { margin-inline-start: auto; color: var(--ink-dim); font-variant-numeric: tabular-nums; font-size: .82rem; }
.rex-opt .rules-tag { flex: 0 0 auto; }

.live-stats { color: #9aa7bd; font-size: .9rem; margin: -.25rem 0 .85rem; opacity: .9; }

/* ── Margin diet (user report: "any pixel must have a purpose") ─────────────────────────────── */
main h1 { margin: .2rem 0 .55rem; }                       /* browser default h1 margins were dead space */
.panel > .picker-label:first-child { margin-top: 0; }     /* no empty band above the first picker */

/* "My games" grouping: games waiting on you vs. on the opponent */
.games-group { margin: .7rem 0 .35rem; font-size: .95rem; color: var(--ink-dim); font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em; }

/* Queue: search settings freeze while in queue (cancel to change them) */
.row-locked .tile { pointer-events: none; opacity: .55; filter: saturate(.5); }

/* Profile / public player: compact view line (avatar · name · edit) */
.profile-view { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.profile-name { font-weight: 700; font-size: 1.15rem;
    /* A heading should WRAP a long unbroken name, not hide it (same gate finding as .rc-player). */
    overflow-wrap: anywhere; min-width: 0; }

/* Opponent link in the in-game status line + player block */
.vs-opponent { white-space: nowrap; }
a.pb-name { color: #86b7ff; text-decoration: none; }
a.pb-name:hover { text-decoration: underline; }

/* Every mention of a player's name is a doorway to their public page (/player/{id}) */
.rc-player, a.rc-player, a.chat-name { color: #86b7ff; cursor: pointer; text-decoration: none; }
.rc-player:hover, a.rc-player:hover, a.chat-name:hover { text-decoration: underline; }
/* Long unbroken display names truncate, never widen the page (gate 20260731-112700: a 38-char
   no-space name overflowed every live-lobby row at 390px; names are user-controlled, so this is
   reachable in prod). Inline-block so max-width applies inside the row flow. */
.rc-player, a.rc-player, a.chat-name {
    display: inline-block; max-width: 260px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* The lobby stats line links to the spectator lobby */
a.live-stats-link { color: inherit; text-decoration: none; }
a.live-stats-link:hover { color: #a9ccff; text-decoration: underline; }

/* While searching, the primary CTA is a status, not a button (report: "clicking it is UB") */
.cta-status { pointer-events: none; cursor: default; animation: ctaPulse 1.6s ease-in-out infinite; }
@keyframes ctaPulse { 50% { filter: brightness(1.18); } }

/* ── Pinned chrome (report 46231039): the top bar sticks to the top and the primary action row
   (queue / invite CTA) to the bottom, so both stay reachable while the middle scrolls. Focus mode
   hides the chrome entirely, so it is naturally exempt. ─────────────────────────────────────── */
/* Glassy like the panels, slim, LOW z-index (below every scrim/modal/menu).
   ⚠️ NEVER put backdrop-filter / filter / transform on .topnav: any of those properties turns the
   bar into the containing block for position:fixed descendants — fixed elements inside it (the
   hamburger dropdown) get trapped and clipped in the strip (real outage, report afc6b68a; the
   About/Report/Settings dialogs were hoisted to the app root in #10, but the menu still lives
   here and check-css still guards the property). Translucency comes from the gradient alpha. */
.topnav { position: sticky; top: 0; z-index: 30;
    /* FULLY opaque (#84): went .88 → .97 → 1.0. At .97 the residual bleed measures 2-4 luminance
       units — invisible to people, but contrast-amplifying screenshot review reads whole words
       through the bar and keeps re-reporting it. Opaque retires the class; the audit enforces it. */
    background: linear-gradient(180deg, rgb(44,55,73), rgb(26,35,49));
    border-bottom: 1px solid rgba(201,162,75,.18);
    padding: .3rem 0 .45rem; margin-bottom: .8rem; }
.panel .cta-row { position: sticky; bottom: 0; z-index: 40;
    margin: .4rem -1.1rem -1rem; padding: .55rem 1.1rem .8rem;
    background: linear-gradient(180deg, rgba(28,37,51,0), rgba(24,32,45,.96) 38%);
    border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; }

/* #46: global matchmaking-search indicator — a slim full-width row INSIDE the sticky header (so it
   rides above the profile row on every page). Rendered only while a search is active: when absent
   it leaves no gap. grid-column spans the header's 3-column grid; flex-basis covers the legacy
   flex layout of .topnav. The time value is LTR-isolated so RTL locales never reorder "1:23". */
.search-indicator {
    grid-column: 1 / -1; flex-basis: 100%;
    display: flex; align-items: center; justify-content: center; gap: .45rem;
    margin: .25rem .2rem 0; padding: .28rem .8rem; min-height: 30px;
    border-radius: 999px; text-decoration: none; font-weight: 600; font-size: .92rem;
    color: #f2e7c9; background: rgba(201,162,75,.16); border: 1px solid rgba(201,162,75,.4);
}
/* Hover feedback via the border only — the hover-background gate keeps washes off controls. */
.search-indicator:hover { border-color: rgba(201,162,75,.75); }
.search-indicator-time, .cta-status-time {
    font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate; color: #ffd97a;
}
.search-indicator-dot {
    width: 9px; height: 9px; border-radius: 50%; background: #ffd97a;
    animation: search-indicator-pulse 1.2s ease-in-out infinite;
}
@keyframes search-indicator-pulse {
    0%, 100% { opacity: .35; transform: scale(.8); }
    50% { opacity: 1; transform: scale(1.15); }
}
/* #73: focus mode hides .topnav (and the in-header indicator with it) — the floating copy keeps
   the search visible on the fullscreen game view. Hidden everywhere else; solid backdrop so it
   reads over the board. Top-center, clear of the corner focus-exit button. */
.search-indicator-floating { display: none; }
.app.focus-mode .search-indicator-floating {
    display: flex; position: fixed; top: 8px; left: 50%; transform: translateX(-50%);
    z-index: 300; max-width: min(70vw, 340px); margin: 0; padding: .3rem .9rem;
    background: rgba(20,26,38,.86);
}

/* ── Queue compactness (report 248f8515: "the whole page should fit a regular screen") ───────── */
.panel { padding: 1rem 1.1rem; }
.picker-label { margin: .5rem 0 .28rem; }
.tile-row { gap: .45rem; }
.tile { padding: .5rem .95rem; min-height: 40px; }
.cta-row .cta { min-height: 42px; }

/* Review step buttons: «‹›» glyph over a tiny localized caption. Equal width, tall enough that
   the caption never spills past the pill's bottom edge. The ROW wraps (Autoplay takes its own line
   when tight) while the step group stays together and fits a 360px viewport (issue #11). */
.review-row { justify-content: center; align-items: center; gap: .4rem .5rem; flex-wrap: wrap; }
/* CONTAINER-relative sizing, not viewport media queries: in landscape the game side column is
   ~260px wide while the viewport is 800px+, so a viewport breakpoint never fires and fixed-width
   buttons overflowed the page sideways (the standing horizontal-view issue). The four steps
   share the row equally and shrink with their container; the counter shrinks last. */
.rev-steps { display: flex; align-items: center; gap: .4rem; flex-wrap: nowrap; width: 100%; max-width: 340px; justify-content: center; }
.rev-btn { flex: 1 1 0; flex-direction: column; gap: .05rem; min-width: 0; max-width: 64px; min-height: 48px;
    padding: .3rem .2rem .35rem; line-height: 1; box-sizing: border-box; }
.rev-glyph { font-size: 1.15rem; font-weight: 800; }
.rev-cap { font-size: .6rem; color: var(--ink-dim); white-space: nowrap; overflow: hidden; max-width: 100%; text-overflow: ellipsis; }
.review-label { flex: 0 0 auto; min-width: 34px; text-align: center; font-variant-numeric: tabular-nums; }
@media (max-width: 430px) {
    .rev-steps { gap: .3rem; }
}

/* Players strip above the board: first mover (First) left, Second right; glow = side to act (review-aware) */
.players-bar { display: flex; justify-content: space-between; gap: .6rem; margin: 0 0 .5rem; }
.p-card { flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: .45rem;
    padding: .35rem .65rem; border: 2px solid rgba(255,255,255,.14); border-radius: 12px;
    background: rgba(28,37,51,.5); transition: border-color .15s, box-shadow .15s; }
.p-card.p-right { justify-content: flex-end; }
.p-card.acting { border-color: #6ed88a; box-shadow: 0 0 10px rgba(110,216,138,.28); }
.p-card .p-name { color: #86b7ff; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-card .p-name:hover { text-decoration: underline; }
.p-card .p-rating { color: var(--ink-dim); font-size: .82rem; white-space: nowrap; }
.side-dot { width: 18px; height: 18px; border-radius: 50%; flex: 0 0 auto; box-shadow: 0 0 6px rgba(0,0,0,.4); }
.side-dot.odd { background: radial-gradient(circle at 35% 30%, #a8d4ff, #1e78e0 60%, #0b3f86); }
.side-dot.even { background: radial-gradient(circle at 35% 30%, #ffe9a8, #f4b91c 60%, #8a5f00); }

/* Collapsible game-history filters (player page + My games): a small toggle chip, panel hidden by default */
.filter-toggle { font-size: .85rem; padding: .35rem .8rem; min-height: 34px; margin: 0 0 .5rem; }

/* Player page game-history filters: labelled controls + applied-filter chips */
.pg-filters { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .6rem; align-items: flex-end; }
.pg-filters select, .pg-filters input { background: #141b28; color: var(--ink);
    border: 1px solid rgba(255,255,255,.16); border-radius: 8px; padding: .38rem .5rem; font-size: .9rem; }
.pg-f { display: flex; flex-direction: column; gap: .15rem; font-size: .78rem; color: var(--ink-dim); }
.pg-opp { flex: 1 1 auto; min-width: 140px; }
.pg-chips { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 .6rem; }
.pg-chip { font-size: .8rem; padding: .25rem .65rem; min-height: 30px; }
.pg-chip .x { margin-inline-start: .4rem; opacity: .8; font-weight: 700; }

/* No tap flash on the custom controls — reads as a stray "animation" on touch */
.tile, .chip, .navpill, .menu-tile, main button, .row-card { -webkit-tap-highlight-color: transparent; }

/* Touch devices: hover is now only a brightness lift (never a skin swap), and on hoverless/coarse
   pointers even that is off — a tap can never leave any lingering visual state. */
@media (hover: none), (pointer: coarse) {
    .chip:hover, .chip-danger:hover, .tile:hover, .navpill:hover,
    main button:hover, .btn:hover, .provider:hover, main button[type=submit]:hover,
    .menu-tile:hover, .menu-tile.primary:hover { filter: none; }
    .menu-tile:hover { transform: none; }
    a.row-card:hover { border-color: rgba(255,255,255,.10); transform: none; }
}

/* Inline share chip next to the game back link (any online game is link-shareable). RTL-safe gap. */
.share-inline { margin-inline-start: .75rem; }

/* Download artifacts are plain links, not chips (owner report b119368f). */
.dl-link { text-decoration: underline; margin-inline-end: 1.1rem; }
/* Paused board placeholder + pause countdown (issue #22 part 2). */
.board-paused { text-align: center; padding: 2.5rem 1rem; }
.pause-countdown { text-align: center; font-weight: 600; }

.paused-title { font-weight: 700; font-size: 1.2rem; }

/* ── Puzzles & custom-board editor (#97) ─────────────────────────────────────────── */
.pz-menu { margin-bottom: 14px; }
.pz-editor .pz-toolbar { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; }
.pz-dim select { margin-inline-end: 10px; }
.pz-palette { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; }
.pz-tool { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.04); color: inherit; cursor: pointer; }
.pz-tool.active { border-color: #c9a24b; box-shadow: 0 0 0 1px #c9a24b inset; }
.pz-swatch { width: 14px; height: 14px; border-radius: 3px; display: inline-block; border: 1px solid rgba(255,255,255,0.25); }
.pz-first .pz-swatch { background: #101d34; border-color: #4a90e2; }
.pz-second .pz-swatch { background: #2a2207; border-color: #f6d63f; }
.pz-both .pz-swatch { background: #0e2a18; border-color: #3ecf6e; }
.pz-none .pz-swatch { background: #171e2a; }
.pz-spent .pz-swatch { background: #090c13; }
.pz-sunfirst .pz-swatch { background: radial-gradient(circle, #4a90e2 55%, #101d34 60%); }
.pz-sunsecond .pz-swatch { background: radial-gradient(circle, #f6d63f 55%, #2a2207 60%); }
.pz-delete .pz-swatch { background: transparent; border-style: dashed; }
.pz-grid { display: grid; gap: 2px; margin: 12px auto; }
.pz-cell { position: relative; aspect-ratio: 1; border: 1px solid rgba(255,255,255,0.10); border-radius: 3px;
  background: #171e2a; cursor: pointer; padding: 0; min-width: 20px; }
.pz-cell.cfirst { background: #101d34; }
.pz-cell.csecond { background: #2a2207; }
.pz-cell.cboth { background: #0e2a18; }
.pz-cell.cnone { background: #171e2a; }
.pz-cell.spent { background: #090c13; }
.pz-cell.occupied { background: #090c13; }
.pz-cell.gone { background: transparent; border-style: dashed; border-color: rgba(255,255,255,0.16); }
.pz-sun { position: absolute; inset: 18%; border-radius: 50%; }
.pz-sun.yellow { background: radial-gradient(circle, #fff2af 15%, #f6d63f 60%, #b48f1c 100%); }
.pz-sun.blue { background: radial-gradient(circle, #d7e9ff 15%, #4a90e2 60%, #20548c 100%); }
.pz-actions { flex-wrap: wrap; }
.pz-objective { white-space: pre-wrap; }
.pz-movecount { margin-inline-start: 10px; }
