/* Wizard — the AMIGO cover's palette: blackletter on near-black slate, parchment cards.
   The colour scheme is derived from cover.jpg (desaturated blue-grey stone under a heavy
   black wash) and the four card colours are its glowing rune accents, kept saturated.
   An earlier violet theme was retinted onto this hue wholesale, which is why so many
   literals here are slate values rather than named variables.
   The board is JS-positioned: game.js writes left/top/width/height (and font-size) onto
   every card and plate from the viewport dimensions, so this file styles appearance only
   and never the board geometry. Card internals are sized in `em` against the card's own
   font-size, which game.js sets to the current card width — one number scales a card. */

/* ── Augusta (self-hosted) ───────────────────────────────────────────────────
   The same blackletter display face games/Dalmuti uses, copied from
   games/Dalmuti/assets/fonts/. woff2 first (23 KB vs 55 KB for the ttf); the ttf
   stays as the fallback. It carries the whole game, with one deliberate exception
   below: see --numerals. */
@font-face {
    font-family: 'Augusta';
    src: url('assets/fonts/Augusta.woff2') format('woff2'),
         url('assets/fonts/Augusta.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    --w-yellow: #f2c200;
    --w-red:    #c0392b;
    --w-green:  #27ae60;
    --w-blue:   #2980b9;

    --display: 'Augusta', Georgia, serif;
    /* Augusta carries the whole game — the one exception is the card's CORNER PIP, which
       is set in a lining sans. It renders at ~0.2em (about 8px on a small card) and in a
       crowded fan it is the only part of a covered card still visible; a blackletter 1/0
       at that size is indistinguishable from I/O. The big face numeral is large enough to
       stay in Augusta and does. */
    --numerals: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    --parchment:  #f6ead0;
    --parchment-2:#e6d4ae;
    --ink:        #2a1c0c;

    /* Kept under the old names so every rule that referenced them still reads; they are
       slate now, not violet — the cover's palette is desaturated blue-grey stone. */
    --violet:      #5d6d7d;
    --violet-soft: #899caf;
    --gold:        #c9a94f;
    --gold-bright: #e8c15a;
    --cream:       #f0ead8;
    --panel-bg:    rgba(19, 22, 25, 0.97);
}

html, body { height: 100%; }
body {
    font-family: var(--display);
    /* cover.jpg's slate merged onto the shared table photo, the whole thing under a
       near-black wash — the cover's own value range.
       `luminosity` takes the STONE (its light and shade) from the cover and the hue from
       the table beneath, so the two read as one surface rather than a picture laid on a
       photo.
       The cover is deliberately ZOOMED PAST its artwork, onto the clean slate along its
       bottom-left. At 1:1 the wordmark ghosts straight across the felt and the AMIGO
       publisher mark sits in the corner of the table like a watermark — neither belongs
       behind live cards. The artwork itself is shown whole on the start screen, where a
       cover image is actually a cover image. Upscaling softens the stone, which is the
       right direction for something this dark. */
    background:
        /* 1. darkening wash — this is what "more transparent" actually means for a
              background layer, since CSS has no per-layer opacity */
        linear-gradient(rgba(8, 10, 12, 0.74), rgba(8, 10, 12, 0.87)),
        /* 2. a flat grey veil over the whole thing */
        linear-gradient(rgba(150, 158, 168, 0.24), rgba(150, 158, 168, 0.24)),
        /* 3. the shared table photo, soft-lit ONTO the cover: soft-light keeps the base
              layer's hue and only carries the wood's light and shade across, so the two
              read as one surface and the cover keeps its own colours */
        url('../table.avif') center/cover no-repeat fixed,
        /* 4. the cover itself, unblended and whole */
        url('cover.jpg') center/cover no-repeat fixed,
        #05070a;
    background-blend-mode: normal, normal, soft-light, normal;
    color: var(--cream);
    overflow: hidden;
    touch-action: none;
    -webkit-user-select: none; user-select: none;
}

/* ── Deckades header ─────────────────────────────────────────────────────────── */

#header-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 52px;
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; padding: 0 14px;
    background: linear-gradient(180deg,
        rgba(12, 15, 17, 0.94), rgba(12, 15, 17, 0.68) 80%, rgba(12, 15, 17, 0));
    border-bottom: 1px solid rgba(128, 148, 168, 0.18);
    z-index: 300;
    pointer-events: none;
}
#header-bar > * { pointer-events: auto; }

#header-left  { display: flex; align-items: center; gap: 12px; min-width: 0; }
#header-right { display: flex; align-items: center; gap: 8px; }

/* Holds the game title. Nothing long lives here any more (the turn messages moved down to
   the hand), so it no longer has to be able to ellipsis a full German sentence. */
#header-center {
    position: absolute; left: 50%; top: 0;
    transform: translateX(-50%);
    height: 52px; display: flex; align-items: center;
    max-width: min(50vw, 520px);
    pointer-events: none;
}

/* Status line — positioned under the human's hand by game.js (renderStatusLine). */
#status-msg {
    position: absolute; z-index: 75;
    transform: translate(-50%, -50%);
    padding: 4px 14px; border-radius: 999px;
    font-size: 14.5px; letter-spacing: 0.3px;
    color: rgba(240, 234, 216, 0.92);
    background: rgba(9, 11, 13, 0.7);
    border: 1px solid rgba(128, 148, 168, 0.22);
    white-space: nowrap; pointer-events: none;
    opacity: 0; transition: opacity 0.25s;
}
#status-msg.show { opacity: 1; }
#status-msg.msg-alert { color: rgba(240, 150, 120, 0.98); border-color: rgba(240, 150, 120, 0.35); }
#status-msg.msg-good  { color: rgba(140, 240, 160, 0.98); border-color: rgba(140, 240, 160, 0.35); }

