/* The palette is fully tokenised so a theme is just a set of variable values.
   :root holds the default (Dark); the [data-theme] blocks below override it.
   Themes are local-only (chosen client-side, persisted in localStorage). */
:root {
    color-scheme: dark; /* light-on-dark native scrollbars + form-control arrows */
    --bg: #0f1115;
    --surface: #171a21;
    --surface-2: #1f232c;
    --surface-3: #2c3340;
    --border: #2a2f3a;
    --text: #e7e9ee;
    --muted: #8b93a3;
    --accent: #4f9dff;
    --accent-soft: #1d2c44;
    --on-accent: #06101f;
    --opponent: #ff8a5b;
    --positive: #3fbf6f;
    --idle: #e0a33a;
    --danger: #ff6b6b;
    --danger-soft: #5e2b2b;
    --hero: #182033;
    --radius: 10px;
    --tabbar-h: 56px;
}

body[data-theme="light"] {
    color-scheme: light;
    --bg: #f1f4f9;
    --surface: #ffffff;
    --surface-2: #e3e9f2;
    --surface-3: #d3dbe8;
    --border: #c6cedb;
    --text: #1b2027;
    --muted: #5f6775;
    --accent: #2f7fe6;
    --accent-soft: #d8e6fb;
    --on-accent: #ffffff;
    --opponent: #d9603a;
    --positive: #2a9d5a;
    --idle: #bd821a;
    --danger: #d6453f;
    --danger-soft: #f3d3d0;
    --hero: #dde6f3;
}

body[data-theme="sepia"] {
    color-scheme: light;
    --bg: #efe6d6;
    --surface: #f8f1e3;
    --surface-2: #e6dac4;
    --surface-3: #dbcbad;
    --border: #d2c2a4;
    --text: #3a3328;
    --muted: #877760;
    --accent: #3f6f8f;
    --accent-soft: #d3cdbb;
    --on-accent: #f8f1e3;
    --opponent: #b85a32;
    --positive: #6f8f3f;
    --idle: #b0801f;
    --danger: #b5443a;
    --danger-soft: #e6cbb8;
    --hero: #e2d5be;
}

body[data-theme="blush"] {
    color-scheme: light;
    --bg: #faf0f4;
    --surface: #ffffff;
    --surface-2: #f4e1ea;
    --surface-3: #ecd0de;
    --border: #e2bfd1;
    --text: #3c2330;
    --muted: #97697f;
    --accent: #0e97a8;
    --accent-soft: #cce8ec;
    --on-accent: #ffffff;
    --opponent: #7c5cdb;
    --positive: #2f9e69;
    --idle: #c4881f;
    --danger: #d6453f;
    --danger-soft: #f3d3d0;
    --hero: #f1d9e6;
}

body[data-theme="lagoon"] {
    color-scheme: light;
    --bg: #ecf5f4;
    --surface: #ffffff;
    --surface-2: #d8eae8;
    --surface-3: #c5dedb;
    --border: #b3d2ce;
    --text: #1c2e2c;
    --muted: #5a716e;
    --accent: #2f49cf;
    --accent-soft: #d4daf6;
    --on-accent: #ffffff;
    --opponent: #d75a9c;
    --positive: #2a9d5a;
    --idle: #bd821a;
    --danger: #d6453f;
    --danger-soft: #f3d3d0;
    --hero: #d7ebe8;
}

body[data-theme="ember"] {
    --bg: #15100b;
    --surface: #1e1812;
    --surface-2: #29211a;
    --surface-3: #362b1f;
    --border: #3a2e21;
    --text: #f1e7d8;
    --muted: #a28f76;
    --accent: #ecb53f;
    --accent-soft: #3a2c18;
    --on-accent: #1a1209;
    --opponent: #d83a2e;
    --positive: #9ab04a;
    --idle: #cf9a3a;
    --danger: #f06a5a;
    --danger-soft: #45241a;
    --hero: #241a10;
}

