/*
 * Gonga web look. Theme tokens are ported from scenes/GongaTheme.cs and scenes/CardPainter.cs.
 *
 * Scale: the table is 720 design px wide and at least 1280 tall. --u is one design pixel in real pixels:
 *   the viewport width / 720 (cards as big as the phone allows), but never more than
 *   810 px / 720 (a phone-width column on wide windows) and never so much that a 1280-tall stage
 *   would not fit the viewport height (a wide, short desktop window gets a narrower centred column).
 *   The stage is as tall as the usable viewport, so on a taller screen than 9:16 it is taller than 1280
 *   design px and the extra height goes to the Melds area (flex: 1).
 * Every size below is calc(N * var(--u)); no JavaScript.
 */
:root {
    /* The usable viewport: the full window minus the safe-area insets (notch, rounded corners, home bar);
       viewport-fit=cover in index.html makes the page extend under them, body padding keeps the stage out. */
    --sw: calc(100vw - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
    --sh: calc(100vh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    --u: min(var(--sw) / 720, 810px / 720, var(--sh) / 1280);
    --felt: #1e5a3a;
    --ink: #f4f1e8;
    --error: #ff8a65;
    --gold: #f2c94c;
    --btn: #2f4858;
    --btn-hover: #3d6078;
    --btn-pressed: #b8860b;
    --btn-disabled: #2a3238;
    --plate: rgba(0, 0, 0, .35);
    --plate-active: rgba(0, 0, 0, .5);
    --plate-border: rgba(255, 255, 255, .15);
    --badge: #2f4858;
    --card-face: #fbfaf5;
    --card-red: #c8102e;
    --card-black: #1a1a1f;
    --suit-clubs: var(--card-black);
    --suit-spades: var(--card-black);
    --suit-diamonds: var(--card-red);
    --suit-hearts: var(--card-red);
    --card-joker: #6a1b9a;
    --card-edge: #3a3a40;
    --card-back: #1d3f7a;
    --card-back-inner: #2d5aa8;
}
@supports (height: 100dvh) {
    :root {
        --sh: calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    }
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
html { touch-action: manipulation; } /* no double-tap zoom; pinch zoom stays available */
body {
    background: var(--felt);
    color: var(--ink);
    font-family: "Open Sans", "Noto Sans", "DejaVu Sans", system-ui, sans-serif;
    font-size: calc(18 * var(--u));
    overflow-x: hidden;
    padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    -webkit-tap-highlight-color: transparent;
    overscroll-behavior: none;
    display: flex;
    justify-content: center;
    align-items: center;
    -webkit-text-size-adjust: 100%;
}
#app { width: 100%; display: flex; justify-content: center; }
#blazor-error-ui { display: none; }
/* Update bar (index.html script): above everything, including modals, at the top of the stage column. */
#update-bar {
    position: fixed; z-index: 1000; left: 50%; transform: translateX(-50%);
    bottom: calc(env(safe-area-inset-bottom, 0px) + 12 * var(--u));
    width: calc(696 * var(--u)); display: flex; align-items: center; gap: calc(12 * var(--u));
    padding: calc(8 * var(--u)) calc(8 * var(--u)) calc(8 * var(--u)) calc(18 * var(--u));
    background: var(--btn); color: var(--ink); border: calc(2 * var(--u)) solid var(--gold); border-radius: calc(8 * var(--u));
    box-shadow: 0 calc(4 * var(--u)) calc(16 * var(--u)) rgba(0, 0, 0, .5);
}
#update-bar[hidden] { display: none; }
#update-bar span { flex: 1; text-align: left; }
#update-bar .update-close {
    width: calc(44 * var(--u)); height: calc(44 * var(--u)); padding: 0; border: none; background: none;
    color: var(--ink); font: inherit; font-size: calc(22 * var(--u)); cursor: pointer;
}

.stage {
    width: calc(720 * var(--u));
    height: var(--sh); /* never below 1280 * --u: --u is capped by --sh / 1280 */
    flex: none;
    overflow: hidden;
}

/* Start screen */
.start { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(20 * var(--u)); text-align: center; }
.title { margin: 0; font-size: calc(64 * var(--u)); font-weight: 400; }
.tagline { margin: 0; }
.start-btn { min-width: calc(220 * var(--u)); min-height: calc(64 * var(--u)); font-size: calc(24 * var(--u)); }
.continue-block { display: flex; flex-direction: column; align-items: center; gap: calc(8 * var(--u)); }
.save-note { margin: 0; opacity: 0.8; }

/* Start screen opponent and Elimination limit choices */
.plate.start-plate { width: calc(560 * var(--u)); box-sizing: border-box; align-items: center; gap: calc(14 * var(--u)); padding: calc(18 * var(--u)) calc(28 * var(--u)); }
.choices { display: flex; gap: calc(16 * var(--u)); }
.choice { width: calc(80 * var(--u)); height: calc(80 * var(--u)); font-size: calc(32 * var(--u)); padding: 0; }
.choice.on { background: var(--btn-hover); color: #fff; box-shadow: inset 0 0 0 calc(3 * var(--u)) var(--gold); }
.btn.primary { background: var(--gold); color: var(--card-black); font-weight: 700; }
.btn.primary:hover:not(:disabled) { background: #ffdb6e; color: var(--card-black); }
.btn.primary:active:not(:disabled) { background: var(--btn-pressed); color: #fff; }
.btn.primary:disabled { background: var(--btn-disabled); color: rgba(244, 241, 232, .45); }
.tabs { display: flex; gap: calc(8 * var(--u)); width: calc(560 * var(--u)); }
.tab { flex: 1; font-size: calc(22 * var(--u)); background: transparent; box-shadow: inset 0 0 0 calc(1 * var(--u)) var(--plate-border); }
.tab.on { background: var(--plate-active); color: #fff; box-shadow: inset 0 calc(-3 * var(--u)) 0 var(--gold); }
.room-hint { margin: 0; opacity: .85; font-size: calc(18 * var(--u)); }
#limit-caption { margin-top: calc(10 * var(--u)); }

/* Start screen: Play with friends (name, Host a room, Room code + Join) */
.room-plate { width: calc(560 * var(--u)); }
.room-row { display: flex; gap: calc(12 * var(--u)); justify-content: center; width: 100%; }
.room-btn { min-width: calc(200 * var(--u)); font-size: calc(20 * var(--u)); }
.field {
    font: inherit; font-size: calc(22 * var(--u)); color: var(--card-black); background: var(--card-face);
    border: 0; border-radius: calc(6 * var(--u)); padding: calc(10 * var(--u)) calc(14 * var(--u));
    min-height: calc(48 * var(--u)); width: calc(320 * var(--u)); text-align: center;
}
.field:disabled { opacity: .6; }
.code-field { width: calc(200 * var(--u)); text-transform: uppercase; letter-spacing: .15em; }
.room-note { margin: 0; color: var(--gold); max-width: calc(500 * var(--u)); }

/* Lobby: the Room code, link, QR code and Share; the seats; the settings; Start */
.lobby { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(18 * var(--u)); text-align: center; padding: calc(24 * var(--u)); }
.lobby-top { display: flex; gap: calc(24 * var(--u)); align-items: center; }
.qr { width: calc(220 * var(--u)); height: calc(220 * var(--u)); flex: none; border-radius: calc(6 * var(--u)); }
.lobby-code-block { display: flex; flex-direction: column; align-items: center; gap: calc(8 * var(--u)); width: calc(330 * var(--u)); }
.lobby-caption { opacity: .85; }
.lobby-code { font-size: calc(56 * var(--u)); letter-spacing: .12em; font-weight: 600; }
.lobby-link { font-size: calc(15 * var(--u)); opacity: .8; overflow-wrap: anywhere; user-select: all; }
.plate.lobby-plate { width: calc(560 * var(--u)); align-items: stretch; gap: calc(10 * var(--u)); padding: calc(14 * var(--u)) calc(20 * var(--u)); }
.lobby-plate .room-btn { align-self: center; }
.lobby-seats { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: calc(6 * var(--u)); }
.lobby-seat { display: flex; align-items: center; gap: calc(12 * var(--u)); min-height: calc(48 * var(--u)); padding: 0 calc(10 * var(--u)); border-radius: calc(6 * var(--u)); background: rgba(255, 255, 255, .06); }
.lobby-seat.you { outline: calc(2 * var(--u)) solid var(--gold); }
.seat-name { flex: 1; text-align: left; font-size: calc(22 * var(--u)); }
.seat-tag { opacity: .75; font-size: calc(16 * var(--u)); }
.seat-remove { min-height: calc(40 * var(--u)); width: calc(44 * var(--u)); padding: 0; }
.timer-choice { font-size: calc(22 * var(--u)); }
.lobby-note { margin: 0; }

/* Buttons */
.btn {
    font: inherit; color: var(--ink); background: var(--btn); border: 0;
    border-radius: calc(6 * var(--u)); padding: calc(12 * var(--u)) calc(16 * var(--u));
    min-height: calc(44 * var(--u)); cursor: pointer;
}
.btn:hover:not(:disabled) { background: var(--btn-hover); color: #fff; }
.btn:active:not(:disabled) { background: var(--btn-pressed); color: #fff; }
.btn:disabled { background: var(--btn-disabled); color: rgba(244, 241, 232, .45); cursor: default; }
/* Keyboard focus only (not :focus, so taps and clicks show no ring). */
button:focus-visible, input:focus-visible, select:focus-visible, a:focus-visible, [tabindex]:focus-visible {
    outline: calc(3 * var(--u)) solid var(--gold); outline-offset: calc(2 * var(--u));
}

/* Table, top to bottom as in scenes/Table.cs (root VBox separation 8) */
.table { height: 100%; display: flex; flex-direction: column; gap: calc(8 * var(--u)); padding: calc(8 * var(--u)) calc(12 * var(--u)); text-align: center; }
.header-row { min-height: calc(44 * var(--u)); display: flex; align-items: center; gap: calc(8 * var(--u)); }
.round-header { flex: 1; min-width: 0; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The ☰ button at the left; a same-width spacer at the right keeps the Round header centred. */
.menu-btn, .menu-spacer { flex: none; width: calc(56 * var(--u)); }
.menu-btn { padding: 0; font-size: calc(26 * var(--u)); line-height: 1; }
/* The ☰ menu: a small plate dropdown under the button, above a light dim that swallows taps (a tap on it closes the menu). */
.modal-dim.menu-dim { background: rgba(0, 0, 0, .3); }
.plate.menu { position: absolute; top: calc(56 * var(--u)); left: calc(12 * var(--u)); z-index: 11; display: flex; flex-direction: column; gap: calc(6 * var(--u)); padding: calc(8 * var(--u)); background: #14382a; min-width: calc(180 * var(--u)); }
.menu-item { text-align: left; }
.status-row { display: flex; align-items: center; gap: calc(8 * var(--u)); }
.status-row .status { flex: 1; } /* only in the top row: the own prompt beside the Hand must not grow, or it pushes the piles away from the Hand (#92) */
.ai-log { height: calc(68 * var(--u)); font-size: calc(18 * var(--u)); display: flex; align-items: center; justify-content: center; text-align: center; white-space: pre-line; line-height: 1.25; overflow: hidden; }
.seat-top { display: flex; justify-content: center; gap: calc(8 * var(--u)); }
.middle { flex: 1; min-height: 0; display: flex; gap: calc(8 * var(--u)); }
.centre { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.seat-side { flex: none; width: calc(118 * var(--u)); display: flex; flex-direction: column; justify-content: center; gap: calc(8 * var(--u)); }
.seat-side .plate { width: 100%; }
.seat-side .seat-cards { flex-direction: column; gap: calc(4 * var(--u)); }
.melds { flex: 1; min-height: calc(122 * var(--u)); overflow-y: auto; display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start; gap: calc(8 * var(--u)); }
.piles { display: flex; justify-content: center; gap: calc(32 * var(--u)); }
/* Turn-start emphasis: while the human is to draw, the piles are larger and glowing. Size and glow ease in and out. The room
   they need comes out of the Melds area's height (it scrolls), and the padding keeps the glow inside the piles' own box so it
   never lies over a Meld card (#92). */
.piles.large { padding-top: calc(20 * var(--u)); }
.piles .card-slot { transition: width .3s ease-out, height .3s ease-out, filter .3s ease-out; }
.piles.large .card-slot { filter: drop-shadow(0 0 calc(10 * var(--u)) rgba(242, 201, 76, .9)); }
.message { min-height: calc(21 * var(--u)); color: var(--error); }
.own-prompt { color: var(--gold); font-weight: 700; min-height: calc(26 * var(--u)); } /* the Turn instruction, beside the Hand (TableModel.StatusIsOwn) */
.total-line { min-height: calc(21 * var(--u)); color: var(--ink); }
.total-line.over { color: var(--error); font-weight: 700; }
.total-line.amber { font-weight: 700; }
.meter { height: calc(5 * var(--u)); margin-bottom: calc(3 * var(--u)); border-radius: calc(3 * var(--u)); background: rgba(0, 0, 0, .25); overflow: hidden; }
.meter-fill { display: block; height: 100%; background: #4caf7a; border-radius: inherit; transition: width .3s; }
.total-line.amber .meter-fill { background: #f0a020; }
.total-line.over .meter-fill { background: var(--error); }
@media (prefers-reduced-motion: reduce) { .meter-fill { transition: none; } }
/* The fanned Hand (HandFan): each slot tilts by --angle degrees about its bottom centre and sits --drop lower along an arc.
   The row is 148 tall: 2 of room above (HandFan.RoomAbove: a slightly tilted card's inner corner), the 114 slot (TableModel.HandCardHeight + HandLift) and 32 below (HandFan.RoomBelow)
   for the outer cards' drop and tilted bottom corners. The tilt uses the rotate property, the drag spread translate and the
   settle animation transform, so none of them overrides another. */
.hand { display: flex; justify-content: center; align-items: flex-end; height: calc(148 * var(--u)); padding: calc(2 * var(--u)) 0 calc(32 * var(--u)); }
/* The slot is 114 tall: 100 for the card and 14 of lift room. Only .hand-hit (the drawn card) takes taps; the room above an
   unselected card is the pointer-events:none wrapper. A selected card's hit area lifts with it, along the slot's tilt. */
.hand-card {
    height: calc(114 * var(--u)); display: flex; align-items: flex-end; pointer-events: none;
    position: relative; top: calc(var(--drop, 0) * var(--u)); rotate: calc(var(--angle, 0) * 1deg); transform-origin: 50% 100%;
}
.hand-hit { pointer-events: none; transition: transform .15s ease-out; }
.hand-hit.tappable { pointer-events: auto; cursor: pointer; }
.hand-hit.grab { pointer-events: auto; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
/* Dragging (wwwroot/js/drag.js): a ghost of the carried cards follows the pointer, the originals fade; legal drop targets are
   lit by the model (.drop-legal on the piles and the Melds area, .legal on Melds and Joker cards), the one under the pointer
   is marked by the script (data-hover). Over the Hand the cards either side of the gap spread apart (data-spread); after a
   move the moved cards stay hidden while the ghost settles onto them (data-settling). */
.hand-hit[data-carried] { opacity: .3; }
.drag-ghost { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; display: flex; filter: drop-shadow(0 6px 8px rgba(0,0,0,.5)); }
.drag-ghost .ghost-card + .ghost-card { margin-left: calc(-36 * var(--u)); }
.hand-card { transition: translate .12s ease-out; }
.hand-card[data-spread="left"] { translate: calc(-16 * var(--u)) 0; }
.hand-card[data-spread="right"] { translate: calc(16 * var(--u)) 0; }
.hand-card[data-settling] { animation: none !important; }
.hand-card[data-settling] .hand-hit { opacity: 0; }
.pile.drop-legal { outline: calc(3 * var(--u)) solid #7ee081; outline-offset: calc(2 * var(--u)); border-radius: calc(8 * var(--u)); }
.melds { position: relative; border-radius: calc(8 * var(--u)); }
.melds.drop-legal { outline: calc(3 * var(--u)) solid #7ee081; outline-offset: calc(-3 * var(--u)); background: rgba(126, 224, 129, .12); }
.melds-zone { width: 100%; min-height: calc(90 * var(--u)); display: flex; align-items: center; justify-content: center; text-align: center; box-sizing: border-box; border: calc(2 * var(--u)) dashed rgba(255, 255, 255, .25); border-radius: calc(8 * var(--u)); color: rgba(255, 255, 255, .5); pointer-events: none; }
.message.hint { color: #cfe8cf; } /* the first-Turn discard hint borrows the message line (TableModel.FirstDiscardHint) */
.melds-preview { width: 100%; text-align: center; color: #7ee081; padding: calc(4 * var(--u)) 0; }
[data-drop][data-hover].legal, [data-drop][data-hover].drop-legal { outline-color: var(--gold); }
/* Selected: a stronger lift and a gold outline. The new card (just drawn): a gold dot at its top left with a pulse (static under reduced motion). */
.hand-hit.selected { transform: translateY(calc(-22 * var(--u))); }
.hand-hit.selected .card { outline: calc(3 * var(--u)) solid var(--gold); outline-offset: calc(-1 * var(--u)); }
@keyframes new-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(242, 201, 76, .8); } 50% { box-shadow: 0 0 0 calc(7 * var(--u)) rgba(242, 201, 76, 0); } }
.hand-hit.new-card { position: relative; }
/* The new-card dot (#91): centred on the card's top edge, clear of the corner index and a Joker's top label; at the tightest
   fan spacing (56 of 70 px showing) the next card still leaves it in view. */
.hand-hit.new-card::after {
    content: ""; position: absolute; top: calc(-8 * var(--u)); left: calc(50% - 7 * var(--u)); width: calc(14 * var(--u)); height: calc(14 * var(--u));
    border-radius: 50%; background: var(--gold); border: calc(2 * var(--u)) solid #14382a; pointer-events: none; animation: new-pulse 1.2s ease-in-out infinite;
}
.pile.tappable { cursor: pointer; }
.pile:not(.tappable) { pointer-events: none; }
.flash { background-color: color-mix(in srgb, #ff5a4d calc(var(--flash, 0) * 70%), transparent); }
.pile.flash { border-radius: calc(8 * var(--u)); }
.btn.flash { background-color: color-mix(in srgb, #ff5a4d calc(var(--flash, 0) * 70%), var(--btn)); }
.hand-card + .hand-card { margin-left: calc(var(--gap) * var(--u)); }
.buttons { display: flex; flex-wrap: nowrap; justify-content: center; gap: calc(8 * var(--u)); }
/* One fixed-height row: the long Lay down label gets the width the other buttons leave and is cut with an ellipsis (full text in the title). */
.buttons .btn { flex: none; white-space: nowrap; padding-left: calc(10 * var(--u)); padding-right: calc(10 * var(--u)); } /* six buttons share the 696 px row */
.buttons #btn-LayDown { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* Opponent plate, fan and count badge */
.plate {
    background: var(--plate); border: calc(1 * var(--u)) solid var(--plate-border); border-radius: calc(8 * var(--u));
    padding: calc(5 * var(--u)) calc(6 * var(--u)); display: flex; flex-direction: column; gap: calc(4 * var(--u));
}
.plate.active { background: var(--plate-active); border: calc(3 * var(--u)) solid var(--gold); box-shadow: 0 0 calc(12 * var(--u)) rgba(242, 201, 76, .5); }
.plate.greyed { opacity: .5; }
/* The seat's own colour (SeatColours, set as --seat): a bar inset along the top of its plate, kept apart from an active plate's gold border. */
.plate[style*="--seat"]::before {
    content: ""; position: absolute; left: calc(4 * var(--u)); right: calc(4 * var(--u)); top: calc(3 * var(--u)); height: calc(5 * var(--u));
    background: var(--seat); border-radius: calc(3 * var(--u)); pointer-events: none;
}
.plate[style*="--seat"] { padding-top: calc(11 * var(--u)); }
.seat-dot { display: inline-block; width: calc(12 * var(--u)); height: calc(12 * var(--u)); margin-right: calc(8 * var(--u)); border-radius: 50%; background: var(--seat); vertical-align: middle; }
/* Thinking marker: three pulsing dots after the name while the active seat is between its draw and its discard (NamePlate.Thinking). */
.plate-countdown { color: var(--gold); font-weight: 700; font-variant-numeric: tabular-nums; font-size: calc(18 * var(--u)); }
.plate-offline { color: var(--error); font-style: italic; font-size: calc(16 * var(--u)); }
.own-countdown { margin-left: calc(12 * var(--u)); font-weight: 700; font-variant-numeric: tabular-nums; }
.own-countdown.urgent { color: var(--error); }
.room-banner { position: absolute; top: calc(96 * var(--u)); left: 50%; transform: translateX(-50%); z-index: 40; white-space: nowrap; padding: calc(6 * var(--u)) calc(14 * var(--u)); border-radius: calc(8 * var(--u));
    background: var(--plate-active); border: calc(2 * var(--u)) solid var(--gold); color: var(--ink); text-align: center; }
.thinking-marker { display: inline-flex; gap: calc(3 * var(--u)); margin-left: calc(6 * var(--u)); vertical-align: middle; }
.thinking-marker i { width: calc(5 * var(--u)); height: calc(5 * var(--u)); border-radius: 50%; background: var(--gold); animation: thinking 1s ease-in-out infinite; }
.thinking-marker i:nth-child(2) { animation-delay: .2s; }
.thinking-marker i:nth-child(3) { animation-delay: .4s; }
@keyframes thinking { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
.seat-cards { display: flex; justify-content: center; align-items: center; gap: calc(6 * var(--u)); }
.plate-total { font-variant-numeric: tabular-nums; font-weight: 700; font-size: calc(18 * var(--u)); }
.dealer-chip {
    display: inline-block; margin-left: calc(6 * var(--u)); min-width: calc(18 * var(--u)); padding: 0 calc(4 * var(--u)); text-align: center;
    border-radius: calc(9 * var(--u)); background: var(--gold); color: #222; font-size: calc(14 * var(--u)); font-weight: 700; line-height: 1.3;
}
.badge {
    background: var(--badge); border: calc(1 * var(--u)) solid var(--ink); border-radius: calc(8 * var(--u));
    padding: calc(4 * var(--u)) calc(8 * var(--u)); min-width: calc(32 * var(--u));
}

/* 4 and 5 opponents (SeatLayout.Shape: Arc): every plate in one band under the AI log, in turn order, spread from x=16 to 704;
 * each .arc-slot sits its ArcDrop lower, so the outer plates read as an arc around the table. No side columns: the Melds area
 * takes the full width. Plates have a fixed width (the name is cut with an ellipsis) and every plate size is times --ps
 * (1, or 0.8 from 5 opponents up); Meld cards are smaller (sized in TableView). */
.arc { display: flex; justify-content: space-between; align-items: flex-start; padding: 0 calc(4 * var(--u)); }
.arc-slot { flex: none; }
.arc .plate {
    width: calc(160 * var(--ps) * var(--u)); font-size: calc(18 * var(--ps) * var(--u)); border-radius: calc(8 * var(--ps) * var(--u));
    padding: calc(5 * var(--ps) * var(--u)) calc(6 * var(--ps) * var(--u)); gap: calc(4 * var(--ps) * var(--u));
}
.arc .plate.active { border-width: calc(3 * var(--ps) * var(--u)); }
.arc .plate[style*="--seat"] { padding-top: calc(11 * var(--ps) * var(--u)); }
.arc .seat-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.arc .seat-cards { gap: calc(6 * var(--ps) * var(--u)); }
.arc .plate-total { font-size: calc(18 * var(--ps) * var(--u)); }
.arc .dealer-chip { font-size: calc(14 * var(--ps) * var(--u)); border-radius: calc(9 * var(--ps) * var(--u)); }
.arc .badge {
    border-radius: calc(8 * var(--ps) * var(--u)); padding: calc(4 * var(--ps) * var(--u)) calc(8 * var(--ps) * var(--u));
    min-width: calc(32 * var(--ps) * var(--u));
}

/* Cards: the slot holds the layout size; the drawn card may shift and tilt inside it (jitter). */
.card-slot { position: relative; width: calc(var(--w) * var(--u)); height: calc(var(--h) * var(--u)); flex: none; }
.card {
    position: absolute; inset: 0; border-radius: calc(6 * var(--u)); border: calc(1 * var(--u)) solid var(--card-edge);
    transform: translate(calc(var(--dx, 0) * var(--u)), calc(var(--dy, 0) * var(--u))) rotate(calc(var(--rot, 0) * 1deg));
    overflow: hidden; line-height: 1; user-select: none;
}
.card.face { background: var(--card-face); }
.card.under::after { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, .12); }
/* Suit ink: red and black by default; .four-colour (App.razor, the start screen's setting) turns clubs green and diamonds blue.
 * Darker than the player colours (#66) should be, and all above 4.5:1 on --card-face.
 * Set on body too: the drag ghost and the flight copies are appended to body, outside the wrapper. */
.four-colour, body:has(.four-colour) { --suit-clubs: #17703a; --suit-diamonds: #1c58b8; }
.card.clubs, .stands.clubs { color: var(--suit-clubs); }
.card.spades, .stands.spades { color: var(--suit-spades); }
.card.diamonds, .stands.diamonds { color: var(--suit-diamonds); }
.card.hearts, .stands.hearts { color: var(--suit-hearts); }
.card.joker { color: var(--card-joker); }
.card.back { background: var(--card-back); color: #fff; }
.card.back::before { content: ""; position: absolute; inset: calc(5 * var(--u)); border: calc(1.5 * var(--u)) solid var(--card-back-inner); }
.card.empty { background: transparent; border: calc(2 * var(--u)) solid rgba(255, 255, 255, .45); color: rgba(255, 255, 255, .8); border-radius: 0; }
.diamond {
    position: absolute; left: 50%; top: 50%; width: calc(min(var(--w), var(--h)) * .56 * var(--u)); aspect-ratio: 1;
    transform: translate(-50%, -50%); background: var(--card-back-inner); clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
.label { position: absolute; left: 0; right: 0; text-align: center; }
.label.top { top: calc(5 * var(--u)); font-size: calc(max(11, var(--h) * .12) * var(--u)); }
.card.joker .label.top { font-size: calc(max(11, var(--h) * .15) * var(--u)); }
.label.mid { top: 50%; transform: translateY(-50%); font-size: calc(max(11, var(--h) * .14) * var(--u)); }
.card.face .label.mid { font-size: calc(max(11, var(--h) * .4) * var(--u)); }
.card.joker .label.mid { font-size: calc(max(11, var(--h) * .42) * var(--u)); }
.card.back .label.mid { font-size: calc(max(11, var(--h) * .26) * var(--u)); }
.corner { position: absolute; display: flex; flex-direction: column; align-items: center; font-size: calc(max(11, var(--h) * .2) * var(--u)); line-height: 1.05; }
.corner.tl { left: calc(4 * var(--u)); top: calc(4 * var(--u)); }
.corner.br { right: calc(4 * var(--u)); bottom: calc(4 * var(--u)); }
/* A compact card (CardFace.IsCompact, under 80 tall: Meld and sheet cards) has the top-left index only and the big suit at the
 * bottom right, clear of it: the 11 px text floor leaves no room for both indices and a centred suit (#99). */
.card.face.compact .label.mid { top: auto; left: auto; transform: none; right: calc(5 * var(--u)); bottom: calc(4 * var(--u)); }

/* Melds: a framed cluster (no owner frame; each card ringed in its placer's colour), wrapping inside the scrolling .melds band */
.meld { background: var(--plate); border: calc(1 * var(--u)) solid var(--plate-border); border-radius: calc(8 * var(--u)); padding: calc(6 * var(--u)); display: flex; flex-direction: column; gap: calc(2 * var(--u)); }
/* A Meld wider than the Melds area (a long Run beside the side columns) wraps its cards inside its frame: centred and
   unwrapped, both ends were cut off behind a sideways scroll (#99). */
.meld-cards { display: flex; flex-wrap: wrap; gap: calc(4 * var(--u)); }
.meld.legal { border: calc(2 * var(--u)) solid #7ee081; background: rgba(0, 0, 0, 0.3); padding: calc(5 * var(--u)); }
/* Each Meld card is ringed in the colour of the seat that put it on the table (--seat, Meld.PlacedBy); the legal-target outline
 * sits outside that ring, so the two never share a line. */
.meld-card .card { box-shadow: 0 0 0 calc(2 * var(--u)) var(--seat, transparent); }
.meld-card.legal { outline: calc(2 * var(--u)) solid #7ee081; outline-offset: calc(3 * var(--u)); border-radius: calc(5 * var(--u)); }
.meld[data-hover].legal { border-color: var(--gold); background: rgba(242, 201, 76, 0.22); }
.stands { position: absolute; left: 0; right: 0; bottom: calc(5 * var(--u)); text-align: center; font-size: calc(max(11, var(--h) * .17) * var(--u)); }

/* Joker picker: a dim layer that swallows taps, and a panel over the table */
.table { position: relative; }
.modal-dim { position: absolute; inset: 0; background: rgba(0, 0, 0, .6); z-index: 10; }
.modal-centre { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 11; pointer-events: none; }
.picker { pointer-events: auto; padding: calc(16 * var(--u)); gap: calc(8 * var(--u)); align-items: center; }
/* The sheets are also .plate.active (gold border); that rule's translucent background would win over a plain .picker, so the opaque one is set on the pair. */
.picker.plate { background: #14382a; }
.rules { width: calc(660 * var(--u)); }
.rules-scroll { max-height: calc(760 * var(--u)); overflow-y: auto; text-align: left; display: flex; flex-direction: column; gap: calc(4 * var(--u)); }
.rule-title { color: var(--gold); margin-top: calc(10 * var(--u)); font-weight: 800; font-size: calc(20 * var(--u)); letter-spacing: .02em; }
.rule-examples { display: flex; flex-wrap: wrap; gap: calc(6 * var(--u)) calc(20 * var(--u)); margin-top: calc(4 * var(--u)); }
.rule-example { display: flex; flex-direction: column; gap: calc(3 * var(--u)); }
.rule-cards { display: flex; gap: calc(3 * var(--u)); }
.rule-version { font-size: calc(13 * var(--u)); opacity: .7; text-align: left; margin-top: calc(6 * var(--u)); }
.rule-caption { font-size: calc(13 * var(--u)); opacity: .8; }
.rule-body { font-size: calc(16 * var(--u)); }
.scores { width: calc(640 * var(--u)); text-align: left; }
.scores .picker-title, #scores-header { text-align: center; }
.picker-buttons { display: flex; gap: calc(8 * var(--u)); justify-content: center; }
.picker-grid { display: flex; flex-wrap: wrap; justify-content: center; max-width: calc(13 * 50 * var(--u)); gap: calc(4 * var(--u)); }
.picker-cell { padding: 0; border: calc(2 * var(--u)) solid transparent; background: none; border-radius: calc(6 * var(--u)); cursor: pointer; width: calc(46 * var(--u)); height: calc(58 * var(--u)); display: flex; align-items: center; justify-content: center; }
.picker-cell:disabled { opacity: .25; cursor: default; }
.picker-cell.chosen { border-color: var(--gold); }
.picker-preview { min-height: calc(24 * var(--u)); }
.picker-preview.bad { color: var(--error); }
.end-game-body { text-align: center; }
.picker-buttons .btn { min-width: calc(120 * var(--u)); }

/* Round summary / game-over panel (#89): sits above the final table's Melds and piles in .centre; the score table is behind its Scores button; the button sits in the button row */
.summary { align-self: stretch; box-sizing: border-box; padding: calc(10 * var(--u)) calc(16 * var(--u)); gap: calc(4 * var(--u)); text-align: left; }
.summary-headline, .summary-reason, .summary-hand { text-align: center; padding: calc(2 * var(--u)) 0; }
.summary-hand { color: var(--gold); font-weight: 700; }
.summary-scores { align-self: center; min-width: calc(140 * var(--u)); }
/* Game over (#84): winner banner, final standings; #85: celebrate.js draws the confetti / ten-run layer in .celebration; the winner column glows */
.game-over-banner { position: relative; text-align: center; padding: calc(4 * var(--u)) 0; }
.celebration { position: absolute; inset: 0; overflow: visible; pointer-events: none; z-index: 5; }
.confetti-bit { position: absolute; top: 0; width: calc(8 * var(--u)); height: calc(14 * var(--u)); opacity: 0; }
.flying-card { position: absolute; left: 50%; bottom: 0; width: calc(40 * var(--u)); height: calc(58 * var(--u)); border-radius: calc(5 * var(--u)); background: #fff; color: #222; font-weight: 800; font-size: calc(22 * var(--u)); display: flex; align-items: center; justify-content: center; transform-origin: 50% 100%; opacity: 0; box-shadow: 0 2px 6px rgba(0,0,0,.4); }
@keyframes winner-glow { 0%, 100% { box-shadow: inset 0 calc(-3 * var(--u)) 0 var(--gold), 0 0 0 rgba(245,197,66,0); } 50% { box-shadow: inset 0 calc(-3 * var(--u)) 0 var(--gold), 0 0 calc(14 * var(--u)) rgba(245,197,66,.8); } }
.game-over-banner .crown { font-size: calc(40 * var(--u)); line-height: 1; }
.game-over-banner .banner-text { font-size: calc(36 * var(--u)); font-weight: 800; color: var(--gold); }
.game-over-banner .banner-sub, .game-over-banner .banner-place { font-size: calc(22 * var(--u)); font-weight: 700; }
.standings { list-style: none; margin: 0; padding: 0; font-size: calc(18 * var(--u)); }
.standing { display: flex; gap: calc(12 * var(--u)); padding: calc(4 * var(--u)) calc(8 * var(--u)); border-bottom: 1px solid rgba(255, 255, 255, .1); }
.standing .place { width: calc(56 * var(--u)); font-weight: 700; }
.standing .standing-name { flex: 1; }
.standing .standing-total { font-variant-numeric: tabular-nums; }
.standing.winner { color: var(--gold); font-weight: 800; }
.standing.local .standing-name { text-decoration: underline; }
.summary-btn { min-width: calc(180 * var(--u)); }

/* Motion. A selected card lifts (transition above) and the Hand settles after a sort or drag (CSS); cards fly between places
   (js/flight.js: copies in .flight-copy, the card at the new place hidden by data-flying until its copy lands; the copies are
   rendered hidden in #flight-cards). CSS motion stops under prefers-reduced-motion, where flights become a quick fade. */
@keyframes hand-settle-0 { from { opacity: .35; transform: translateY(calc(10 * var(--u))); } to { opacity: 1; transform: none; } }
@keyframes hand-settle-1 { from { opacity: .35; transform: translateY(calc(10 * var(--u))); } to { opacity: 1; transform: none; } }
.hand.reflow-0 .hand-card { animation: hand-settle-0 .25s ease-out; }
.hand.reflow-1 .hand-card { animation: hand-settle-1 .25s ease-out; }
.flight-cards { position: fixed; left: 0; top: 0; visibility: hidden; pointer-events: none; }
.flight-copy { position: fixed; left: 0; top: 0; z-index: 1001; pointer-events: none; transform-origin: 0 0; filter: drop-shadow(0 4px 6px rgba(0,0,0,.45)); }
[data-flying] { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* Reactions and the Round summary's countdown (#60) */
.reaction-btn, .react-btn { font-size: calc(24 * var(--u)); }
.plate.reaction-row { position: absolute; top: calc(56 * var(--u)); right: calc(12 * var(--u)); z-index: 11; display: flex; flex-direction: row; gap: calc(6 * var(--u)); padding: calc(8 * var(--u)); background: #14382a; }
.reaction-choice { width: calc(56 * var(--u)); padding: 0; font-size: calc(28 * var(--u)); line-height: 1; }
.plate { position: relative; }
.reaction-bubble { position: absolute; top: calc(-18 * var(--u)); right: calc(-10 * var(--u)); z-index: 5; padding: calc(2 * var(--u)) calc(10 * var(--u)); border-radius: calc(18 * var(--u)); background: #fff; font-size: calc(30 * var(--u)); line-height: 1.2; box-shadow: 0 calc(2 * var(--u)) calc(6 * var(--u)) rgba(0, 0, 0, .4); pointer-events: none; }
.reaction-bubble.own { top: auto; right: auto; left: 50%; bottom: calc(196 * var(--u)); transform: translateX(-50%); }
.summary-countdown { margin-top: calc(8 * var(--u)); color: var(--gold); font-weight: 700; font-variant-numeric: tabular-nums; }
.ready-mark { color: var(--gold); font-weight: 700; }

/* Start screen: the four-colour suits setting */
.suit-option { min-width: calc(260 * var(--u)); }
.suit-sample { margin-left: calc(10 * var(--u)); background: var(--card-face); border-radius: calc(4 * var(--u)); padding: 0 calc(6 * var(--u)); letter-spacing: .1em; }
.suit-sample span:nth-child(1) { color: var(--suit-clubs); }
.suit-sample span:nth-child(2) { color: var(--suit-diamonds); }
.suit-sample span:nth-child(3) { color: var(--suit-spades); }
.suit-sample span:nth-child(4) { color: var(--suit-hearts); }

/* Score table (#83): a column per player, a row per Round; the header stays put while the rows scroll */
.score-scroll { width: 100%; }
.score-scroll.scrolls { max-height: calc(420 * var(--u)); overflow-y: auto; }
.score-table { width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed; font-size: calc(18 * var(--u)); font-variant-numeric: tabular-nums; text-align: center; }
.score-table th, .score-table td { padding: calc(6 * var(--u)) calc(2 * var(--u)); border-bottom: 1px solid rgba(255, 255, 255, .1); }
.score-table thead th { position: sticky; top: 0; z-index: 1; background: #14382a; color: rgba(244, 241, 232, .8); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-bottom: 2px solid var(--plate-border); }
.score-table .score-round { width: calc(64 * var(--u)); font-weight: 400; color: rgba(244, 241, 232, .7); }
.score-col.local .score-name { color: var(--gold); }
.score-col.out { opacity: .5; }
.score-col.winner { background: #3a4a1e; box-shadow: inset 0 calc(-3 * var(--u)) 0 var(--gold); animation: winner-glow 1.6s ease-in-out 3; }
.dealer-chip { display: inline-block; margin-left: calc(4 * var(--u)); padding: 0 calc(5 * var(--u)); border-radius: calc(8 * var(--u)); background: var(--gold); color: #1a1a1f; font-size: calc(12 * var(--u)); font-weight: 800; }
.score-row.current td, .score-row.current th { background: rgba(242, 201, 76, .22); }
.score-row.void td { opacity: .6; font-style: italic; }
.score-cell.near { color: #ffb74d; font-weight: 700; }
.score-cell.struck { text-decoration: line-through; color: var(--error); }
.went-out { color: var(--gold); font-weight: 700; }