.deckades-logo {
    font-family: var(--display);
    font-weight: 700; font-size: 22px; letter-spacing: 0.12em;
    color: rgba(192, 203, 213, 0.5);
    text-decoration: none; line-height: 1; transition: color 0.2s;
}
.deckades-logo:hover { color: rgba(192, 203, 213, 0.95); }
.deckades-spade {
    color: rgba(128, 148, 168, 0.6);
    font-size: 1.2em; vertical-align: middle;
    display: inline-block; transform: translateY(-2px);
    transition: color 0.2s;
}
.deckades-logo:hover .deckades-spade { color: rgba(169, 189, 209, 1); }
/* The game's title, centred in the header. Display size, because it is now the title of the
   page rather than a tag next to the deckades logo. */
.game-wordmark {
    font-family: var(--display);
    font-size: 22px; letter-spacing: 0.26em; text-transform: uppercase;
    color: var(--gold-bright); opacity: 0.92;
    text-shadow: 0 0 18px rgba(232, 193, 90, 0.28);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── AI indicator ────────────────────────────────────────────────────────────── */

#ai-indicator {
    position: relative;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px 3px 8px; border-radius: 12px;
    font-size: 12px; font-weight: 600; letter-spacing: 0.6px;
    background: rgba(17, 20, 24, 0.65);
    border: 1px solid rgba(128, 148, 168, 0.18);
    color: rgba(192, 203, 213, 0.7);
    white-space: nowrap; cursor: default;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}
#ai-indicator::before {
    content: ''; width: 8px; height: 8px; border-radius: 50%;
    background: rgba(180, 180, 180, 0.5); box-shadow: 0 0 6px rgba(180, 180, 180, 0.4);
}
#ai-indicator.ai-pending::before   { background: rgba(200,180,80,0.85); box-shadow: 0 0 6px rgba(200,180,80,0.55); }
#ai-indicator.ai-onnx              { color: rgba(140,240,160,0.95); border-color: rgba(140,240,160,0.45); }
#ai-indicator.ai-onnx::before      { background: rgba(140,240,160,0.95); box-shadow: 0 0 8px rgba(140,240,160,0.7); }
#ai-indicator.ai-ready             { color: rgba(179, 194, 209, 0.95); border-color: rgba(154, 172, 190, 0.45); }
#ai-indicator.ai-ready::before     { background: rgba(179, 194, 209, 0.95); box-shadow: 0 0 8px rgba(154, 172, 190, 0.65); }
#ai-indicator.ai-heuristic         { color: rgba(220,180,110,0.95); border-color: rgba(220,180,110,0.35); }
#ai-indicator.ai-heuristic::before { background: rgba(220,180,110,0.9); box-shadow: 0 0 6px rgba(220,180,110,0.5); }

#ai-indicator-detail {
    position: absolute; top: calc(100% + 6px); right: 0;
    min-width: 224px; padding: 8px 10px;
    background: var(--panel-bg);
    border: 1px solid rgba(128, 148, 168, 0.32); border-radius: 8px;
    font-size: 11px; font-weight: 500; letter-spacing: 0.3px; text-transform: none;
    color: rgba(220, 225, 231, 0.92); line-height: 1.5;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55);
    display: none; z-index: 10001;
}
#ai-indicator:hover #ai-indicator-detail,
#ai-indicator.tip-open #ai-indicator-detail { display: block; }
#ai-indicator-detail .ai-detail-head { font-size: 9.5px; letter-spacing: 1px;
    opacity: 0.55; margin-bottom: 5px; }
#ai-indicator-detail .ai-detail-row { display: flex; align-items: baseline; gap: 10px; }
#ai-indicator-detail .ai-detail-key { opacity: 0.55; }
#ai-indicator-detail .ai-detail-val { margin-left: auto; text-align: right; font-variant-numeric: tabular-nums; }
#ai-indicator-detail .ai-detail-time { margin-top: 6px; padding-top: 5px;
    border-top: 1px solid rgba(128, 148, 168, 0.18);
    font-size: 9.5px; letter-spacing: 0.5px; opacity: 0.6; }

/* ── Header tool buttons + rules popup ───────────────────────────────────────── */

.hdr-tool-btn {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; background: transparent;
    border: 1px solid rgba(128, 148, 168, 0.45);
    color: rgba(172, 186, 200, 0.85);
    font-size: 16px; padding: 0; cursor: pointer;
    touch-action: manipulation;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
#rules-btn { font-size: 18px; font-weight: 700; }
.hdr-tool-btn:hover, .hdr-tool-btn.active {
    background: rgba(128, 148, 168, 0.2);
    color: rgba(198, 211, 224, 1);
    border-color: rgba(149, 169, 190, 1);
}

#rules-popup {
    position: fixed; right: 14px; top: 62px;
    min-width: 220px; max-width: 320px;
    padding: 14px 36px 14px 14px;
    background: var(--panel-bg);
    border: 1px solid rgba(128, 148, 168, 0.5); border-radius: 10px;
    color: rgba(224, 229, 234, 0.94);
    font-size: 12.5px; letter-spacing: 0.3px; line-height: 1.6;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.6);
    z-index: 301;
}
#rules-popup-close {
    position: absolute; top: 6px; right: 8px;
    background: transparent; border: none;
    color: rgba(156, 169, 183, 0.85); font-size: 13px; cursor: pointer; padding: 4px;
}
#rules-popup-close:hover { color: #fff; }
#rules-popup a { display: inline-block; margin-top: 8px; color: var(--gold-bright); }