body[data-theme="midnight"] {
    --bg: #080b14;
    --surface: #0f1422;
    --surface-2: #161d2e;
    --surface-3: #212b42;
    --border: #232c44;
    --text: #dce3f2;
    --muted: #7c87a3;
    --accent: #3ec9dd;
    --accent-soft: #123842;
    --on-accent: #060b16;
    --opponent: #ff6ba0;
    --positive: #45cf85;
    --idle: #e2b150;
    --danger: #ff7b7b;
    --danger-soft: #4a2530;
    --hero: #141d33;
}

body[data-theme="orchid"] {
    --bg: #17101f;
    --surface: #20162c;
    --surface-2: #2a1e39;
    --surface-3: #382a4b;
    --border: #38294c;
    --text: #efe5f5;
    --muted: #a991ba;
    --accent: #e9609b;
    --accent-soft: #3a2034;
    --on-accent: #1c0c15;
    --opponent: #7d8cf2;
    --positive: #4fcf86;
    --idle: #e0b24f;
    --danger: #ff7691;
    --danger-soft: #4a2333;
    --hero: #271738;
}

* { box-sizing: border-box; }

/* The hidden attribute must win over our author `display` rules (e.g. .gate { display: grid }). */
[hidden] { display: none !important; }

html, body {
    margin: 0;
    height: 100%;
}

body {
    background: var(--bg);
    color: var(--text);
    font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    overflow: hidden;
}

/* --- Entry gate --- */
.gate {
    position: fixed;
    inset: 0;
    display: grid;
    place-items: center;
    background: radial-gradient(120% 120% at 50% 0%, var(--hero) 0%, var(--bg) 60%);
    z-index: 10;
}

.gate__card {
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: min(360px, 90vw);
    text-align: center;
}

.gate__logo {
    margin: 0;
    font-size: 40px;
    letter-spacing: -0.02em;
}

.gate__tagline {
    margin: 0 0 8px;
    color: var(--muted);
}

.gate__input, .gate__button, .chat-form__input {
    font: inherit;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    padding: 12px 14px;
    background: var(--surface);
    color: var(--text);
}

.gate__input:focus, .chat-form__input:focus {
    outline: none;
    border-color: var(--accent);
}

.gate__button {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
    cursor: pointer;
}

.gate__button:hover { filter: brightness(1.08); }
.gate__button:disabled { opacity: 0.5; cursor: not-allowed; }

.gate__status {
    margin: 4px 0 0;
    min-height: 1.2em;
    font-size: 13px;
    color: var(--muted);
}

/* --- App shell: three columns --- */
.app {
    display: grid;
    grid-template-columns: max-content 1fr 300px;
    height: 100vh;
}

.panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-right: 1px solid var(--border);
}

.panel--chat { border-right: none; border-left: 1px solid var(--border); }
.panel--board { background: var(--bg); }
.panel--list, .panel--chat { background: var(--surface); }

.panel__header {
    padding: 16px 18px;
    font-weight: 600;
    border-bottom: 1px solid var(--border);
    flex: 0 0 auto;
}

/* The left panel's header doubles as the app wordmark (echoes the gate logo). */
.panel__header--brand {
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.03em;
}

/* --- Player / match list --- */
.list { overflow-y: auto; padding: 8px 0; flex: 1 1 auto; min-height: 0; }

/* The "you" identity row + inline rename, pinned to the bottom of the left panel. */
.identity {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 18px;
    border-top: 1px solid var(--border);
    flex: 0 0 auto;
}
.identity__label { flex: 0 0 auto; color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; }
/* The name button and the edit field share one box so they're the same size: the name
   reads as an editable chip (accent on hover), the field gets an accent border. */
.identity__name, .identity__input {
    flex: 1 1 auto;
    min-width: 0;
    font: inherit;
    font-size: 13px;
    padding: 5px 8px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    text-align: left;
}
.identity__name { font-weight: 600; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.identity__name:hover { border-color: var(--accent); }
.identity__input { border-color: var(--accent); }
.identity__input:focus { outline: none; }
.identity__save {
    flex: 0 0 auto;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 5px 11px;
    border-radius: 6px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--on-accent);
    cursor: pointer;
}
.identity__save:hover { filter: brightness(1.08); }
/* Secondary, low-emphasis action; reddens on hover since it discards the session. */
.identity__signout {
    flex: 0 0 auto;
    font: inherit;
    font-size: 11px;
    padding: 5px 8px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    white-space: nowrap;
}
.identity__signout:hover { color: var(--danger); border-color: var(--danger); }