/* ── SEO intro (visible only behind the start screen, removed by init) ───────── */

/* Crawlable landing copy — present in the markup, never painted. It used to render until
   init() removed it, which flashed a headline and a paragraph over the table on every load.
   The text still ships in the HTML source for crawlers; it just no longer reaches the
   screen, so there is no flash to remove later. */
#seo-intro {
    display: none;
    position: absolute; top: 70px; left: 50%; transform: translateX(-50%);
    width: min(680px, 90vw); text-align: center; z-index: 1;
    color: rgba(232, 236, 240, 0.72);
}
#seo-intro h1 { font-family: var(--display); font-size: 34px;
    color: var(--gold-bright); margin-bottom: 10px; }
#seo-intro p { font-size: 14px; line-height: 1.7; }

/* ── Game surface ────────────────────────────────────────────────────────────── */

#game { position: fixed; inset: 0; touch-action: none; z-index: 10; display: none; }
#game.on { display: block; }

/* The felt is placed and sized by game.js (boardDims); this is just its look. */
#felt {
    position: absolute;
    border-radius: 22px;
    /* Opaque enough that the cover art behind it never competes with the cards. The table
       is where the game is read; the artwork frames it. */
    background:
        radial-gradient(ellipse at 50% 40%, rgba(83, 97, 112, 0.28), transparent 70%),
        rgba(7, 9, 11, 0.82);
    /* border-color and the glow are set inline from the trump colour (renderFelt); these
       are the no-trump values and the fallback before a round starts. */
    border: 2px solid rgba(143, 160, 179, 0.55);
    box-shadow: inset 0 0 0 1px rgba(143, 160, 179, 0.22),
                inset 0 0 60px rgba(0, 0, 0, 0.6),
                0 0 26px rgba(143, 160, 179, 0.18),
                0 8px 28px rgba(0, 0, 0, 0.5);
    transition: border-color 0.45s ease, box-shadow 0.45s ease;
}
/* Trump plate — pinned inside the felt's top-left by game.js */
#trump-slot { position: absolute; display: flex; align-items: center; gap: 8px; }
.trump-plate {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 6px 10px; border-radius: 10px;
    background: rgba(8, 9, 11, 0.6);
    border: 1px solid rgba(201, 169, 79, 0.35);
}
.trump-label { font-size: 11.5px; letter-spacing: 0.8px;
    color: rgba(232, 236, 240, 0.55); white-space: nowrap; }
.trump-swatch { width: 26px; height: 26px; border-radius: 7px;
    border: 2px solid rgba(255, 255, 255, 0.45); box-shadow: 0 0 12px currentColor; }
.trump-none { font-family: var(--display); font-size: 16px;
    color: rgba(232, 236, 240, 0.75); white-space: nowrap; }

#round-badge {
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: 8px; display: flex; gap: 12px;
    font-size: 12.5px; letter-spacing: 0.6px;
    color: rgba(232, 236, 240, 0.5); white-space: nowrap;
}

/* ── Seat plates ─────────────────────────────────────────────────────────────── */