/* Theme swatches, pinned to the bottom of the left panel. Each swatch shows the
   theme it selects (its background + accent), while its border/ring uses the
   *current* theme's tokens so the active marker adapts. */
.theme-picker {
    display: flex;
    gap: 9px;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    flex: 0 0 auto;
}
.theme-swatch {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    padding: 0;
    border-radius: 50%;
    border: 2px solid var(--border);
    cursor: pointer;
    transition: transform 140ms ease;
}
.theme-swatch:hover { transform: scale(1.12); }
.theme-swatch.is-active {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-soft);
}
.list__group { margin-bottom: 6px; }

.list__title {
    margin: 0;
    padding: 10px 18px 4px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
}

/* The lobby header doubles as a way back to the shared chat, and carries the
   unread badge for lobby messages when you're not currently viewing it. */
.list__title--lobby { display: flex; align-items: center; cursor: pointer; }
.list__title--lobby:hover { color: var(--accent); }
.list__title-badge {
    margin-left: auto;
    min-width: 16px;
    height: 16px;
    padding: 0 5px;
    border-radius: 8px;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 10px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    letter-spacing: 0;
}

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

.entry {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 18px;
    cursor: pointer;
    border-left: 3px solid transparent;
}

.entry:hover { background: var(--surface-2); }
.entry.is-selected { background: var(--accent-soft); border-left-color: var(--accent); }
/* The challenge/rematch and your-turn pills pulse their colour to and from the local
   participant accent — a softer draw for the eye than the old opacity blink. */
.entry__badge--pulse { animation: pulse-accent 1.4s ease-in-out infinite; }
@keyframes pulse-accent {
    0%, 100% { color: var(--muted); border-color: var(--border); }
    50% { color: var(--accent); border-color: var(--accent); }
}

.entry__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--positive);
    flex: 0 0 auto;
}
.entry__dot--idle { background: var(--idle); }

.entry__name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entry__result { flex: 0 0 auto; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
/* Spectated bot-vs-bot rows: a de-emphasised "vs", and a per-side score coloured like the board status bar. */
.entry__vs { margin: 0 0.45em; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.entry__score { margin-left: 0.3em; font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
.entry__score--a { color: var(--accent); }
.entry__score--b { color: var(--opponent); }

/* Trailing indicators (unread count now; an its-your-turn marker will join it). */
.entry__badge {
    flex: 0 0 auto;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    font-size: 11px;
    font-weight: 600;
    line-height: 18px;
    text-align: center;
}
.entry__badge--unread { background: var(--accent); color: var(--on-accent); }
.entry__badge--action {
    min-width: 0;
    height: auto;
    line-height: 1;
    padding: 3px 7px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--muted);
    text-transform: uppercase;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.05em;
}


/* --- Board / quick play --- */
.panel--board { align-items: center; justify-content: center; }

.board-empty { text-align: center; display: flex; flex-direction: column; gap: 12px; align-items: center; }

.quick-play {
    font: inherit;
    font-size: 18px;
    font-weight: 600;
    padding: 16px 40px;
    border-radius: var(--radius);
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--on-accent);
    cursor: pointer;
}
.quick-play:hover { filter: brightness(1.08); }

.board-empty__hint { color: var(--muted); margin: 0; }

/* Dev self-play launcher (revealed only when the server answers in dev mode). */
.selfplay { margin-top: 18px; padding: 16px 18px; border: 1px solid var(--border); border-radius: 12px; display: flex; flex-direction: column; gap: 10px; text-align: left; min-width: 300px; }
.selfplay__title { margin: 0; font-size: 14px; color: var(--text); }
.selfplay__row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.selfplay__row > label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 13px; }
/* Force identical box metrics on the select and the number fields (border-box + fixed height), so a
   native select's intrinsic padding can't make it taller than the text inputs. */
.selfplay select, .selfplay input { background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 7px; height: 32px; padding: 0 8px; font: inherit; line-height: 30px; }
.selfplay input[type="number"] { width: 72px; }
.selfplay__status { margin: 2px 0 0; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; min-height: 1em; }
.selfplay__status:empty { display: none; }

/* The grid is the fixed centre; header and footer sit in the balanced rows around
   it, so their changing size never nudges the board between turns. */
.board-view {
    display: grid;
    grid-template-rows: 1fr auto 1fr;
    justify-items: center;
    gap: 14px;
    width: 100%;
    height: 100%;
    padding: 16px;
    box-sizing: border-box;
    --board-size: min(70vmin, 70vw, 520px);
}
.board-status { align-self: end; }
.board-foot { align-self: start; }

.board-stage {
    position: relative;
    width: var(--board-size);
    aspect-ratio: 1;
}
.board-cursors {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* One generic cursor for any size: a rounded border with a gap at the middle of each
   tile edge (period --tile, set in JS). Two striped masks — vertical and horizontal —
   intersected keep only the corners, so the border's own rounding gives matching
   inner/outer radii (inner = outer - thickness: a clean bent line, not a 90° inner
   notch). At 1x1 that's four rounded brackets; at 4x4, a gap at every tile boundary. */
.cursor {
    position: absolute;
    top: 0;
    left: 0;
    /* Line thickness and corner radius scale with the tile pitch (--tile, set in JS) so
       the cursor keeps its proportions across formats, like the glyphs do. Both scale
       together, so the rounded bend (inner radius = outer - edge) stays consistent. */
    --edge: clamp(2px, calc(var(--tile, 40px) * 0.07), 5px);
    --seg: 30%;
    border: var(--edge) solid currentColor;
    border-radius: clamp(3px, calc(var(--tile, 40px) * 0.13), 9px);
    transition: transform 240ms ease;
    -webkit-mask:
        linear-gradient(to right, #000 0 var(--seg), transparent var(--seg) calc(100% - var(--seg)), #000 calc(100% - var(--seg)) 100%) left top / var(--tile) 100% repeat-x,
        linear-gradient(to bottom, #000 0 var(--seg), transparent var(--seg) calc(100% - var(--seg)), #000 calc(100% - var(--seg)) 100%) left top / 100% var(--tile) repeat-y;
    -webkit-mask-composite: source-in;
    mask:
        linear-gradient(to right, #000 0 var(--seg), transparent var(--seg) calc(100% - var(--seg)), #000 calc(100% - var(--seg)) 100%) left top / var(--tile) 100% repeat-x,
        linear-gradient(to bottom, #000 0 var(--seg), transparent var(--seg) calc(100% - var(--seg)), #000 calc(100% - var(--seg)) 100%) left top / 100% var(--tile) repeat-y;
    mask-composite: intersect;
}
.cursor--local { color: var(--accent); transition: none; }
.cursor--remote { color: var(--opponent); }
/* When observing, the local cursor is driven by a participant's moves, so it glides like the remote one. */
.cursor--local.cursor--gliding { transition: transform 240ms ease; }

/* Scores stay pinned to the board's top corners; the turn label is centred
   absolutely so a changing label or score never shifts anything. */
.board-status {
    position: relative;
    width: var(--board-size);
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-weight: 600;
}
.board-status__side {
    display: flex;
    align-items: baseline;
    gap: 6px;
}
/* The name stays full-strength on both sides — never dimmed on the opponent's turn.
   Whose turn it is reads from the centred turn label and the always-tinted scores. */
.board-status__name { font-weight: 500; color: var(--text); }
.board-status__score { font-weight: 700; font-variant-numeric: tabular-nums; }
/* Each side's score is always tinted in that player's colour (you = accent, them = opponent). */
#board-status-me .board-status__score { color: var(--accent); }
#board-status-them .board-status__score { color: var(--opponent); }

/* A single centred turn label: accent for your turn, red for theirs. */
.board-status__turn {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    color: var(--accent);
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.board-status__turn--them { color: var(--opponent); }
.board-status__turn--won { color: var(--positive); }
.board-status__turn--lost { color: var(--muted); }

.board-grid {
    display: grid;
    grid-template-columns: repeat(var(--columns, 12), 1fr);
    /* The tiles have no border of their own; the --border grid background shows through the gap
       and padding to separate them. gap/padding absorb the 1px the old per-tile inset used to add
       on each side, so the separators (4px between tiles, 3px frame) are unchanged. */
    gap: 4px;
    width: 100%;
    height: 100%;
    /* Match the gap so the outer frame is the same thickness as the gaps between tiles. */
    padding: 4px;
    box-sizing: border-box;
    background: var(--border);
    cursor: none;
}
/* Observing a match you're not in: the local cursor follows the players, not the pointer, so show
   the real pointer for inspecting tiles. */
.board-grid.is-observing { cursor: default; }

.tile {
    display: grid;
    place-items: center;
    aspect-ratio: 1;
    /* 1px (not 2px): matches the corner the old inset border used to leave on the tile surface. */
    border-radius: 1px;
    font-weight: 700;
    /* Scale glyphs with the actual tile size (board ÷ columns) so numbers and mines
       keep the same proportion across formats, not a fixed viewport size. */
    --tile-glyph: clamp(8px, calc(var(--board-size) / var(--columns, 12) * 0.46), 28px);
    font-size: var(--tile-glyph);
    user-select: none;
    background: var(--surface-2);
}
.board-grid.is-interactive:not(.is-bombing) .tile--closed:hover { background: var(--surface-3); }
.tile--target { background: var(--surface-3); }
.tile--open { background: var(--bg); }
/* Captured mines are tinted by who captured them (you = accent, them = opponent), on the normal
   revealed background so the cursor stays visible over a mine. Count numbers instead take the
   neutral name text colour (white in dark themes) — high contrast on the background, and clearly
   distinct from the coloured mines. */
.tile--mine-me { color: var(--accent); }
.tile--mine-them { color: var(--opponent); }
.tile--owner-me, .tile--owner-them { color: var(--text); }

.tile--reveal { animation: tile-reveal 180ms ease-out forwards; }
@keyframes tile-reveal {
    from { opacity: 0; transform: scale(0.5); }
    to { opacity: 1; transform: scale(1); }
}

/* Dev solver overlay (toggle with D in dev mode): exact mine odds painted on closed tiles in a
   single neutral colour (readable on every theme). No always-on fills, borders, or outlines —
   flood risk is revealed only on hover. The hover readout reuses the footer label. Never shown
   to a normal player. */
.tile--solver {
    /* Scale the odds with tile size like the revealed numbers do, but smaller so two
       digits fit — ~0.64 of the single-glyph size keeps "88" inside the tile. */
    font-size: calc(var(--tile-glyph) * 0.64);
    font-weight: 700;
    line-height: 1;
    /* Dimmer than --muted so the hover highlight (--text) reads clearly against it. */
    color: color-mix(in srgb, var(--muted) 62%, var(--bg));
    font-variant-numeric: tabular-nums;
}
.tile--solver-approx { opacity: 0.55; font-style: italic; }
/* A certainty shows the mine glyph at the tile's normal glyph size (not the smaller odds size). */
.tile--solver-mine { font-size: var(--tile-glyph); }

/* Hover highlights (transient): a constraint-mate brightens its number to the higher-contrast
   text colour. The flood region is OUTLINED — its perimeter is drawn as exact rectangles in the
   inter-tile gaps on an SVG layer over the grid (see SolverOverlay.drawFloodOutline), which the
   per-side CSS approaches couldn't do without miter/corner artifacts. */
.tile--solver-mate { color: var(--text); }
.flood-outline {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    pointer-events: none;
}
/* Contrasts with the regular --border gaps the theme-appropriate way: mixing toward --text makes
   it darker in light themes and lighter in dark ones. */
.flood-outline rect { fill: color-mix(in srgb, var(--border) 65%, var(--text)); }

/* gap matches the board-view grid gap (status↔board↔footer) so the spacing above
   the label equals the spacing below it (label↔buttons). */
.board-foot { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; min-height: 32px; }
/* Status message and the likelihood readout share one centred line, joined by the same em-dash
   the message uses internally — but only when the message is present, so there's no dangling dash. */
.board-statusline { display: flex; align-items: baseline; justify-content: center; }
.board-message { color: var(--muted); font-size: 13px; }
.board-message:empty { display: none; }
.board-message:not(:empty) + .board-likelihood::before { content: "\2014"; margin: 0 0.45em; color: var(--muted); }
/* Live likelihood readout (dev): how probable the current turn's outcomes were; updates per reveal. */
.board-likelihood { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; white-space: nowrap; }
.board-likelihood:empty { display: none; }
/* On-demand hover lookahead (dev): the move's Monte-Carlo value, inline on the status line. */
.board-lookahead { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; white-space: nowrap; }
.board-lookahead:empty { display: none; }
.board-message:not(:empty) ~ .board-lookahead:not(:empty)::before { content: "\2014"; margin: 0 0.45em; color: var(--muted); }

/* One shared button look across the whole footer: bomb, resign, rematch/dismiss,
   accept/decline. They give a clear, consistent surface (never the disabled-looking
   transparent fill). */
.board-button {
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    padding: 8px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, filter 160ms ease;
}
.board-button:hover:not(:disabled) { border-color: var(--muted); }
.board-button:disabled { opacity: 0.45; cursor: not-allowed; }
.board-button--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.board-button--primary:hover:not(:disabled) { border-color: var(--accent); filter: brightness(1.08); }

/* Bomb armed = the local-player accent; resign reddens on hover. */
#bomb-button.is-armed { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
#resign-button:hover:not(:disabled) { color: var(--danger); border-color: var(--danger); }

/* In-match action row: bomb + resign, side by side and equally sized. */
/* Buttons fit their content and centre under the board, rather than stretching to the
   footer label's width. */
.board-actions { display: flex; gap: 8px; }

/* Pre-match format picker (Blitz / Duel / Epic): a small segmented control. */
.format-picker { display: flex; gap: 6px; }
.format-picker__option {
    font: inherit;
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.25;
    padding: 5px 12px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    transition: color 160ms ease, border-color 160ms ease;
}
.format-picker__option:hover { color: var(--text); }
.format-picker__option.is-selected { border-color: var(--accent); color: var(--accent); }
.format-picker__name { font-size: 13px; font-weight: 600; }
.format-picker__dims { font-size: 10px; opacity: 0.7; }

/* End-of-match controls: rematch / dismiss, or the rematch-offer handshake. */
.match-end { display: flex; gap: 10px; }

/* --- Chat --- */
.messages {
    list-style: none;
    margin: 0;
    padding: 12px 16px;
    flex: 1 1 auto;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.msg { word-wrap: break-word; }
/* Sender names mirror the board's participant colours: your own messages in the
   local-player accent, everyone else in the opponent colour. */
.msg__from { font-weight: 600; color: var(--opponent); margin-right: 6px; }
.msg--system { color: var(--muted); font-size: 13px; font-style: italic; }
.msg--mine .msg__from { color: var(--accent); }

.chat-form { padding: 12px; border-top: 1px solid var(--border); flex: 0 0 auto; }
.chat-form__input { width: 100%; }
.chat-form__input:disabled { opacity: 0.5; cursor: not-allowed; }

/* --- Mobile tab bar (hidden on desktop) --- */
.tabbar { display: none; }

@media (max-width: 760px) {
    .app {
        grid-template-columns: 1fr;
        height: calc(100vh - var(--tabbar-h));
    }

    .panel { border: none; }
    .panel { display: none; }
    body[data-active-panel="opponents"] .panel--list,
    body[data-active-panel="board"] .panel--board,
    body[data-active-panel="chat"] .panel--chat { display: flex; }

    .tabbar {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        height: var(--tabbar-h);
        border-top: 1px solid var(--border);
        background: var(--surface);
    }

    .tabbar__tab {
        font: inherit;
        background: none;
        border: none;
        color: var(--muted);
        cursor: pointer;
    }
    .tabbar__tab.is-active { color: var(--accent); font-weight: 600; }
}