.seat-plate {
    position: absolute;
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 10px 18px; border-radius: 12px;
    background: rgba(9, 11, 13, 0.72);
    border: 1px solid rgba(128, 148, 168, 0.3);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
    white-space: nowrap; z-index: 40;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.seat-plate.active {
    border-color: var(--gold-bright);
    box-shadow: 0 0 16px rgba(232, 193, 90, 0.45), 0 4px 14px rgba(0, 0, 0, 0.45);
}
.seat-name { font-size: 18.5px; font-weight: 600; color: rgba(240, 234, 216, 0.92); }
.seat-name .dealer-chip {
    display: inline-block; margin-left: 7px; padding: 0 7px;
    border-radius: 7px; font-size: 13.5px; letter-spacing: 0.4px;
    background: rgba(201, 169, 79, 0.25); color: var(--gold-bright);
}
.seat-stats { display: flex; align-items: center; gap: 11px; }
.seat-bid {
    font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums;
    padding: 2px 11px; border-radius: 10px;
    background: rgba(128, 148, 168, 0.22); color: rgba(207, 217, 227, 0.95);
}
.seat-bid.hit  { background: rgba(60, 170, 95, 0.3);  color: #b7f0c6; }
.seat-bid.over { background: rgba(200, 80, 70, 0.3);  color: #f6c0b8; }
/* Augusta, like the rest of the plate. This used to be pinned to a sans because Cormorant's
   "1" and "0" read as "I" and "O" and a score of 10 looked like the letters IO — Augusta's
   digits are distinct enough at 14px that the exception is no longer earned. The card's
   corner pip is the one place it still is; see --numerals. */
.seat-score {
    font-weight: 700; font-size: 20px; letter-spacing: 0.2px;
    color: var(--gold-bright); font-variant-numeric: tabular-nums lining-nums;
}

/* Compact variant for small viewports — a full-size plate is wider than the margin
   between the felt and the screen edge at 640x360. */
.seat-plate.compact { padding: 6px 11px; gap: 4px; }
.seat-plate.compact .seat-name  { font-size: 14.5px; }
.seat-plate.compact .seat-bid   { font-size: 14px; padding: 1px 8px; }
.seat-plate.compact .seat-score { font-size: 16px; }
.seat-plate.compact .dealer-chip { font-size: 11px; margin-left: 5px; }

/* Smallest tier — a phone in landscape. The plate has to fit the strip between the felt and
   the screen edge, so it gives back everything the two tiers above gained. */
.seat-plate.tiny { padding: 4px 8px; gap: 2px; }
.seat-plate.tiny .seat-name  { font-size: 11px; }
.seat-plate.tiny .seat-bid   { font-size: 11px; padding: 1px 6px; }
.seat-plate.tiny .seat-score { font-size: 12.5px; }
.seat-plate.tiny .dealer-chip { font-size: 8.5px; margin-left: 4px; }
.seat-plate.tiny .bid-bubble { font-size: 11px; padding: 1px 8px; }

/* The bid a seat has just announced, floating clear of its plate. It is deliberately NOT
   part of the plate's box: the plate is what the packing search places, and a bubble that
   grew the box would push every plate around for the length of the bidding and then let
   them all snap back. */
.bid-bubble {
    position: absolute; left: 50%; bottom: calc(100% + 8px);
    transform: translateX(-50%);
    padding: 3px 11px; border-radius: 999px;
    background: linear-gradient(180deg, rgba(238, 205, 118, 0.97), rgba(186, 146, 56, 0.97));
    border: 1px solid rgba(255, 236, 180, 0.5);
    color: #191308; font-size: 17px; font-weight: 700; letter-spacing: 0.3px;
    white-space: nowrap; pointer-events: none;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.55);
}
/* Only on the bubble's FIRST render — game.js drops the class afterwards. A plate rebuild
   restarts any animation on it, and one seat bidding rebuilds all of them. */
.bid-bubble.pop { animation: bubble-pop 0.22s cubic-bezier(0.2, 1.4, 0.5, 1); }
/* The tail points back at the plate, so it has to flip with the bubble. */
.bid-bubble::after {
    content: ''; position: absolute; left: 50%; margin-left: -5px; bottom: -5px;
    border-left: 5px solid transparent; border-right: 5px solid transparent;
    border-top: 6px solid rgba(196, 156, 66, 0.97);
}
.bid-bubble.below { bottom: auto; top: calc(100% + 8px); }
.bid-bubble.below::after {
    bottom: auto; top: -5px;
    border-top: none; border-bottom: 6px solid rgba(226, 194, 108, 0.97);
}
.seat-plate.compact .bid-bubble { font-size: 14px; padding: 2px 10px; }
@keyframes bubble-pop {
    from { opacity: 0; transform: translateX(-50%) scale(0.7); }
    to   { opacity: 1; transform: translateX(-50%) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .bid-bubble { animation: none; } }

/* ── Cards ───────────────────────────────────────────────────────────────────── */
/* game.js sets width/height/left/top and font-size (= card width) inline. */

.card {
    position: absolute;
    border-radius: 0.09em;
    background: var(--parchment);
    color: var(--ink);
    box-shadow: 0 0.04em 0.09em rgba(0, 0, 0, 0.5);
    overflow: hidden;
    transition: filter 0.12s, box-shadow 0.12s, transform 0.12s;
    will-change: transform;
}
/* Coloured outer frame + parchment inner panel. */
/* Uploaded artwork, laid over the CSS-drawn card. It is added by game.js and REMOVES ITSELF
   on a load error, so an id whose PNG has not been uploaded yet falls back to the drawn card
   rather than showing a broken image. z-index clears .card::before/::after, which are the
   drawn card's colour band and parchment face. */
/* Once the artwork has actually LOADED, game.js puts .has-art on the card and the drawn
   face is dropped. Without this the pips and big numeral keep rendering under a PNG that
   has its own — invisible while the art covers it, but it shows through the moment a card
   is mid-flip, and it is what made a card briefly look "generic" before settling. */
.card.has-art::before,
.card.has-art::after,
.card.has-art > .pip,
.card.has-art > .face { display: none; }

.card-art {
    position: absolute; inset: 0; z-index: 2;
    width: 100%; height: 100%;
    object-fit: cover;                 /* art is 269x417 (1.550); cover absorbs any drift */
    border-radius: inherit;
    pointer-events: none;
    -webkit-user-drag: none; user-select: none;
}

.card::before {
    content: ''; position: absolute; inset: 0;
    border-radius: inherit;
    background: var(--c);
}
.card::after {
    content: ''; position: absolute; inset: 0.055em;
    border-radius: 0.06em;
    background: linear-gradient(160deg, var(--parchment) 0%, var(--parchment-2) 100%);
    box-shadow: inset 0 0 0 0.012em rgba(42, 28, 12, 0.35);
}
.card.c-y { --c: var(--w-yellow); }
.card.c-r { --c: var(--w-red); }
.card.c-g { --c: var(--w-green); }
.card.c-b { --c: var(--w-blue); }

.card > * { position: relative; z-index: 2; }

/* Corner index. Kept tight to the edge: a 15-card fan overlaps heavily, and the top-left
   pip plus the coloured frame edge are all that stays visible of the covered cards. */
.card .pip {
    position: absolute; text-align: center; line-height: 0.95;
    /* Sans here on purpose, and now stated rather than inherited: at ~9px a display face's
       1/0 are hard to tell from I/O, and in a 20-card fan this pip is the only part of a
       covered card still visible. It used to get sans by inheriting the body font — which
       stopped being true the moment the body moved to Augusta. */
    font-family: var(--numerals);
    font-weight: 700; font-size: 0.2em; letter-spacing: -0.02em;
    font-variant-numeric: lining-nums; color: var(--c);
}
.card .pip.tl { top: 0.38em; left: 0.36em; }
.card .pip.br { bottom: 0.38em; right: 0.36em; transform: rotate(180deg); }

.card .face {
    position: absolute; inset: 0.055em;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.02em;
}
.card .face-num {
    font-family: var(--display); font-weight: 700;
    font-size: 0.56em; line-height: 1; color: var(--c);
    font-variant-numeric: lining-nums;
    text-shadow: 0 0.01em 0 rgba(255, 255, 255, 0.7);
}
.card .face-glyph { font-size: 0.2em; line-height: 1; color: var(--c); opacity: 0.85; }
.card .face-word {
    font-size: 0.10em; letter-spacing: 0.08em;
    color: rgba(42, 28, 12, 0.5);
}

/* Wizard — the strongest card: a glowing serif W. */
.card.is-wizard .face-num { font-size: 0.5em; }
.card.is-wizard::after {
    background:
        radial-gradient(circle at 50% 42%, rgba(255, 255, 255, 0.95), rgba(246, 234, 208, 0) 62%),
        linear-gradient(160deg, var(--parchment) 0%, var(--parchment-2) 100%);
}
/* Jester — the weakest card: muted, no glow. */
.card.is-jester .face-num { font-size: 0.5em; color: rgba(42, 28, 12, 0.62); }
.card.is-jester .face-glyph { color: rgba(42, 28, 12, 0.45); }
.card.is-jester::after { filter: saturate(0.55); }
.card.is-jester .pip { color: rgba(42, 28, 12, 0.55); }

/* Card back — arcane runes, pure CSS. */
.card.back::before { background: linear-gradient(160deg, #363f49, #191e23); }
.card.back::after {
    inset: 0.05em;
    border-radius: 0.06em;
    background:
        repeating-linear-gradient(45deg,  rgba(201,169,79,0.18) 0 0.03em, transparent 0.03em 0.12em),
        repeating-linear-gradient(-45deg, rgba(201,169,79,0.18) 0 0.03em, transparent 0.03em 0.12em),
        radial-gradient(circle at 50% 50%, rgba(232,193,90,0.35), transparent 55%),
        linear-gradient(160deg, #262d35, #13171b);
    box-shadow: inset 0 0 0 0.014em rgba(201, 169, 79, 0.5);
}
.card.back .face, .card.back .pip { display: none; }

/* Interaction states on the human hand */
.card.playable { cursor: pointer; box-shadow: 0 0 0 0.025em var(--gold-bright), 0 0.05em 0.12em rgba(0,0,0,0.55); }
.card.playable:hover { filter: brightness(1.08); }
.card.blocked { filter: grayscale(0.55) brightness(0.62); cursor: not-allowed; }
/* The card that took the trick, and everything it beat. The dim is what makes the glow
   read at a glance — a lit card among four normal ones is a much weaker signal. */
.card.won-glow {
    box-shadow: 0 0 0 0.04em #ffe58a, 0 0 0.42em rgba(255, 229, 138, 0.95);
    transform: scale(1.1); z-index: 80;
}
.card.lost-dim { filter: brightness(0.5) saturate(0.65); }

/* The deck the round is dealt out of — face-down backs stacked at the middle of the felt. */
.deal-deck { z-index: 50; pointer-events: none; box-shadow: 0 0.06em 0.14em rgba(0, 0, 0, 0.6); }

/* The trump card turning over in its corner once it lands. */
.card.flip-in { animation: flip-in 0.4s ease-out; }
@keyframes flip-in {
    from { transform: rotateY(90deg) scale(1.12); }
    to   { transform: rotateY(0deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .card.flip-in { animation: none; } }
.card.flying { z-index: 500; pointer-events: none; }

/* ── Action bar (bids / trump choice) ────────────────────────────────────────── */

/* Sizes itself to its buttons (game.js then centres it on the felt) and carries its own
   panel background, so it reads as a prompt even when it is wider than the felt. */
#action-bar {
    position: absolute; display: none; z-index: 70;
    flex-direction: column; align-items: center; gap: 10px;
    padding: 12px 16px;
    max-width: min(560px, calc(100vw - 24px));
    background: rgba(9, 11, 13, 0.93);
    border: 1px solid rgba(128, 148, 168, 0.42); border-radius: 14px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.6);
}
#action-bar.on { display: flex; }
.act-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.act-label {
    text-align: center; font-size: 12.5px; letter-spacing: 0.5px;
    color: rgba(232, 236, 240, 0.8);
}
/* Second line under the prompt — who leads the first trick. Quieter than the prompt: it is
   context for the decision, not the question being asked. */
.act-note {
    text-align: center; font-size: 11.5px; letter-spacing: 0.3px;
    color: rgba(214, 224, 234, 0.6);
    margin-top: -2px;
}
.bid-btn {
    min-width: 44px; min-height: 44px; padding: 0 12px;
    border-radius: 10px; border: 1px solid rgba(128, 148, 168, 0.55);
    background: linear-gradient(180deg, rgba(57, 67, 78, 0.95), rgba(31, 37, 43, 0.95));
    color: #eaeff4; font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums;
    cursor: pointer; touch-action: manipulation;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 3px 8px rgba(0, 0, 0, 0.4);
    transition: background 0.15s, transform 0.1s;
}
.bid-btn:hover:not(:disabled) { background: linear-gradient(180deg, #6d8398, #3d4a56); transform: translateY(-2px); }
.bid-btn:disabled { opacity: 0.32; cursor: not-allowed; }
/* Late rounds put up to 21 bid buttons on screen at once (round 20, three players); keep
   the 44px tap height and only give back the horizontal padding. */
.bid-btn.tight { min-width: 40px; padding: 0 6px; font-size: 15px; }
.trump-btn {
    width: 52px; height: 52px; border-radius: 12px; padding: 0;
    border: 2px solid rgba(255, 255, 255, 0.35); cursor: pointer;
    touch-action: manipulation; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.45);
    transition: transform 0.1s, box-shadow 0.15s;
}
.trump-btn:hover { transform: translateY(-3px); box-shadow: 0 0 16px currentColor; }

/* ── Toast ───────────────────────────────────────────────────────────────────── */

#toast {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    z-index: 150; padding: 12px 22px; border-radius: 12px;
    background: rgba(11, 13, 16, 0.92); border: 1px solid var(--gold);
    color: var(--cream); font-size: 16px; text-align: center;
    pointer-events: none; max-width: 86vw; white-space: pre-line;
    transition: opacity 0.3s;
}

/* ── Scoreboard panel ────────────────────────────────────────────────────────── */

/* ── Standings, top right ─────────────────────────────────────────────────────── */
/* game.js measures this and treats the rectangle as a wall, so its size may change freely —
   but it must stay a single opaque block, not a floating list. */

#rank-panel {
    position: absolute; top: 60px; right: 10px;
    display: none; z-index: 45;
    padding: 8px 10px 9px; border-radius: 12px;
    background: rgba(9, 11, 13, 0.82);
    border: 1px solid rgba(128, 148, 168, 0.32);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
    white-space: nowrap; pointer-events: none;
}
.rank-title {
    font-size: 12px; letter-spacing: 1px; text-align: center;
    color: rgba(214, 224, 234, 0.55); margin-bottom: 2px;
}
/* Brighter than the title: the title never changes, so this is the line worth reading. */
.rank-round {
    font-size: 12.5px; font-weight: 600; letter-spacing: 0.4px; text-align: center;
    color: rgba(232, 240, 248, 0.82); margin-bottom: 6px;
    font-variant-numeric: tabular-nums;
}
#rank-panel table { border-collapse: collapse; }
#rank-panel th {
    font-size: 10.5px; font-weight: 500; letter-spacing: 0.3px;
    color: rgba(200, 212, 224, 0.5); padding: 0 7px 4px; text-align: left;
}
#rank-panel td { padding: 2px 7px; font-size: 15px; }
#rank-panel tbody tr + tr td { border-top: 1px solid rgba(128, 148, 168, 0.14); }
#rank-panel tr.me td { background: rgba(201, 169, 79, 0.12); }
#rank-panel tr.me .rank-name { color: var(--gold-bright); }
.rank-place { color: rgba(200, 212, 224, 0.5); font-size: 13px; text-align: center; }
.rank-name  { color: rgba(240, 234, 216, 0.92); }
.rank-num   { text-align: right; font-variant-numeric: tabular-nums lining-nums; }
.rank-bid {
    padding: 1px 7px; border-radius: 8px; font-size: 13.5px; font-weight: 700;
    background: rgba(128, 148, 168, 0.2); color: rgba(207, 217, 227, 0.95);
}
.rank-bid.hit  { background: rgba(60, 170, 95, 0.3);  color: #b7f0c6; }
.rank-bid.over { background: rgba(200, 80, 70, 0.3);  color: #f6c0b8; }
.rank-pts { color: var(--gold-bright); font-weight: 700; }

#score-panel {
    position: fixed; top: 60px; right: 12px;
    width: min(400px, 94vw); max-height: calc(100dvh - 76px);
    display: none; flex-direction: column;
    background: var(--panel-bg);
    border: 1px solid rgba(128, 148, 168, 0.42); border-radius: 14px;
    overflow: hidden; box-shadow: 0 10px 34px rgba(0, 0, 0, 0.62);
    z-index: 320;
}
#score-panel.open { display: flex; }
.panel-head {
    display: flex; align-items: center; gap: 8px; padding: 10px 14px;
    border-bottom: 1px solid rgba(128, 148, 168, 0.25); background: rgba(0, 0, 0, 0.25);
}
.panel-title { font-family: var(--display); font-weight: 700;
    color: var(--gold-bright); font-size: 16px; }
.panel-head button { margin-left: auto; background: none; border: none; color: #fff;
    font-size: 16px; cursor: pointer; min-width: 36px; min-height: 36px; touch-action: manipulation; }
#score-body { overflow: auto; -webkit-overflow-scrolling: touch; padding: 10px 12px 14px; }

.score-table { width: 100%; border-collapse: collapse; font-size: 13px;
    font-variant-numeric: tabular-nums; }
.score-table th, .score-table td { padding: 5px 6px; text-align: right; white-space: nowrap; }
.score-table th { color: rgba(232, 236, 240, 0.55); font-weight: 600; font-size: 11px;
    letter-spacing: 0.3px; }
.score-table th:first-child, .score-table td:first-child { text-align: left; }
.score-table tbody td { border-top: 1px solid rgba(128, 148, 168, 0.16); }
.score-table .rnum { color: rgba(232, 236, 240, 0.45); }
.score-table .made { color: #b7f0c6; }
.score-table .miss { color: #f0b6ac; }
.score-table tr.totals td { border-top: 2px solid rgba(201, 169, 79, 0.5);
    font-weight: 800; color: var(--gold-bright); padding-top: 8px; }
.score-empty { opacity: 0.55; font-style: italic; font-size: 13px; padding: 6px 2px; }

/* ── Overlays / modals ───────────────────────────────────────────────────────── */

.overlay {
    position: fixed; inset: 0; z-index: 1100;
    display: grid; place-items: center; padding: 16px;
    background: rgba(7, 8, 10, 0.86);
}
.overlay.hidden { display: none; }
.panel {
    position: relative;
    background: linear-gradient(180deg, #1f2429, #14171b);
    border: 1px solid rgba(128, 148, 168, 0.45); border-radius: 16px;
    padding: 22px 24px; width: min(440px, 94vw);
    max-height: calc(100dvh - 32px); overflow-y: auto;
    text-align: center; box-shadow: 0 12px 44px rgba(0, 0, 0, 0.7);
}
.panel h2 { font-family: var(--display); font-weight: 700;
    font-size: 24px; color: var(--gold-bright); margin-bottom: 12px; }
.primary-btn {
    margin-top: 16px; width: 100%; min-height: 48px;
    border: 1px solid var(--violet-soft); border-radius: 10px;
    background: var(--violet); color: #fff;
    font-size: 16px; font-weight: 700; cursor: pointer; touch-action: manipulation;
    transition: background 0.15s;
}
.primary-btn:hover { background: #6d8398; }
.over-line { font-size: 15px; line-height: 1.6; margin-bottom: 10px; }

/* ── Start screen ────────────────────────────────────────────────────────────── */

#start-screen {
    position: fixed; inset: 0; z-index: 1200;
    display: flex; align-items: center; justify-content: center;
    /* The cover, whole and unzoomed — this is the one screen where its wordmark and rune
       glyphs are the subject rather than a watermark. Still under the same near-black wash
       as the table, so entering the game is a continuous surface, not a scene change. */
    background:
        linear-gradient(rgba(6, 7, 9, 0.82), rgba(6, 7, 9, 0.90)),
        url('cover.jpg') center/cover no-repeat fixed,
        #06070a;
    backdrop-filter: blur(2px);
}
/* Fixed width — NOT min-width — so a language switch never resizes the card. */
.start-card {
    position: relative;
    width: 620px; max-width: 92vw;
    padding: 26px 30px 62px;
    background: rgba(17, 20, 22, 0.97);
    border: 1px solid var(--violet); border-radius: 14px;
    box-shadow: 0 0 30px rgba(115, 139, 164, 0.35), 0 10px 40px rgba(0, 0, 0, 0.8);
    text-align: center;
    transform-origin: center center;
}
.start-title {
    font: 700 42px var(--display); letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #e5ebf1; text-shadow: 0 0 18px rgba(137, 156, 175, 0.7);
    margin-bottom: 4px; white-space: nowrap;
}
.start-subtitle {
    font-size: 13px; color: #b2bac1; margin-bottom: 20px; letter-spacing: 0.3px;
    line-height: 1.5;
}

.start-columns     { display: flex; gap: 26px; align-items: stretch; text-align: left; }
.start-col         { display: flex; flex-direction: column; }
.start-col-left    { flex: 0 0 50%; gap: 14px; }
.start-col-right   { flex: 1; gap: 10px; justify-content: center; }
.start-col-divider { width: 1px; align-self: stretch; background: rgba(137, 156, 175, 0.35); }

.start-field       { display: flex; flex-direction: column; gap: 5px; }
.start-field label,
.start-field-label { color: #b2bac1; font: 600 13px var(--display); letter-spacing: 0.03em;
    white-space: nowrap; }
.start-field select {
    width: 100%; min-height: 40px; padding: 8px;
    background: #1a1d20; color: #eee;
    border: 1px solid #3f454b; border-radius: 6px;
    font: 14px var(--display); cursor: pointer;
}
.start-check {
    display: flex; align-items: center; gap: 10px; min-height: 44px;
    color: #d4dae0; font: 600 14px var(--display); cursor: pointer;
    touch-action: manipulation;
}
.start-check input[type=checkbox] {
    width: 22px; height: 22px; accent-color: var(--violet-soft); cursor: pointer; flex: none;
}
.start-sub-hint { color: #838b93; font: 400 12.5px var(--display); line-height: 1.45;
    margin-top: -8px; min-height: 0; }

.start-speed input[type=range] { width: 100%; height: 24px; cursor: pointer; accent-color: var(--violet-soft); }
.start-speed-val { color: #e5ebf1; font: 400 13px var(--display); min-height: 16px; }

.start-play {
    width: 100%; min-height: 48px; padding: 12px 30px;
    font: 700 18px var(--display); color: #fff;
    background: var(--violet); border: 1px solid var(--violet-soft); border-radius: 8px;
    cursor: pointer; touch-action: manipulation;
    transition: background 0.15s, opacity 0.15s;
}
.start-play:hover:not(:disabled) { background: #6d8398; }
.start-play:disabled { opacity: 0.35; cursor: not-allowed; }
.start-secondary { background: transparent; border-color: #69747f; color: #d4dae0;
    font-weight: 600; font-size: 14px; }
.start-secondary:hover:not(:disabled) { background: rgba(109, 131, 152, 0.25); }

.start-hint { margin-top: 12px; color: #838b93; font: 400 13px var(--display); min-height: 16px; }

/* Form controls do not inherit the page font on their own — without this the selects, the
   checkbox label and the Play button fall back to the UA's sans and the start screen is the
   one place in the game that is not Augusta. */
button, select, input, a { font-family: inherit; }

/* TOP-right, not bottom: the language flag is chrome, and chrome belongs with the other
   chrome at the top of the card rather than competing with the launch buttons. */
.start-lang-corner { position: absolute; top: 14px; right: 18px;
                   display: flex; align-items: center; gap: 10px; z-index: 5; }
.start-lang-wrap { position: relative; }
.start-lang-btn  { width: 44px; height: 32px; padding: 0; border: 1px solid var(--violet);
                   border-radius: 5px; background: rgba(17, 20, 22, 0.9); cursor: pointer;
                   overflow: hidden; display: block; touch-action: manipulation;
                   transition: border-color 0.15s, box-shadow 0.15s; }
.start-lang-btn:hover { border-color: var(--violet-soft); box-shadow: 0 0 10px rgba(137, 156, 175, 0.5); }
/* Opens DOWNWARD now that the flag sits at the top of the card — opening upward from a
   top-anchored button would put the picker off the card entirely. */
.start-lang-picker {
    position: absolute; top: calc(100% + 6px); right: 0;
    display: flex; gap: 8px; padding: 10px;
    background: rgba(17, 20, 22, 0.98); border: 1px solid var(--violet); border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6); z-index: 10;
}
.start-lang-opt  { width: 44px; height: 32px; padding: 0; border: 2px solid #3f454b;
                   border-radius: 5px; background: rgba(17, 20, 22, 0.9); cursor: pointer;
                   overflow: hidden; display: block; touch-action: manipulation; }
.start-lang-opt.on { border-color: var(--violet-soft); }

/* Phones / short landscape: stack the two columns, drop the divider. */
@media (max-width: 620px), (max-height: 540px) {
    .start-card       { width: 420px; padding: 20px 20px 62px; }
    .start-columns    { flex-direction: column; gap: 14px; }
    .start-col-divider{ display: none; }
    .start-col-left   { flex: none; }
    .start-title      { font-size: 32px; }
    .start-subtitle   { margin-bottom: 14px; }
}
@media (max-height: 560px) {
    #seo-intro p { display: none; }
}

/* ── Multiplayer lobby ────────────────────────────────────────────────────────
   Reuses the game's .overlay / .panel / .primary-btn chrome; only the pieces the
   lobby adds are defined here. Controls are >=44px so the code input and the seat
   list stay usable on a phone. */
.mp-panel { max-width: 420px; }
.mp-blurb { font-size: 13.5px; line-height: 1.55; color: rgba(232, 236, 240, 0.7);
            margin-bottom: 10px; }
.mp-seats-note { font-size: 12.5px; color: rgba(232, 236, 240, 0.5); margin-bottom: 12px; }
.mp-field { display: flex; flex-direction: column; gap: 4px; text-align: left;
            margin: 10px 0; font-size: 13px; color: rgba(232, 236, 240, 0.75); }
.mp-field input {
    min-height: 44px; padding: 8px 12px; border-radius: 8px;
    border: 1px solid var(--violet); background: rgba(9, 11, 13, 0.85);
    color: var(--cream); font: 400 16px var(--display);   /* 16px: iOS zooms below it */
}
.mp-field input:focus { outline: none; border-color: var(--violet-soft); }
#mp-code { letter-spacing: 0.22em; text-transform: uppercase; text-align: center; }
.mp-or { margin: 12px 0 4px; font-size: 12px; letter-spacing: 1px;
         color: rgba(232, 236, 240, 0.4); }
.mp-code {
    font-family: var(--numerals); font-size: 34px; font-weight: 700;
    letter-spacing: 0.28em; text-indent: 0.28em;      /* balance the trailing space */
    color: var(--gold-bright); margin: 10px 0 6px;
    text-shadow: 0 0 20px rgba(232, 193, 90, 0.3);
}
.mp-copy { margin-bottom: 12px; }
.mp-seats { width: 100%; margin: 8px 0 4px; }
.mp-seats td { padding: 7px 10px; font-size: 14px; }
.mp-seats tr.me td { color: var(--gold-bright); }
.mp-ai { opacity: 0.6; font-style: italic; }
.mp-err { min-height: 20px; font-size: 13px; color: rgba(240, 150, 120, 0.95);
          margin: 8px 0; }
