/* ============================================================================
   Poker — PokerNow-style layout: play area (left) + menu/log sidebar (right).
   Proportions cloned from PokerNow's measured ratios (table ~1.6:1, seats ~18%
   of table, cards ~0.82:1) using CSS container units so they hold at any size.
   Vanilla CSS, no build step.
   ============================================================================ */

:root {
  --font: "Aptos Narrow", "Aptos", "IBM Plex Sans Condensed", "Inter Tight",
    "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;

  --bg: #262626;
  --bg-2: #1e1e1e;
  --panel: #242424;
  --panel-2: #1a1a1a;
  --line: rgba(255, 255, 255, 0.07);
  --line-2: rgba(255, 255, 255, 0.22);

  --text: #ededed;
  --muted: #b9b9b9;
  --muted-2: #9a9a9a;

  /* Table surfaces. Each rich gradient is derived from a single picked base via
     color-mix(), so one color yields full depth. The three bases are overridable
     per-player (JS writes them on :root from localStorage) or per-table (host
     config) — see applyTableTheme() in app.js. Built-in look: emerald felt /
     oak rail / near-black backdrop. */
  --felt-base: #2f9560;
  --bg-base: #0c0e0d;
  /* wood rail is now a texture image (see public/woods/, set per effective wood by
     applyTableTheme). Default here so the rail renders before JS runs / if JS fails. */
  --rail-img: url("/woods/oak_veneer_01.jpg");

  --felt-1: color-mix(in srgb, var(--felt-base), #ffffff 16%);
  --felt-2: var(--felt-base);
  --felt-3: color-mix(in srgb, var(--felt-base), #000000 20%);
  --felt-4: color-mix(in srgb, var(--felt-base), #000000 40%);

  --cta: #36a86a;
  --cta-press: #2c8f59;
  --cta-hover: #3fbd79;
  --cta-text: #04190d;
  --gold: #f0c64a;

  --ok: #37d07f;
  --off: #6a6a6a;
  --warn: #e9b949;
  --bad: #e5685f;

  /* medal accents (1st/2nd/3rd) + net win/loss — deliberately distinct from --gold/--ok/--bad */
  --medal-gold: #f3cf5b;
  --medal-silver: #ccd1da;
  --medal-bronze: #d2904f;
  --net-up: #4bd089;
  --net-down: #e0686a;

  --shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  --radius: 14px;

  /* shared surface tokens (were duplicated as raw hex across inputs / hover states) */
  --input-bg: #161616;
  --btn-hover: #2f2f2f;
  /* fold action: a muted maroon that still clears --panel so it reads as a real (destructive) button */
  --btn-fold: #371d1e;
  --btn-fold-border: #5e3133;
  /* ink for text laid directly on the felt (pot/board labels). JS overrides this per
     felt color from its luminance (see feltInk in app.js); the default suits the emerald felt. */
  --felt-ink: #ffffff;
}

* {
  box-sizing: border-box;
}
html,
body {
  margin: 0;
  height: 100%;
}
body {
  /* near-black backdrop derived from --bg-base (lighter top-center -> darker edge)
     so the lit table reads with strong contrast against it. */
  background: radial-gradient(
      125% 100% at 50% 4%,
      color-mix(in srgb, var(--bg-base), #ffffff 7%) 0%,
      var(--bg-base) 52%,
      color-mix(in srgb, var(--bg-base), #000000 55%) 100%
    )
    fixed;
  color: var(--text);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
#app {
  height: 100%;
}
button {
  font-family: inherit;
}

.num {
  font-variant-numeric: tabular-nums;
}

/* ---------- buttons / inputs ---------- */
.btn {
  appearance: none;
  border: 1px solid var(--line-2);
  background: var(--panel);
  color: var(--text);
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.06s ease, background 0.15s ease, border-color 0.15s ease,
    opacity 0.15s ease;
}
.btn:hover {
  background: var(--btn-hover);
  border-color: rgba(255, 255, 255, 0.22);
}
.btn:active {
  transform: translateY(1px);
}
.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
}
.btn:focus-visible,
.field:focus-visible,
.bot-select:focus-visible,
.speed-slider:focus-visible,
.bet-slider:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 2px;
}
.btn-primary {
  background: var(--cta);
  border-color: transparent;
  color: var(--cta-text);
}
.btn-primary:hover {
  background: var(--cta-hover);
}
.btn-primary:active {
  background: var(--cta-press);
}
.btn-ghost {
  background: transparent;
}
.btn-sm {
  padding: 7px 12px;
  font-size: 13px;
}
/* inline line icons — monochrome SVGs that inherit the button's currentColor and
   scale to its font-size, used on the HUD / chat / labeled buttons in place of emoji */
.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  line-height: 0;
  flex: 0 0 auto;
}
.icon svg {
  width: 1.2em;
  height: 1.2em;
  display: block;
}
/* a labeled button that leads with an icon sits the icon beside its text */
.btn:has(.icon) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

.field {
  display: block;
  width: 100%;
  background: var(--input-bg);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  color: var(--text);
  padding: 12px 14px;
  font-size: 15px;
  outline: none;
}
.field:focus {
  border-color: var(--cta);
  box-shadow: 0 0 0 3px rgba(54, 168, 106, 0.18);
}
/* Dark-theme native dropdowns: keep the open <option> popup dark instead of the
   browser default white, which made the inherited light text white-on-white.
   color-scheme darkens the UA popup; explicit option colors are the cross-browser fallback. */
select {
  color-scheme: dark;
}
option,
optgroup {
  background-color: var(--bg-2);
  color: var(--text);
}
.label {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 6px 2px;
}

/* ============================================================================
   HOME
   ============================================================================ */
.home {
  min-height: 100%;
  display: grid;
  place-items: center;
  padding: 24px;
}
.home-card {
  width: min(420px, 100%);
  background: linear-gradient(180deg, var(--panel), var(--panel-2));
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 30px 26px 26px;
  box-shadow: var(--shadow);
}
.home-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 4px;
}
.home-brand .spade {
  color: var(--cta);
}
.home-logo {
  height: 1.15em;
  width: auto;
  flex: 0 0 auto;
}
.home-sub {
  color: var(--muted);
  margin: 0 0 24px;
  font-size: 14px;
}
.home .group {
  margin-bottom: 18px;
}
.home .btn {
  width: 100%;
  padding: 13px;
  font-size: 15px;
}
.home .divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--muted-2);
  font-size: 12px;
  letter-spacing: 0.1em;
  margin: 22px 0 18px;
}
.home .divider::before,
.home .divider::after {
  content: "";
  height: 1px;
  flex: 1;
  background: var(--line);
}
/* Stack the join field over its button so the input gets the full card width — wide
   enough to paste an invite link or room code (sharing the row let the button squeeze
   the field down to its minimum). */
.join-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.join-row .field {
  width: 100%;
}

/* ============================================================================
   ROOM — play area (left) + menu/log sidebar (right)
   ============================================================================ */
.room {
  height: 100%;
  display: flex;
  min-height: 0;
}

/* ---- play area (the felt) ---- */
.play {
  flex: 1;
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}
.felt-area {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 10px;
  overflow: hidden; /* the table + overhanging seat plates can never push a page scroll */
  /* size container so .stage can bound itself by the area's HEIGHT (cqh), not just
     the viewport — the action row is a sibling below, so this is what keeps the
     table + action row inside the viewport with no page scroll. */
  container-type: size;
}
.stage {
  position: relative;
  container-type: size;
  /* ~1.6:1 table, sized to leave a margin for the seat plates that ring the felt edge
     (side seats sit at x 5%/95% and overhang outward, so the table can't fill the full
     play width or they'd hit the sidebar). Bounded in BOTH axes off the felt-area:
     width 88cqw AND height 140cqh (-> table height ~88% of the area, leaving room for
     the overhang), plus a 1500px ceiling. */
  width: min(88cqw, 140cqh, 1500px);
  aspect-ratio: 1.6 / 1;
}
/* the table itself is the wooden rail: an ellipse filling the stage, with the felt
   ellipse laid on top (.felt is inset within it). Grain = a wood texture image
   (var --rail-img, set per effective wood); a translucent diagonal sheen on top
   gives rounded, lit siding; shadows lift it off the backdrop (outer drop) and
   carve the inner lip (inset). */
.table {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  /* wood rail = a CC0 photo (var --rail-img, set per effective wood) under a
     translucent diagonal sheen, so it still reads as a lit, rounded rail. */
  background-image: linear-gradient(
      160deg,
      rgba(255, 255, 255, 0.16),
      rgba(255, 255, 255, 0) 38%,
      rgba(0, 0, 0, 0.34)
    ),
    var(--rail-img);
  /* sheen spans the whole rail (cover); the wood itself tiles at a fraction of the table so the
     grain reads proportional to a table this size instead of one photo blown up across it. */
  background-size: cover, var(--rail-grain, 16%);
  background-position: center, center;
  background-repeat: no-repeat, repeat;
  box-shadow: 0 26px 64px rgba(0, 0, 0, 0.62), 0 6px 18px rgba(0, 0, 0, 0.5),
    inset 0 2px 2px rgba(255, 255, 255, 0.14), inset 0 -14px 30px rgba(0, 0, 0, 0.55);
}
.seat-layer {
  position: absolute;
  inset: 0;
}
/* chip animations: a pointer-events-free overlay where chips fly between a seat and the pot */
.chip-fx {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
  z-index: 8; /* above seats/pods (z2-6); transient + click-through */
}
.fly-chip {
  position: absolute;
  top: 0;
  left: 0;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px; /* anchor the chip on its translate point */
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 35%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 45%),
    var(--chip-color, #c8473f);
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, 0.82),
    inset 0 0 0 3px rgba(0, 0, 0, 0.18),
    0 2px 5px rgba(0, 0, 0, 0.5);
  will-change: transform, opacity;
}
.fly-chip::after { /* dashed chip edge */
  content: '';
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  background: repeating-conic-gradient(rgba(255, 255, 255, 0.9) 0 7deg, rgba(255, 255, 255, 0) 7deg 30deg);
  -webkit-mask: radial-gradient(circle, transparent 56%, #000 58%, #000 70%, transparent 72%);
          mask: radial-gradient(circle, transparent 56%, #000 58%, #000 70%, transparent 72%);
}
@keyframes pot-pulse {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.12); }
}
.pot.pot-pulse { animation: pot-pulse 0.32s ease; }
@media (prefers-reduced-motion: reduce) {
  .chip-fx { display: none; }
  .pot.pot-pulse { animation: none; }
}
/* soundboard emote tiles now live in a popover beside the chat input (see .sb-pop / .sb-key);
   a fired emote still floats its emoji over the sender's seat (.emote-pop below). */
.emote-pop {
  position: absolute;
  margin: -12px 0 0 -12px;
  font-size: 32px;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.55));
  animation: emote-float 1.6s ease-out forwards;
}
@keyframes emote-float {
  0% { opacity: 0; transform: translateY(8px) scale(0.5); }
  14% { opacity: 1; transform: translateY(0) scale(1.18); }
  28% { transform: translateY(-7px) scale(1); }
  100% { opacity: 0; transform: translateY(-52px) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .emote-pop { animation: emote-fade 1.2s ease forwards; }
}
@keyframes emote-fade { 0%, 70% { opacity: 1; } 100% { opacity: 0; } }
/* uploaded photo avatars: the seat disc holds an <img>; the upload UI lives in the Appearance tab */
.avatar.avatar-img {
  padding: 0;
  overflow: hidden;
  background: var(--panel);
}
.avatar.avatar-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;
}
.avatar-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 2px;
}
.avatar-prev {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line-2);
  display: grid;
  place-items: center;
}
.avatar-prev img { width: 100%; height: 100%; object-fit: cover; }
.avatar-prev-empty { font-size: 26px; opacity: 0.7; }
.avatar-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.avatar-file { display: none; }
/* session stats: tabbed modal (Standings / full-page Chip chart / Leaders) */
.modal.modal-stats { width: min(1040px, 96vw); } /* roomy so the chip chart can fill the page */
.stats-body { min-height: 210px; }
.stats-loading,
.stats-empty { padding: 36px 8px; text-align: center; color: var(--muted); }

/* tab navbar */
.stats-tabs {
  display: flex;
  gap: 4px;
  margin: 2px 0 14px;
  border-bottom: 1px solid var(--line);
}
.stats-tab {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 8px 15px;
  font: inherit;
  font-weight: 700;
  font-size: 13px;
  color: var(--muted);
  cursor: pointer;
}
.stats-tab:hover { color: var(--text); }
.stats-tab.on { color: var(--text); border-bottom-color: var(--cta); }
.stats-tab:focus-visible { outline: 2px solid var(--cta); outline-offset: 2px; }

/* chip chart — full page */
.chart-wrap { display: flex; flex-direction: column; gap: 12px; }
.chip-chart {
  width: 100%;
  height: auto;
  display: block;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.cc-plot { fill: rgba(255, 255, 255, 0.015); stroke: rgba(255, 255, 255, 0.12); stroke-width: 1; }
.cc-grid { stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
.cc-ylab,
.cc-xlab { fill: var(--muted-2); font-size: 13px; font-variant-numeric: tabular-nums; }
.cc-axis-title { fill: var(--muted); font-size: 15px; font-weight: 700; letter-spacing: 0.04em; }
.cc-legend-row { display: flex; flex-wrap: wrap; gap: 6px 16px; justify-content: center; }
.cc-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.cc-legend-item.you { color: var(--text); font-weight: 700; }
/* hover crosshair + per-hand chip tooltip */
.cc-canvas { position: relative; width: 100%; }
.cc-end-av { position: absolute; transform: translate(-50%, -50%); pointer-events: none; z-index: 1; }
.cc-end-av.you { z-index: 2; }
.cc-end-av .avatar.cc-av { width: 28px; height: 28px; font-size: 14px; }
.cc-end-av.you .avatar.cc-av { width: 34px; height: 34px; font-size: 16px; }
.cc-cross { stroke: var(--muted); stroke-width: 1.4; stroke-dasharray: 5 4; stroke-opacity: 0.85; pointer-events: none; }
.cc-hover { pointer-events: none; }
.cc-cross-dot { stroke: #0c0e0d; stroke-width: 1.5; }
.cc-tooltip {
  position: absolute;
  pointer-events: none;
  z-index: 5;
  min-width: 156px;
  max-width: 248px;
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 8px 10px;
  box-shadow: var(--shadow);
}
.cc-tip-head { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2); margin-bottom: 7px; }
.cc-tip-row { display: flex; align-items: center; gap: 8px; padding: 2px 0; font-size: 13px; }
.cc-tip-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.cc-tip-row.you .cc-tip-name { color: var(--text); font-weight: 700; }
.cc-tip-chips { font-variant-numeric: tabular-nums; font-weight: 800; color: var(--gold); }
/* avatar disc reused in the legend + tooltip (smaller than the seat disc; color ring set inline) */
.avatar.cc-av { width: 22px; height: 22px; font-size: 12px; border: none; }
.avatar.cc-av.emoji { font-size: 14px; }
/* Style tab — VPIP × PFR player-type scatter */
.style-canvas { position: relative; width: 100%; max-width: 560px; margin: 0 auto; }
.style-chart { width: 100%; height: auto; display: block; background: rgba(0, 0, 0, 0.22); border: 1px solid var(--line); border-radius: 12px; }
.st-divider { stroke: rgba(255, 255, 255, 0.1); stroke-width: 1; stroke-dasharray: 4 4; }
.st-diag { stroke: rgba(255, 255, 255, 0.06); stroke-width: 1; }
.st-zone { fill: var(--muted-2); font-size: 15px; font-weight: 800; letter-spacing: 0.04em; opacity: 0.5; }
.st-zone-sub { fill: var(--muted-2); font-size: 11px; opacity: 0.38; }
.style-dot { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 2px; pointer-events: none; }
.style-dot.you { z-index: 2; }
.style-name { font-size: 11px; color: var(--muted); max-width: 76px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.style-dot.you .style-name { color: var(--text); font-weight: 700; }
.style-canvas .avatar.cc-av { width: 42px; height: 42px; font-size: 19px; }
.style-canvas .style-dot.you .avatar.cc-av { width: 50px; height: 50px; font-size: 23px; }
.style-hint { font-size: 12px; color: var(--muted-2); text-align: center; line-height: 1.4; }
/* Highlights tab — biggest pots + standout bluff / hero call */
.highlights { display: flex; flex-direction: column; gap: 14px; }
.hl-feats { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.hl-feat { background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line-2); border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
.hl-feat-label { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2); }
.hl-feat-val { font-size: 22px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.hl-feat-sub { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.hl-who { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.hl-name { font-size: 13px; color: var(--text); font-weight: 600; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hl-section-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-2); }
.hl-list { display: flex; flex-direction: column; gap: 4px; }
.hl-row { display: grid; grid-template-columns: 34px 1fr auto auto auto; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 8px; }
.hl-row:nth-child(odd) { background: rgba(255, 255, 255, 0.035); }
.hl-rank { font-size: 12px; font-weight: 800; color: var(--muted-2); }
.hl-winners { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; }
.hl-pot { font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.hl-hand { font-size: 11px; color: var(--muted-2); white-space: nowrap; }
.hl-board { display: inline-flex; gap: 3px; }
.hl-card { font-size: 12px; font-weight: 700; padding: 1px 4px; border-radius: 4px; background: rgba(255, 255, 255, 0.06); }
.hl-card.s-d, .hl-card.s-h { color: #e5685f; }
.hl-card.s-c, .hl-card.s-s { color: var(--text); }
.hl-board-empty { color: var(--muted-2); }
/* Awards tab — achievement badges */
.awards { display: flex; flex-direction: column; gap: 12px; }
.badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); gap: 12px; }
.badge { display: flex; gap: 15px; align-items: center; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line-2); border-radius: 14px; padding: 15px 17px; }
/* award mascot — full-color inline SVG on a collectible "token" disc */
.badge-art {
  flex: 0 0 auto; width: 64px; height: 64px;
  display: grid; place-items: center; border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, rgba(47, 149, 96, 0.20), rgba(47, 149, 96, 0.06) 70%, transparent 72%);
  box-shadow: inset 0 0 0 1px var(--line-2), 0 1px 2px rgba(0, 0, 0, 0.35);
}
.badge-art svg { width: 55px; height: 55px; display: block; }
.badge-body { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.badge-title { font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gold); font-weight: 800; }
.badge-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.badge-name { font-size: 16px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.badge-sub { font-size: 13px; color: var(--muted); }
/* preflop range chart (reference) */
.modal.modal-range { width: min(1040px, 96vw); }
.range-body { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.range-side { flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: 11px; }
.range-side > div { margin-top: 0; }
.range-sub { font-size: 12px; color: var(--muted); margin-bottom: 12px; line-height: 1.45; }
.range-pos { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.range-pos-btn { padding: 5px 13px; border-radius: 8px; border: 1px solid var(--line-2); background: var(--panel); color: var(--muted); font-weight: 800; font-size: 13px; cursor: pointer; }
.range-pos-btn:hover { border-color: var(--cta); }
.range-pos-btn.on { background: var(--cta); color: var(--cta-text); border-color: transparent; }
/* square grid as the right-hand column: 13 equal rows + columns + 1:1 aspect keep every cell square */
/* square grid, but never taller than the viewport leaves room for (header + side + legend + actions
   + padding) — so the whole modal fits without a near-empty scrollbar on shorter screens. */
.range-grid { flex: 1 1 300px; min-width: 0; max-width: min(552px, calc(100dvh - 300px)); display: grid; grid-template-columns: repeat(13, 1fr); grid-template-rows: repeat(13, 1fr); gap: 2px; aspect-ratio: 1 / 1; }
.range-cell { display: grid; place-items: center; min-width: 0; overflow: hidden; font-size: clamp(7px, 1.5vw, 11px); font-weight: 700; border-radius: 3px; background: var(--panel-2); color: var(--muted-2); user-select: none; }
.range-cell.pair { background: rgba(240, 198, 74, 0.09); }
/* position views: in-range hands are colored by strength via the t-* ramp below
   (out-of-range hands stay dark) — same green→red language as the Tiers view. A
   light inset ring marks the range edge so it reads even where tiers are similar. */
.range-cell.in { box-shadow: inset 0 0 0 1.5px rgba(245, 240, 230, 0.4); }
.range-meta { margin-top: 11px; font-size: 13px; color: var(--text); font-weight: 800; }
.range-legend { margin-top: 8px; display: flex; gap: 14px; align-items: center; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
.range-key { display: inline-flex; align-items: center; gap: 6px; }
.range-sw { width: 14px; height: 14px; border-radius: 3px; background: var(--panel-2); display: inline-block; }
.range-sw.in { background: #2f9560; }
.range-sw-ramp { background: linear-gradient(90deg, #2f9560 0%, #e0c34a 52%, #a8463f 100%); }
.range-note { color: var(--muted-2); }
/* strength-tier view — an intuitive green→red heat ramp (premium = green, fold =
   red), so a hand's color reads its strength at a glance. Colors win over the
   pair/suited base tints above. */
.range-cell.t-premium { background: #2f9560; color: #04190d; }
.range-cell.t-strong { background: #79bd55; color: #0b1705; }
.range-cell.t-playable { background: #e0c34a; color: #201804; }
.range-cell.t-specul { background: #e0954b; color: #20140a; }
.range-cell.t-marginal { background: #d4694e; color: #220b06; }
.range-cell.t-fold { background: #a8463f; color: #ffe6e2; }
.range-sw.t-premium { background: #2f9560; }
.range-sw.t-strong { background: #79bd55; }
.range-sw.t-playable { background: #e0c34a; }
.range-sw.t-specul { background: #e0954b; }
.range-sw.t-marginal { background: #d4694e; }
.range-sw.t-fold { background: #a8463f; }
/* per-view explanation + the tier descriptions */
.range-info { margin-top: 11px; font-size: 12.5px; line-height: 1.5; color: var(--muted); background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.range-tierlist { flex-direction: column; align-items: stretch; gap: 7px; }
.range-tier-row { display: flex; align-items: center; gap: 9px; }
.range-tier-row .range-sw { flex: 0 0 auto; }
.range-tier-label { font-weight: 800; font-size: 12.5px; color: var(--text); min-width: 88px; }
.range-tier-desc { font-size: 12px; color: var(--muted); }
/* live hover readout: the hand + an explanation of its current highlight */
.range-cell:hover { outline: 2px solid var(--text); outline-offset: -1px; z-index: 1; }
.range-hover { margin-top: 11px; min-height: 40px; display: flex; align-items: center; flex-wrap: wrap; font-size: 13px; line-height: 1.45; color: var(--muted); background: rgba(255, 255, 255, 0.03); border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px; }
.range-hover-hand { font-weight: 800; color: var(--text); }
.range-hover-detail { color: var(--muted); }
.range-hover-hint { color: var(--muted-2); font-style: italic; }

/* standings table */
.stats-table-wrap { overflow-x: auto; }
.stats-grid { width: 100%; border-collapse: collapse; font-size: 13px; }
.stats-grid th,
.stats-grid td { padding: 7px 10px; white-space: nowrap; }
.stats-grid thead th {
  color: var(--muted-2);
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-align: right;
  border-bottom: 1px solid var(--line);
}
.stats-grid th.st-player { text-align: left; }
.stats-grid th.st-sort { cursor: pointer; user-select: none; }
.stats-grid th.st-sort:hover { color: var(--muted); }
.stats-grid th.st-sort.on { color: var(--text); }
.stats-grid tbody tr { border-bottom: 1px solid rgba(255, 255, 255, 0.04); }
.stats-grid tbody tr.you { background: rgba(224, 179, 65, 0.1); }
.stats-grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
.stats-grid td.num.up { color: var(--net-up); }
.stats-grid td.num.down { color: var(--net-down); }
.stats-grid td.st-player { text-align: left; }
.stats-grid td.st-player .stats-swatch { margin-right: 7px; }
.stats-grid td.st-player .stats-youtag { margin-left: 7px; }
.stats-swatch {
  display: inline-block;
  vertical-align: middle;
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
}
.stats-name { vertical-align: middle; }
.stats-youtag {
  display: inline-block;
  vertical-align: middle;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.08em;
  background: var(--cta);
  color: #0c0c0c;
  padding: 1px 4px;
  border-radius: 4px;
}

/* leaders */
.leaders { display: flex; flex-direction: column; gap: 12px; }
.leaders-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.leader-card {
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
}
.leader-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-2); }
.leader-who { display: flex; align-items: center; gap: 7px; margin: 8px 0 4px; font-weight: 700; }
.leader-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.leader-val { font-size: 20px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.leaders-foot { text-align: center; color: var(--muted-2); font-size: 12px; }
.felt {
  position: absolute;
  inset: 8% 5%;
  border-radius: 50%;
  background: radial-gradient(
    120% 120% at 50% 28%,
    var(--felt-1),
    var(--felt-2) 40%,
    var(--felt-3) 72%,
    var(--felt-4) 100%
  );
  /* the wood rail now shows in the ring around the felt, so the felt drops its old
     dark ring and instead carves a thin seam (dark groove + faint highlight) where
     it meets the wood, plus inner shading for the bowl depth. */
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--felt-base), #000000 50%),
    0 0 0 3px rgba(255, 255, 255, 0.06), inset 0 0 60px rgba(0, 0, 0, 0.42);
}
/* faint inner bet line */
.felt::after {
  content: "";
  position: absolute;
  inset: 14% 9%;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--felt-base), #000000 55%);
}
/* slight felt weave — a faint tintable noise over the felt, toggled per-player
   (#app.felt-textured, default on). mix-blend keeps it working over ANY felt color. */
#app.felt-textured .felt::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23f)'/%3E%3C/svg%3E");
  background-size: 150px 150px;
  opacity: 0.5;
  mix-blend-mode: overlay;
}

/* center: pot + board + start/waiting */
.center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  width: 72%;
  text-align: center;
}
.pot {
  font-size: clamp(11px, 3cqw, 15px);
  color: var(--felt-ink, #fff);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.pot b {
  font-weight: 800;
}
.board {
  display: flex;
  gap: clamp(3px, 0.9cqw, 7px);
}
.card-slot {
  width: clamp(34px, 8.1cqw, 130px);
  aspect-ratio: 41 / 50;
  border-radius: 4px;
  border: 1px dashed rgba(255, 255, 255, 0.18);
  background: rgba(0, 0, 0, 0.14);
}
.center-action {
  min-height: 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.center-msg {
  font-size: 12px;
  color: #e3efe8;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(255, 255, 255, 0.12);
  padding: 6px 12px;
  border-radius: 999px;
}
/* Start Game / lobby CTA: it sits on a host-chosen felt of ANY color, so it can't
   lean on its fill to stand out. A light inner ring frames it against dark/colored
   felt, a dark ring just outside it frames it against light felt, and a lift shadow
   floats it off the cloth. */
.center-action .btn-primary {
  padding: 13px 30px;
  font-size: 16px;
  font-weight: 800;
  border-radius: 12px;
  border-color: transparent;
  position: relative;
  top: 8px;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.95), 0 0 0 3.5px rgba(0, 0, 0, 0.42),
    0 10px 26px rgba(0, 0, 0, 0.5);
}
/* the "Need 2+ players" hold state: a lighter frame */
.center-action .btn-primary:disabled {
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.55), 0 4px 12px rgba(0, 0, 0, 0.4);
}

/* seats — translucent dark plate with round avatar, hero bottom-center */
.seat {
  position: absolute;
  transform: translate(-50%, -50%);
  width: clamp(120px, 24cqw, 196px);
  transition: transform 0.15s ease;
}
.seat.acting {
  z-index: 6;
}
/* A seat with a live bet rides above every plate. The bet-chip is trapped in the seat's transform
   stacking context, so its own z-index can't clear a neighbour's pod; lifting the whole seat above
   the pod band (plain 0, acting 6) keeps the wagered amount visible no matter who's acting or where
   the seat falls in DOM order. Ties the HUD's z7, but the HUD wins on source order + sits in the
   corners, so it's never overlapped. */
.seat:has(.bet-chip),
.seat:has(.check-chip),
.seat:has(.win-badge) {
  z-index: 7;
}
.pod {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  min-height: 56px; /* dual-use plate: identity on the left, hole cards on the right */
  background: rgba(40, 40, 40, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 8px;
  padding: 5px 8px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.4);
  transition: transform 0.15s ease, opacity 0.2s ease, filter 0.2s ease;
}
/* the identity + hole-cards row inside the plate (the plate itself is a column now) */
.pod-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* current made-hand category — full-width strip at the bottom of the plate */
.hand-value {
  margin-top: 4px;
  padding-top: 3px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  text-align: center;
  font-size: clamp(9px, 2cqw, 12px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.seat.me .pod {
  border-color: transparent;
  box-shadow: 0 0 0 2px rgba(54, 168, 106, 0.65), 0 3px 10px rgba(0, 0, 0, 0.4);
}
.avatar {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(180deg, #3c3c3c, #2a2a2a);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #e6ece8;
  font-weight: 800;
  font-size: 15px;
  display: grid;
  place-items: center;
}
/* an emoji seat symbol fills the 38px circle (initials stay 18px) */
.avatar.emoji {
  font-size: 21px;
  line-height: 1;
}
/* Plate avatars are large portrait discs that straddle the plate's left edge: a negative left
   margin of half the avatar's size (plus the plate's 8px padding) centers the circle on that edge,
   so it's a clean 50/50 split — half on the plate, half overhanging the felt (the .pod doesn't
   clip). Sized to ~the hole-card height so it fills most of the plate's vertical room. The size is
   a custom property so the 50/50 offset stays exact as it scales. Photos stay cleanly clipped to
   the circle via .avatar-img (overflow:hidden + object-fit:cover). */
.seat .avatar {
  --av-size: clamp(46px, 8.5cqw, 74px);
  width: var(--av-size);
  height: var(--av-size);
  font-size: calc(var(--av-size) * 0.42);
  margin: 0 4px 0 calc(var(--av-size) / -2 - 8px);
  transform: translateY(6px); /* nudge down so the top-border stat slots clear the avatar's top */
}
.seat .avatar.emoji {
  font-size: calc(var(--av-size) * 0.58);
}
.pinfo {
  min-width: 58px; /* protected: name + chip count never collapse under the cards */
  flex: 1;
  text-align: left;
}
.seat .name {
  font-size: 14px;
  font-weight: 600;
  color: #cfcfcf;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
}
.seat .pdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);
  flex: 0 0 auto;
}
.seat.offline .pdot {
  background: var(--off);
}
.seat.offline .name {
  color: var(--muted-2);
}
.seat .name .pname { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* per-player soundboard mute — subtle speaker icon inline by an opponent's name */
.mute-player {
  appearance: none;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  border: none;
  background: none;
  color: var(--muted-2);
  opacity: 0.6;
  cursor: pointer;
  border-radius: 4px;
}
.mute-player svg { width: 12px; height: 12px; display: block; }
.mute-player:hover { opacity: 0.95; color: var(--text); background: rgba(255, 255, 255, 0.08); }
.mute-player:focus-visible { opacity: 0.95; outline: 2px solid var(--cta); outline-offset: 1px; }
.mute-player.on { opacity: 1; color: var(--net-down); }
.seat .stack {
  font-size: 14px;
  font-weight: 700;
  color: var(--gold);
  margin-top: 2px;
}
.seat .substatus {
  font-size: 12px;
  color: var(--warn);
  margin-top: 2px;
  letter-spacing: 0.04em;
}

/* empty seat — rectangular plate */
.seat-empty {
  display: grid;
  place-items: center;
}
/* circular numbered "Sit" disc — click an open seat to take that exact seat; the
   host gets a small text-only "add bot" button stacked inside the same disc */
/* The seat ring IS the Sit button — the whole circle is the click target (seat # + SIT). The
   host gets a small circular bot button inside it at the bottom (a bespoke robot glyph, not an
   emoji); its click stops propagation so it never triggers the sit. */
.pod-empty {
  position: relative;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  box-sizing: border-box;
  line-height: 1;
  border: 2px solid rgba(255, 255, 255, 0.34);
  background: rgba(0, 0, 0, 0.4);
  color: var(--muted);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.pod-empty:not(.locked):hover { border-color: var(--cta); background: rgba(54, 168, 106, 0.16); transform: scale(1.05); }
.pod-empty:not(.locked):hover .pe-act { color: var(--cta); }
.pod-empty:focus-visible { outline: none; border-color: var(--cta); box-shadow: 0 0 0 3px rgba(54, 168, 106, 0.35); }
.pod-empty.locked { cursor: default; border-style: dashed; border-color: rgba(255, 255, 255, 0.1); background: rgba(0, 0, 0, 0.26); }
.pe-num { font-size: 26px; font-weight: 800; color: var(--text); }
.pod-empty.locked .pe-num { color: var(--muted); }
.pe-act { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
/* host-only: a small circular button (bespoke robot glyph) to drop a bot into this seat */
.pe-bot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-top: 3px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  border: 1.5px solid rgba(255, 255, 255, 0.3);
  color: var(--muted);
  cursor: pointer;
  transition: border-color 0.13s ease, background 0.13s ease, transform 0.13s ease, color 0.13s ease;
}
.pe-bot:hover { border-color: var(--cta); background: rgba(54, 168, 106, 0.22); color: var(--cta); transform: scale(1.1); }
.pe-bot .icon, .pe-bot .icon svg { width: 21px; height: 21px; display: block; }
/* Stat slots straddling the plate's TOP border — small circular badges sitting 50/50 on/off the
   border (like the avatar on the left edge), packed left→right: hands won, then rebuys, then the
   position chip(s) when held. Each appears only when it has a value; small + unobtrusive. */
.plate-slots {
  position: absolute;
  top: 0;
  left: 20px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
  z-index: 5;
}
.plate-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.slot-wins {
  background: radial-gradient(circle at 50% 32%, #5cca88, #2f9c5d);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.3);
}
.slot-rebuys {
  background: radial-gradient(circle at 50% 32%, #e3685d, #b23227);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.3);
}
/* Position chips (dealer button / blinds). Color only — shape + size come from .plate-slot (the
   resting slot on the plate) or .fly-pos-chip (in flight between plates as the button rotates).
   Dealer = white button, SB/BB tinted. */
.dealer-chip {
  background: radial-gradient(circle at 50% 32%, #ffffff, #d7dadf);
  color: #2a2a2a;
  border: 1px solid rgba(0, 0, 0, 0.22);
}
.sb-chip {
  background: radial-gradient(circle at 50% 32%, #74a4e4, #3f6fb8);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.38);
}
.bb-chip {
  background: radial-gradient(circle at 50% 32%, #e3a648, #b06f1f);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.38);
}
/* your own plate's leave-seat button — top-right corner, in line with the stat slots and the same
   size (mirrors their left:7px with right:7px). Dark/red so it reads as a control, not a stat. */
.plate-x {
  position: absolute;
  top: 0;
  left: -9px;
  transform: translateY(-50%);
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  background: #2e1615;
  border: 1px solid #5a2b2b;
  color: var(--bad);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.plate-x:hover { background: #3a1f1f; border-color: #7a3636; }
/* a position chip in flight between plates when the button/blinds rotate. Lives in the chip-fx
   overlay (above the plates, so the travel is always visible) and reuses the -chip color classes.
   left/top:0 + a half-size negative margin centers it on its translate(x,y) point. */
.fly-pos-chip {
  position: absolute;
  left: 0;
  top: 0;
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1;
  pointer-events: none;
  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.45);
  z-index: 3;
  will-change: transform, opacity;
}

/* seat number — small chip on the bottom-right corner of each occupied plate, so
   every seat is identifiable and matches the numbered empty-seat discs */
.seat-num {
  position: absolute;
  bottom: -8px;
  right: -8px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: rgba(10, 12, 11, 0.85);
  border: 1px solid var(--line-2);
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}

/* action cluster — compact, pinned bottom-right of the play area */
.action-cluster {
  position: absolute;
  right: calc(14px + env(safe-area-inset-right, 0px));
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  /* steady footprint: hold a min-width that fits the full Fold·Call·Raise·All-in row so the cluster
     doesn't resize / shift when the All-in button toggles in and out between streets */
  min-width: 306px;
}
.action-cluster .frac {
  display: flex;
  gap: 6px;
}
.action-cluster .frac .btn {
  padding: 5px 9px;
  font-size: 12px;
}
.bet-slider {
  width: min(220px, 56vw); /* responsive, mirrors the .amt field's min(100px, 40vw) */
  accent-color: var(--cta);
}
.action-cluster .action-row {
  display: flex;
  gap: 6px;
}
.action-cluster .action-row .btn {
  min-width: 72px;
  padding: 9px 12px;
  font-size: 13px;
}
/* high-contrast focus ring on the live action cluster: the shared --cta (green) ring can
   wash out on the dark fold button, so pin a white ring here for keyboard players mid-action */
.action-cluster .action-row .btn:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}
.btn-fold {
  background: var(--btn-fold);
  border-color: var(--btn-fold-border);
}
.btn-bet {
  background: var(--cta);
  border-color: transparent;
  color: var(--cta-text);
}
/* Call gets a faint accent so "match the bet" reads distinct from a free Check (plain .btn) */
.btn-call {
  border-color: color-mix(in srgb, var(--cta) 50%, var(--line-2));
  background: color-mix(in srgb, var(--cta) 12%, transparent);
}
.action-hint {
  color: var(--muted);
  font-size: 13px;
  padding: 6px 10px;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 8px;
}
.bet-controls .amt {
  min-width: 46px;
  text-align: center;
  font-weight: 800;
  color: var(--gold);
  background: var(--input-bg);
  border: 1px solid var(--line-2);
  border-radius: 6px;
  padding: 4px 8px;
}
/* the amount is a typable field: strip the native input chrome, keep the gold box */
.bet-controls input.amt {
  appearance: none;
  -webkit-appearance: none;
  width: min(100px, 40vw);
  min-width: 0;
  font-family: inherit;
  font-size: 13px;
  cursor: text;
}
.bet-controls input.amt:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 1px;
  border-color: var(--cta);
}

/* ---- cards ---- */
.card {
  position: relative;
  width: clamp(26px, 6.6cqw, 52px);
  aspect-ratio: 41 / 50;
  border-radius: 5px;
  background: #f7f7f2;
  color: #1a1a1a;
  overflow: hidden;
  font-weight: 800;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
  font-variant-numeric: tabular-nums;
  /* Base the corner glyphs (em-fractions below) on the card's own font-size, set
     proportional to width per context (.hole / hero / .board-card) so the rank &
     suit scale with the card instead of capping out small. */
  font-size: clamp(13px, 3.2cqw, 25px);
}

/* default 2-color deck */
.card.s-h,
.card.s-d {
  color: #c8102e;
}
.card.s-c,
.card.s-s {
  color: #1a1a1a;
}

/* 4-color deck (personal): clubs green, hearts red, diamonds gold, spades blue */
#app.four-color .card.s-c {
  color: #1b8f3a;
}
#app.four-color .card.s-h {
  color: #c8102e;
}
#app.four-color .card.s-d {
  color: #d4a620;
}
#app.four-color .card.s-s {
  color: #1f6fd6;
}

/* corner index: rank stacked over its suit pip, anchored top-left; the second
   copy is mirrored (rotated 180°) into the bottom-right corner. */
.card .cnr {
  position: absolute;
  top: 0.14em;
  left: 0.2em;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 0.84;
}
.card .cnr-br {
  top: auto;
  left: auto;
  right: 0.2em;
  bottom: 0.14em;
  transform: rotate(180deg);
}
.card .cr {
  font-size: 0.62em;
}
.card .cs {
  font-size: 0.46em;
  margin-top: 0.05em;
}
.card.back {
  /* personal skin via --card-back-img (applyCardBack); falls back to the built-in twill */
  background-image: var(--card-back-img, repeating-linear-gradient(45deg, #2a4a5e, #2a4a5e 4px, #24414f 4px, #24414f 8px));
  background-size: cover;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.06), 0 2px 5px rgba(0, 0, 0, 0.4);
}
.board-card {
  width: clamp(34px, 8.1cqw, 130px); /* PokerNow: big card ~8.1% of table width */
  font-size: clamp(16px, 3.9cqw, 62px);
}

/* run-it-again: stacked per-run boards at showdown (shrunk so up to 5 fit) */
.board.multi {
  flex-direction: column;
  gap: clamp(3px, 0.8cqw, 8px);
  align-items: center;
}
.board-row {
  display: flex;
  align-items: center;
  gap: clamp(2px, 0.7cqw, 6px);
}
.board.multi .card,
.board.multi .card-slot {
  width: clamp(22px, 4.6cqw, 74px);
  font-size: clamp(11px, 2.3cqw, 36px);
}
.board-row-n {
  min-width: 1.5em;
  text-align: right;
  font-size: clamp(8px, 1.5cqw, 13px);
  font-weight: 800;
  color: var(--muted-2);
}
.board-row-win {
  margin-left: 4px;
  max-width: 7em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: clamp(8px, 1.5cqw, 13px);
  font-weight: 700;
  color: var(--gold);
}

/* run-it-again vote prompt (takes over the table center while open) */
.runit-prompt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.62);
  border: 1px solid var(--gold);
  border-radius: 12px;
  padding: 11px 15px;
  box-shadow: var(--shadow);
  max-width: 94%;
}
.runit-title {
  font-size: clamp(11px, 2.6cqw, 15px);
  font-weight: 700;
  color: #fff;
  text-align: center;
}
.runit-btns {
  display: flex;
  gap: 6px;
}
.runit-btns .btn {
  min-width: 40px;
  padding: 8px 11px;
  font-weight: 800;
}
.runit-picks {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 10px;
}
.runit-pick {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--muted);
}
.runit-pick-val {
  font-weight: 700;
  color: var(--muted-2);
}
.runit-pick.set .runit-pick-val {
  color: var(--cta);
  font-weight: 800;
}
.runit-count {
  font-size: 12px;
  font-weight: 800;
  color: var(--gold);
}

/* hole cards live in the RIGHT portion of the seat plate (dual-use): margin-left:auto
   pins them to the plate's right edge while the avatar + name/chips keep the left.
   They appear only once dealt; opponents' are face-down, the hero's larger + face-up. */
.hole {
  flex: 0 0 auto;
  margin-left: auto;
  padding-left: 11px; /* buffer so the tilted card's corner can't reach back over the name/chips */
  display: flex;
  align-items: center;
  z-index: 0;
}
.hole .card {
  width: clamp(42px, 8.1cqw, 74px);
  /* glyph scale held proportional to width (~0.48x) at every clamp stop, so the
     card-width-to-font ratio is constant — that's what lets the em-based overlap
     below reveal a consistent slice of the back card at any size. */
  font-size: clamp(20px, 3.85cqw, 36px);
}
/* Self-sizing overlap: expressed in em (relative to each card's own font-size, which scales with
   the card), so the fan stays proportional at any card size. Capped at 1.05em so the back card's
   visible left slice stays ≈1em wide — enough to show the WIDEST rank index, the two-digit "10",
   even when it's the card behind (the index ends ~0.9em from the card's left edge). Tighter than
   this clips the "10". The 2nd card is later in the DOM so it paints on top; the gentle tilt lifts
   the back card's index to peek. */
.hole .card + .card {
  margin-left: -1.05em;
}
.hole .card:first-child {
  transform: rotate(-3deg);
  transform-origin: bottom center;
}
.hole .card:last-child {
  transform: rotate(3deg);
  transform-origin: bottom center;
}
.seat.me .hole .card {
  width: clamp(50px, 10.1cqw, 92px);
  font-size: clamp(24px, 4.9cqw, 45px);
}
/* post-hand: your own hole cards become clickable to flash one or both to the table.
   dashed gold = click to show; solid gold = already shown to everyone */
.hole.revealable .card.to-reveal {
  cursor: pointer;
  outline: 2px dashed var(--gold);
  outline-offset: 1px;
}
.hole.revealable .card.to-reveal:hover,
.hole.revealable .card.to-reveal:focus-visible {
  box-shadow: 0 0 0 2px var(--gold), 0 0 12px 2px rgba(240, 198, 74, 0.55);
  outline: none;
}
.hole.revealable .card.shown {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}
/* one-shot flip when you reveal a hidden card: it visibly turns from back to face, confirming
   to you exactly what the table now sees. Added once per reveal (not on every re-render). */
.hole.revealable .card.flip-in {
  animation: cardflip 0.42s cubic-bezier(0.2, 0.7, 0.3, 1) both;
  transform-origin: center;
}
@keyframes cardflip {
  from { transform: rotateY(82deg); opacity: 0.25; }
  to   { transform: rotateY(0); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hole.revealable .card.flip-in { animation: none; }
}
/* rabbit-hunt cards — the board that would have come; clearly reads as "didn't happen" */
.board-card.rabbit {
  opacity: 0.5;
  filter: saturate(0.55);
  outline: 1px dashed rgba(255, 255, 255, 0.4);
  outline-offset: 1px;
}

/* a folded player sits out the rest of the hand — fade + desaturate their plate
   so it clearly reads as "not in this hand" */
.seat.folded .hole,
.seat.folded .pod {
  opacity: 0.32;
  filter: grayscale(0.85);
}
/* sitting out — dimmed but clearly able to return (lighter than a fold) */
.seat.sitting-out .pod {
  opacity: 0.72;
}
.sit-toggle {
  appearance: none;
  display: inline-block;
  margin-top: 3px;
  padding: 2px 7px;
  font-size: 10px;
  font-weight: 700;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  background: var(--input-bg);
  color: var(--muted);
  cursor: pointer;
}
.sit-toggle:hover {
  border-color: var(--cta);
  color: var(--text);
}
.sit-toggle.on {
  border-color: var(--gold);
  color: var(--gold);
}
.sit-tag {
  background: rgba(255, 255, 255, 0.06);
  color: var(--muted-2);
}

/* active player: white plate + depleting timer bar */
.seat.acting .pod {
  background: #fbfbf7;
  border-color: #fff;
  transform: scale(1.06);
  animation: turnpulse 2s ease-in-out infinite;
}
@keyframes turnpulse {
  0%,
  100% {
    box-shadow: 0 0 0 3px var(--gold), 0 0 14px 4px rgba(240, 198, 74, 0.5), 0 4px 14px rgba(0, 0, 0, 0.5);
  }
  50% {
    box-shadow: 0 0 0 3px var(--gold), 0 0 30px 9px rgba(240, 198, 74, 0.72), 0 4px 14px rgba(0, 0, 0, 0.5);
  }
}
.seat.acting .name,
.seat.acting .stack {
  color: #16140c;
}
/* the light acting-seat plate needs a dark hand-value for contrast */
.seat.acting .hand-value {
  color: #16140c;
  border-top-color: rgba(0, 0, 0, 0.15);
}
/* time bank engaged — recolor the turn timer so it clearly reads as "extra time" */
.turn-timer.bank .timer-fill {
  background: #5ab0ff;
}
.turn-timer.bank .turn-clock {
  color: #5ab0ff;
}
.seat.acting .avatar {
  background: linear-gradient(180deg, #e9e9e2, #cfcfc6);
  color: #1a1a1a;
}
.turn-timer {
  margin-top: 5px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 9px;
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.timer-bar {
  flex: 1;
  height: 8px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.5);
  overflow: hidden;
  position: relative; /* anchor for the low-time marker line */
}
/* the line on the bar where the low-time countdown (10s left) begins */
.timer-mark {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.5);
}
.timer-fill {
  height: 100%;
  width: 100%;
  background: hsl(120, 80%, 48%); /* JS recolors green -> yellow -> red as the clock runs down */
  transition: width 0.2s linear, background 0.2s linear;
}
.turn-clock {
  min-width: 22px;
  text-align: center;
  font-size: 17px;
  font-weight: 800;
  color: var(--gold);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.65); /* legible on any felt */
}

/* bet chip out in front of the seat */
.bet-chip {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: #f3ffce;
  color: #14210f;
  font-weight: 800;
  font-size: 12px;
  padding: 3px 9px;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(40, 101, 67, 0.4);
  white-space: nowrap;
  z-index: 2;
}
.bet-chip::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #ffd86b, #d99a2b);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
}
.seat.upper .bet-chip,
.seat.upper .check-chip,
.seat.upper .win-badge {
  top: calc(100% + 10px);
}
.seat.lower .bet-chip,
.seat.lower .check-chip,
.seat.lower .win-badge {
  bottom: calc(100% + 16px); /* clear the top-border stat slots (they straddle ~11px above the plate) */
}

/* "checked" marker — same slot as the bet-chip (a checked seat has nothing wagered), but muted with
   a green tick so it reads as "acted, no bet" rather than chips on the felt. Positioned by the shared
   .seat.upper/.lower rules above; the seat is lifted via .seat:has(.check-chip) so it clears plates. */
.check-chip {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgba(12, 16, 13, 0.85);
  color: #d6ead9;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid rgba(120, 200, 150, 0.55);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  white-space: nowrap;
  z-index: 2;
}
.check-chip::before {
  content: "✓";
  font-weight: 800;
  color: #6fd699;
}

/* shown on the felt in place of the bet-chip once the hand is won (positioned by the shared
   .seat.upper/.lower rules below) */
.win-badge {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.5);
  color: #ffe488;
  font-weight: 800;
  font-size: 16px;
  padding: 4px 13px;
  border-radius: 999px;
  border: 1px solid rgba(255, 222, 120, 0.9);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45), 0 0 26px 8px rgba(255, 226, 120, 0.95);
  text-shadow: 0 0 9px rgba(255, 226, 120, 0.85);
  white-space: nowrap;
}
.seat.won .pod {
  box-shadow: 0 0 0 2px var(--cta), 0 4px 14px rgba(0, 0, 0, 0.5);
}
/* the winner's avatar picks up a subtle gold glow to match the win badge */
.seat.won .avatar {
  box-shadow: 0 0 13px 3px rgba(250, 218, 112, 0.55);
}

.tag.allin {
  margin-top: 2px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: #ffd36b;
}
.rebuy {
  margin-top: 4px;
  font-size: 13px;
  font-weight: 700;
  color: var(--cta);
  background: rgba(54, 168, 106, 0.12);
  border: 1px solid rgba(54, 168, 106, 0.5);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
}
.tag.bot-tag {
  margin-top: 2px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: #8fd0ff;
}
.seat.bot .avatar {
  background: linear-gradient(180deg, #2b4a63, #1f3a4f);
  color: #cfe8ff;
}

/* host bot selector (sidebar) */
.side-bots {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid #282828;
}
.bots-label {
  font-size: 13px;
  color: var(--muted);
}
.bot-select {
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
}
.side-botspeed {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid #282828;
}
.speed-slider {
  flex: 1;
  accent-color: var(--cta);
}
.speed-val {
  min-width: 52px;
  text-align: right;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

/* per-bot temperament sliders (host only) */
.side-aggro {
  padding: 10px 14px;
  border-bottom: 1px solid #282828;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 230px;
  overflow-y: auto;
}
.side-aggro-title {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.aggro-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 3px;
}
.aggro-name {
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.aggro-tag {
  font-size: 11px;
  font-weight: 700;
  color: var(--gold);
  flex: 0 0 auto;
  margin-left: 8px;
}
.aggro-track {
  display: flex;
  align-items: center;
  gap: 7px;
}
.aggro-track .aggro-slider {
  flex: 1;
  accent-color: var(--cta);
}
.aggro-end {
  font-size: 9.5px;
  letter-spacing: 0.04em;
  color: var(--muted-2);
}

/* per-bot 2-axis style pad (host only): tight/loose × passive/aggressive */
.style-row { padding: 4px 0 12px; }
.style-grid {
  display: inline-grid;
  grid-template-columns: 12px 118px 12px;
  grid-template-rows: 13px 118px 13px;
  grid-template-areas: ".  top  ." "left pad right" ".  bot  .";
  align-items: center; justify-items: center;
  column-gap: 4px; margin-top: 5px;
}
.style-pad {
  grid-area: pad; width: 118px; height: 118px; position: relative;
  border: 1px solid var(--line-2); border-radius: 8px;
  cursor: crosshair; touch-action: none;
  background-image:
    linear-gradient(to right, transparent calc(50% - 0.5px), var(--line) calc(50% - 0.5px), var(--line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
    linear-gradient(to bottom, transparent calc(50% - 0.5px), var(--line) calc(50% - 0.5px), var(--line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
    radial-gradient(circle at 50% 50%, rgba(47, 149, 96, 0.12), transparent 72%);
}
.style-pad:focus-visible { outline: 2px solid var(--cta); outline-offset: 2px; }
.style-dot {
  position: absolute; width: 14px; height: 14px; border-radius: 50%;
  background: var(--gold); border: 2px solid #161616;
  transform: translate(-50%, -50%); pointer-events: none;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.style-ax { font-size: 9px; letter-spacing: 0.05em; color: var(--muted-2); text-transform: uppercase; white-space: nowrap; }
.style-ax-top { grid-area: top; }
.style-ax-bot { grid-area: bot; }
.style-ax-left { grid-area: left; writing-mode: vertical-rl; transform: rotate(180deg); }
.style-ax-right { grid-area: right; writing-mode: vertical-rl; }

.pot .street {
  /* derive from the felt-ink token (which flips dark on a light felt) so the "· Flop/Turn" suffix
     stays legible on any host felt — a fixed --muted gray washed out on light cloth */
  color: color-mix(in srgb, var(--felt-ink, #fff) 68%, transparent);
  font-weight: 600;
}
.center-msg.win {
  color: #fff;
  border-color: #ffe488;
  background: rgba(0, 0, 0, 0.5);
  font-weight: 800;
  font-size: 14px;
  box-shadow: 0 0 26px 9px rgba(255, 226, 120, 1);
  text-shadow: 0 0 10px rgba(255, 226, 120, 0.75);
}
.center-msg.gameover { display: flex; flex-direction: column; align-items: center; gap: 11px; }
.gameover-title { font-size: 18px; font-weight: 800; color: var(--gold); letter-spacing: 0.01em; }
.gameover-sub { font-size: 13px; color: var(--muted); font-weight: 600; }
.gameover-btns { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; align-items: stretch; }
/* both end-of-game buttons share one box (same size, shape, baseline); only the fill
   differs — Play Again primary, Reset neutral. Overrides the lone-CTA "hero" treatment
   that .center-action .btn-primary gives the lobby Start button (big padding + ring +
   an 8px downward shift), which otherwise made the pair mismatched + misaligned. */
.gameover-btns .btn {
  flex: 0 0 auto;
  min-width: 140px;
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 700;
  border-radius: 10px;
  position: relative;
  top: 0;
  box-shadow: none;
}
/* Reset is destructive — a persistent red tint (not solid red, which would fight the
   green Play Again primary): reddish fill + border + text at rest, deepening on hover. */
.gameover-btns .btn.danger {
  background: rgba(229, 104, 95, 0.13);
  border-color: rgba(229, 104, 95, 0.5);
  color: #f0928a;
}
.gameover-btns .btn.danger:hover {
  background: rgba(229, 104, 95, 0.2);
  border-color: var(--bad);
}

/* ---- cash ledger: standings + settle-up (shared with the game-over settle block) ---- */
.ledger-table { display: grid; gap: 1px; }
.settle-box { margin-top: 14px; padding: 12px 14px; border-radius: 12px; background: rgba(103, 201, 139, 0.08); border: 1px solid rgba(103, 201, 139, 0.25); }
.settle-title { font-weight: 700; margin-bottom: 8px; opacity: 0.85; }
.settle-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.settle-from { font-weight: 700; }
.settle-arrow { opacity: 0.55; font-size: 0.9em; }
.settle-to { font-weight: 700; color: var(--good, #67c98b); }
.settle-amt { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 700; }
.settle-warn { margin-top: 8px; font-size: 0.85rem; color: var(--bad, #e5685f); }
.settle-nudge { margin-top: 14px; font-size: 0.9rem; opacity: 0.7; text-align: center; }

/* ---- HUD Tools dropdown ---- */
.hud-controls { position: relative; }
.hud-menu { position: absolute; top: calc(100% + 8px); left: 0; display: flex; flex-direction: column; min-width: 150px; padding: 5px; border-radius: 12px; background: #14181a; border: 1px solid rgba(255, 255, 255, 0.14); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); z-index: 60; }
.hud-menu-item { display: block; width: 100%; text-align: left; padding: 10px 12px; border: 0; background: none; color: inherit; border-radius: 8px; cursor: pointer; font: inherit; }
.hud-menu-item:hover { background: rgba(255, 255, 255, 0.08); }

/* clicking a plate pops that player's session-stats summary; host kick is on the corner ✕, whose
   own menu (below) is mounted on <body> and fixed-positioned from the plate. */
.avatar.clickable { cursor: pointer; }
/* small per-player session-stats summary modal (popped by clicking a plate) */
.psum-overlay { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; background: rgba(0, 0, 0, 0.5); }
.psum-card { width: min(300px, 92vw); background: #14181a; border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 14px; box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6); overflow: hidden; }
.psum-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px 14px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
.psum-name { font-size: 15px; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.psum-close { flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%; border: 0; background: rgba(255, 255, 255, 0.08); color: var(--muted); cursor: pointer; display: grid; place-items: center; font-size: 12px; }
.psum-close:hover { background: rgba(255, 255, 255, 0.16); color: var(--text); }
.psum-body { padding: 6px 14px 12px; }
.psum-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.05); font-size: 13px; }
.psum-row:last-child { border-bottom: 0; }
.psum-k { color: var(--muted); min-width: 0; }
.psum-v { font-weight: 700; font-variant-numeric: tabular-nums; flex: 0 0 auto; white-space: nowrap; text-align: right; }
.psum-v.up { color: var(--net-up); }
.psum-v.down { color: var(--net-down); }
.kick-menu {
  position: fixed;
  transform: translateX(-50%);
  z-index: 70;
  min-width: 134px;
  padding: 6px;
  border-radius: 11px;
  background: #14181a;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kick-menu-name {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-align: center;
  padding: 3px 8px 6px;
  margin-bottom: 3px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}
.kick-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 11px;
  border: 0;
  background: none;
  color: inherit;
  border-radius: 7px;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}
.kick-menu-item:hover { background: rgba(255, 255, 255, 0.08); }
.kick-menu-item.danger { color: #ff9c93; }
.kick-menu-item.danger:hover { background: rgba(180, 50, 40, 0.28); }

/* ---- game-over: a contained, scrollable end-screen overlay over the felt ---- */
.gameover-overlay { position: absolute; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; padding: 18px; background: rgba(6, 8, 7, 0.62); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.gameover-card { display: flex; flex-direction: column; align-items: center; gap: 16px; width: min(540px, 100%); max-height: 100%; overflow-y: auto; padding: 24px 22px; background: var(--panel, #12150f); border: 1px solid var(--gold); border-radius: 20px; box-shadow: 0 22px 60px rgba(0, 0, 0, 0.6); }
.gameover-card .gameover-title { font-size: 22px; text-align: center; }
.gameover-settle { width: 100%; margin: 0; }
.gameover-sec-title { font-weight: 700; opacity: 0.8; margin-bottom: 6px; text-align: center; }
.gameover-awards { display: flex; flex-direction: column; gap: 12px; width: 100%; margin: 0; }
.gameover-award { display: flex; align-items: center; gap: 16px; width: 100%; min-width: 0; box-sizing: border-box; padding: 16px 20px; border-radius: 18px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); }
.gameover-award .ga-art, .gameover-award .ga-art .badge-art, .gameover-award .ga-art svg { width: 88px; height: 88px; flex: 0 0 88px; }
.gameover-award .ga-who { display: flex; align-items: center; gap: 12px; min-width: 0; }
.gameover-award .ga-who .avatar { width: 56px; height: 56px; font-size: 1.5rem; flex: 0 0 56px; }
.gameover-award .ga-title { font-weight: 800; font-size: 1.1rem; }
.gameover-award .ga-name { opacity: 0.9; }
.gameover-award .ga-sub { font-size: 0.85rem; opacity: 0.7; }
.gameover-awards-loading { opacity: 0.6; margin: 4px 0; }
@media (max-width: 560px) { .gameover-award { flex-direction: column; text-align: center; min-width: 0; } }

/* ---- sidebar (menu + game log + chat) ---- */
.sidebar {
  flex: 0 0 268px;
  width: 268px;
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  border-left: 1px solid #282828;
}
.side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid #282828;
}
.side-brand {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.side-brand .spade {
  color: var(--cta);
}
.side-brand .home-logo {
  height: 1.8em;
  width: auto;
}
/* ---- table HUD: room/host/blinds badge + symbol controls, floated over the felt ---- */
.table-hud {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top, 0px));
  left: calc(10px + env(safe-area-inset-left, 0px));
  right: calc(10px + env(safe-area-inset-right, 0px));
  z-index: 7; /* above seats (z6) so an upper acting seat can't tie/overlap the HUD */
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  pointer-events: none; /* clicks fall through to the felt except on the badge + buttons */
}
.hud-info {
  position: relative;
  pointer-events: auto;
  max-width: 48%;
  padding: 7px 22px 7px 11px;
  font-size: 12px;
  line-height: 1.25;
  background: rgba(10, 12, 11, 0.62);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  backdrop-filter: blur(6px);
}
.hud-info-rows { display: flex; flex-direction: column; gap: 3px; }
/* collapse toggle (top-right caret); collapsed shrinks the panel to just this button */
.hud-collapse {
  position: absolute;
  top: 3px;
  right: 5px;
  width: 16px;
  height: 16px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 11px;
  line-height: 1;
  display: grid;
  place-items: center;
}
.hud-collapse:hover { color: var(--text); }
.hud-info.collapsed { padding: 3px; max-width: none; }
.hud-info.collapsed .hud-info-rows { display: none; }
.hud-info.collapsed .hud-collapse { position: static; width: 22px; height: 22px; font-size: 12px; }
.hud-info-row {
  display: flex;
  align-items: baseline;
  gap: 7px;
  white-space: nowrap;
}
.hud-label {
  flex: 0 0 auto;
  width: 46px;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--muted);
}
.hud-info .num,
.hud-host-name {
  color: var(--text);
  font-weight: 700;
}
.hud-host-name {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 150px;
}
.hud-code {
  color: var(--text);
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.hud-code:hover {
  color: var(--cta);
}
.hud-esc {
  color: var(--gold);
  font-weight: 800;
}
/* host-only inline quick-edit of essential table settings, inside the info badge —
   stacked one-per-row down, in line with the ROOM/HOST rows */
.hud-quick {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.hud-q-input {
  width: 64px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line-2);
  border-radius: 5px;
  color: var(--text);
  font-weight: 700;
  font-size: 12px;
  padding: 2px 5px;
  outline: none;
}
.hud-q-input:focus-visible {
  border-color: var(--cta);
  outline: 2px solid var(--cta); /* keyboard focus needs a real ring, not just a faint border tint */
  outline-offset: 1px;
}
/* SB/BB locked because a Linear/Exponential formula now drives the blinds — gold dashed read-only */
.hud-q-input:disabled {
  opacity: 0.85;
  cursor: not-allowed;
  color: var(--gold);
  border-style: dashed;
  border-color: var(--gold);
  background: rgba(240, 198, 74, 0.08);
}
@keyframes blind-bump { 0%, 100% {} 35% { color: var(--gold); text-shadow: 0 0 12px rgba(240, 198, 74, 0.9); } }
.blind-bump { animation: blind-bump 0.7s ease; }
.hud-q-input[type='number']::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.hud-q-input[type='number'] {
  -moz-appearance: textfield;
}
.hud-q-sel {
  width: auto;
  min-width: 88px;
  padding: 2px 4px;
  cursor: pointer;
}
.hud-controls {
  pointer-events: auto;
  display: flex;
  align-items: stretch; /* uniform button height + full-height group dividers */
  gap: 7px;
}
.hud-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 48px;
  padding: 6px 9px 5px;
  border-radius: 11px;
  font-size: 17px; /* drives the icon size (svg is 1.2em) */
  line-height: 1;
  color: var(--text);
  background: rgba(10, 12, 11, 0.62);
  border: 1px solid var(--line-2);
  cursor: pointer;
  backdrop-filter: blur(6px);
  transition: transform 0.08s ease, background 0.15s ease, border-color 0.15s ease;
}
.hud-btn-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--muted);
}
/* thin divider between the Info | Config | Leave groups */
.hud-sep {
  align-self: stretch;
  width: 1px;
  margin: 5px 1px;
  background: var(--line-2);
}
.hud-btn:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.25);
  transform: translateY(-1px);
}
.hud-btn:active {
  transform: translateY(0);
}
.hud-btn:disabled {
  opacity: 0.4;
  cursor: default;
  transform: none;
}
.hud-btn:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 2px;
}
.hud-btn.hud-cog {
  color: #c4c8ce; /* silver */
}
.hud-btn.hud-ledger {
  color: var(--gold); /* yellow */
}
/* leave-table button reads red at rest (the door icon inherits this color), not just on hover */
.hud-btn.danger {
  color: var(--bad);
  border-color: #5a2b2b;
  background: rgba(46, 22, 21, 0.62);
}
.hud-btn.danger:hover {
  color: #ff8077;
  background: #3a1b1a;
  border-color: #7a3735;
}
.btn.danger {
  color: #f0928a;
}
.btn.danger:hover {
  border-color: #5a2b2b;
  background: #1f1413;
}
.side-log {
  flex: 2;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 12px 14px;
  overflow: hidden;
  border-top: 1px solid #282828;
}
.side-log-title {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 8px;
}
.side-log-body {
  flex: 1;
  overflow-y: auto;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.5;
}
.side-chat {
  flex: 3;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 14px;
}
.side-chat-title {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.chat-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  line-height: 1.4;
  padding: 8px 10px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--line-2);
  border-radius: 8px;
}
.chat-empty {
  color: var(--muted-2);
}
/* settle-up ledger modal */
.ledger-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 8px 0 2px;
  max-height: 50vh;
  overflow-y: auto;
}
.ledger-row {
  display: grid;
  grid-template-columns: 1fr 70px 76px 70px;
  gap: 10px;
  align-items: baseline;
  padding: 5px 4px;
  border-bottom: 1px solid var(--line);
}
.ledger-row .num {
  text-align: right;
}
.ledger-head {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
  border-bottom-color: var(--line-2);
}
.ledger-name {
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ledger-net.up {
  color: var(--net-up);
}
.ledger-net.down {
  color: var(--net-down);
}
.ledger-empty {
  color: var(--muted);
  padding: 10px 4px;
}
/* pre-action (auto-action) toggles shown while it's not your turn */
.pre-actions {
  display: flex;
  gap: 6px;
  margin-top: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.pre-btn.on {
  border-color: var(--cta);
  color: var(--cta);
  background: rgba(54, 168, 106, 0.14);
}
.chat-msg {
  color: var(--text);
  word-break: break-word;
}
.chat-name {
  font-weight: 700;
  color: var(--gold);
  margin-right: 5px;
}
/* hand-result box — one box per finished hand, with 1st/2nd/3rd medal rows */
.chat-result {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 3px 0 12px;
  padding: 6px 8px;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.03);
}
/* a clear divider line after each hand's result, separating one hand from the next */
.chat-result::after {
  content: '';
  position: absolute;
  left: 2px;
  right: 2px;
  bottom: -7px;
  height: 1px;
  background: rgba(255, 255, 255, 0.16);
}
.chat-result-title {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.place {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding-left: 6px;
  border-left: 3px solid transparent;
}
.place-medal {
  font-size: 13px;
  line-height: 1;
}
.place-name {
  font-weight: 700;
}
.place-hand {
  margin-left: auto;
  align-self: center;
  color: var(--muted);
  font-size: 11px;
}
.place-1 {
  border-left-color: var(--medal-gold);
}
.place-1 .place-name {
  color: var(--medal-gold);
}
.place-2 {
  border-left-color: var(--medal-silver);
}
.place-2 .place-name {
  color: var(--medal-silver);
}
.place-3 {
  border-left-color: var(--medal-bronze);
}
.place-3 .place-name {
  color: var(--medal-bronze);
}
.chat-input {
  width: 100%;
  background: var(--input-bg);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 13px;
}
.chat-input:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 1px;
  border-color: var(--cta);
}
.chat-box {
  position: relative;
}
.chat-row {
  display: flex;
  gap: 6px;
  align-items: stretch;
}
.chat-row .chat-input {
  flex: 1;
  width: auto;
  min-width: 0;
}
.chat-emoji-btn {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  background: var(--input-bg);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  color: var(--text);
}
.chat-emoji-btn:hover {
  border-color: var(--cta);
}
.chat-emoji-pop {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 6px);
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  z-index: 30;
}
.chat-emoji-pop.open {
  display: block;
}
/* soundboard popover — reuses the .chat-emoji-pop chrome; emotes render as labeled tiles */
.sb-title {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin: 0 2px 8px;
}
.sb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
}
.sb-key {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border: 1px solid var(--line-2);
  background: var(--input-bg);
  border-radius: 8px;
  color: var(--text);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.1s ease, background 0.1s ease, transform 0.1s ease;
}
.sb-key:hover {
  border-color: var(--cta);
  background: var(--btn-hover);
}
.sb-key:active {
  transform: scale(0.97);
}
.sb-key:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}
.sb-key .sb-emoji {
  flex: 0 0 auto;
  font-size: 17px;
  line-height: 1;
}
.sb-key .sb-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* connection pill (sidebar header) */
.conn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--muted);
}
.conn .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--off);
}
.conn[data-s="open"] .dot {
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(55, 208, 127, 0.18);
}
.conn[data-s="connecting"] .dot,
.conn[data-s="reconnecting"] .dot {
  background: var(--warn);
  animation: pulse 1s infinite;
}
.conn[data-s="closed"] .dot {
  background: var(--bad);
}
@keyframes pulse {
  50% {
    opacity: 0.3;
  }
}

/* ============================================================================
   OVERLAY / MODAL / TOAST
   ============================================================================ */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.66);
  display: grid;
  place-items: center;
  z-index: 50;
  padding: 20px;
  backdrop-filter: blur(3px);
}
.modal {
  width: min(360px, 100%);
  background: linear-gradient(180deg, var(--panel), var(--panel-2));
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 22px;
  box-shadow: var(--shadow);
  /* Never grow past the viewport, and scroll the whole modal if content would — otherwise on a short
     / landscape screen the title and the Done/Close button overflow the centered modal and become
     unreachable (only the inner body region scrolled before). */
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
}
.modal h3 {
  margin: 0 0 4px;
  font-size: 18px;
}
.modal p {
  margin: 0 0 16px;
  color: var(--muted);
  font-size: 13px;
}
.modal .actions {
  display: flex;
  gap: 8px;
  margin-top: 18px;
}
.modal .actions .btn {
  flex: 1;
}
/* sit-down / buy-in modal — give each labeled section room to breathe so the chips
   field (auto-focused, with its focus glow) and the avatar/emoji pickers never crowd
   the label beneath them. Labels still hug their own control (their 6px margin). */
.modal-buyin .field { margin-bottom: 16px; }
.modal-buyin .avatar-row { margin: 6px 0 16px; }

#toasts {
  position: fixed;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 60;
  pointer-events: none;
}
.toast {
  background: var(--panel);
  border: 1px solid var(--line-2);
  color: var(--text);
  padding: 10px 16px;
  border-radius: 10px;
  font-size: 13px;
  box-shadow: var(--shadow);
  animation: rise 0.2s ease;
}
.toast.bad {
  border-color: #5a2b2b;
  background: #1f1413;
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* ============================================================================
   RESPONSIVE — stack the sidebar under the table on narrow screens
   ============================================================================ */
@media (max-width: 860px) {
  .stage {
    width: 88%;
    max-height: 90%;
  }
  .room {
    flex-direction: column;
  }
  /* Dock the action controls as a static full-width bar as soon as the layout goes single-column
     (the table is full-width here) — otherwise the floating bottom-right cluster overlaps a lower
     seat between 561-860px. */
  .action-cluster {
    position: static;
    right: auto;
    bottom: auto;
    width: 100%;
    min-width: 0; /* full-width centered bar doesn't need the desktop steady-footprint floor */
    align-items: center;
    gap: 7px;
    padding: 7px 8px calc(7px + env(safe-area-inset-bottom, 0px));
  }
  .action-cluster .frac,
  .action-cluster .action-row,
  .action-cluster .pre-actions {
    justify-content: center;
    flex-wrap: wrap;
  }
  .action-cluster .bet-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
  }
  .sidebar {
    flex: 0 0 auto;
    width: auto;
    max-height: 46vh; /* table keeps the top half; the rest scrolls in one region */
    overflow-y: auto;
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .side-head {
    flex-direction: row;
  }
  /* keep the game log + chat (hand results, messages) reachable on phones — let the
     whole sidebar be the single scroll region instead of hiding them */
  .side-log,
  .side-chat {
    flex: 0 0 auto;
  }
  .side-log-body,
  .chat-log {
    max-height: none;
    overflow: visible;
  }
}
@media (max-width: 560px) {
  .stage {
    width: 84%;
    aspect-ratio: 4 / 5;
    max-height: 92%;
  }
  /* shrink the HUD so the badge + control buttons still fit a narrow phone */
  .table-hud {
    top: calc(6px + env(safe-area-inset-top, 0px));
    left: calc(6px + env(safe-area-inset-left, 0px));
    right: calc(6px + env(safe-area-inset-right, 0px));
    gap: 6px;
  }
  .hud-info {
    padding: 5px 20px 5px 8px;
    font-size: 10.5px;
  }
  .hud-label {
    width: 38px;
  }
  .hud-controls {
    gap: 5px;
  }
  /* icon-only on phones: drop the text labels + group dividers, keep the compact 32px circles */
  .hud-btn {
    width: 32px;
    height: 32px;
    min-width: 0;
    padding: 0;
    border-radius: 50%;
    font-size: 14px;
    gap: 0;
  }
  .hud-btn-label {
    display: none;
  }
  .hud-sep {
    display: none;
  }
  /* the action cluster already docks as a full-width bar at <=860px (single-column layout); here we
     just narrow the slider + seat plates for phone widths */
  .bet-slider {
    width: min(260px, 68vw);
  }
  /* tighten the seat plates a touch so the side seats overhang the felt edge less */
  .seat {
    width: clamp(118px, 30cqw, 184px);
  }
}

/* ---- table settings modal + game log lines ---- */
.modal-settings {
  width: min(880px, 94vw); /* roomy so the card-back grid populates many per row */
}
.set-row {
  margin-bottom: 12px;
}
.set-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 12px;
}
.set-grid .set-row {
  margin-bottom: 0;
}
/* phones: the two-up settings grid is too cramped — stack to one column */
@media (max-width: 430px) {
  .set-grid {
    grid-template-columns: 1fr;
  }
}
.set-hint {
  margin: 4px 0 0 2px;
  font-size: 11px;
  color: var(--muted-2);
}
.set-check-row {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 14px;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
}
.set-check {
  width: 17px;
  height: 17px;
  accent-color: var(--cta);
  cursor: pointer;
  flex: 0 0 auto;
}

/* ---- table colors modal ---- */
.modal-theme {
  width: min(420px, 100%);
}
.theme-section-label {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin: 14px 0 8px;
}
.theme-presets {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.theme-preset {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border: 1px solid var(--line-2);
  border-radius: 9px;
  background: var(--panel);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.theme-preset:hover {
  border-color: rgba(255, 255, 255, 0.28);
  background: var(--btn-hover);
}
.theme-preset-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* preset felt + wood shown as a small split lozenge (felt laps over the wood) */
.theme-chip {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.4);
}
.theme-chip.felt {
  position: relative;
  z-index: 1;
  margin-right: -9px;
}
.theme-chip.rail {
  width: 15px;
}
.theme-pickers {
  display: flex;
  gap: 10px;
}
.theme-picker {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--muted);
}
.theme-picker-label {
  letter-spacing: 0.04em;
}
.theme-picker-input {
  width: 100%;
  height: 38px;
  padding: 2px;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  background: var(--input-bg);
  cursor: pointer;
}
.theme-picker-input::-webkit-color-swatch {
  border: none;
  border-radius: 5px;
}
.theme-picker-input::-webkit-color-swatch-wrapper {
  padding: 0;
}
.modal-theme .actions {
  flex-wrap: wrap;
}
.modal-theme .actions .btn {
  flex: 1 1 auto;
}

/* ============================================================================
   REDUCED MOTION — honor the OS "reduce motion" preference
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
  .seat.acting .pod {
    animation: none;
    transform: none;
    box-shadow: 0 0 0 3px var(--gold), 0 0 16px 5px rgba(240, 198, 74, 0.55), 0 4px 14px rgba(0, 0, 0, 0.5);
  }
  .conn[data-s="connecting"] .dot,
  .conn[data-s="reconnecting"] .dot {
    animation: none;
  }
  .toast {
    animation: none;
  }
  .seat,
  .btn,
  .pod,
  .pod-empty,
  .timer-fill {
    transition: none;
  }
}

/* ---- victory flash: a giant WIN flashes across the screen on a game win ---- */
.win-flash {
  position: fixed;
  inset: 0;
  z-index: 45; /* above the table, BELOW modals (overlay z-50) + toasts (z-60) so it can't bury them */
  pointer-events: none;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.win-flash::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 45%, rgba(240, 198, 74, 0.22), transparent 62%);
  animation: winglow 2s ease-out forwards;
}
.win-flash .win-word {
  position: relative;
  z-index: 2; /* keep the words above the confetti + sweep */
  max-width: 92vw;
  text-align: center;
  font-weight: 900;
  font-size: clamp(46px, 13vw, 210px);
  line-height: 0.95;
  letter-spacing: 0.02em;
  /* gold gradient clipped to the glyphs (light top -> deep gold bottom) */
  background: linear-gradient(180deg, #fff7d4 0%, #ffe08a 30%, #f0c64a 52%, #e0a522 72%, #b9790f 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  /* drop-shadow (not text-shadow) so the glow follows the gradient-filled text */
  filter: drop-shadow(0 0 16px rgba(240, 198, 74, 0.85)) drop-shadow(0 0 46px rgba(240, 198, 74, 0.5))
    drop-shadow(0 6px 24px rgba(0, 0, 0, 0.55));
  animation: winword 2s cubic-bezier(0.2, 0.9, 0.2, 1) forwards;
}
.win-flash .win-sweep {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -55%;
  width: 50%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.16) 42%, rgba(255, 255, 255, 0.42) 50%, rgba(255, 255, 255, 0.16) 58%, transparent);
  filter: blur(2px);
  animation: winsweep 1.15s ease-in forwards;
}
@keyframes winword {
  0% { opacity: 0; transform: translateY(0) scale(0.4) rotate(-7deg); }
  12% { opacity: 1; transform: translateY(0) scale(1.2) rotate(-2deg); }
  24% { transform: translateY(0) scale(0.97) rotate(0deg); }
  34% { transform: translateY(0) scale(1.05) rotate(0deg); }
  44% { transform: translateY(0) scale(1) rotate(0deg); animation-timing-function: ease-out; }
  /* two settling hops before it fades — up decelerates, down accelerates */
  54% { transform: translateY(-8%) scale(1) rotate(0deg); animation-timing-function: ease-in; }
  64% { transform: translateY(0) scale(1) rotate(0deg); animation-timing-function: ease-out; }
  71% { transform: translateY(-3.5%) scale(1) rotate(0deg); animation-timing-function: ease-in; }
  78% { opacity: 1; transform: translateY(0) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translateY(0) scale(1.32) rotate(0deg); }
}
@keyframes winsweep {
  0% { left: -55%; opacity: 0; }
  18% { opacity: 1; }
  100% { left: 105%; opacity: 0; }
}
@keyframes winglow {
  0% { opacity: 0; }
  12% { opacity: 1; }
  60% { opacity: 0.5; }
  100% { opacity: 0; }
}
.win-flash .confetti-bit {
  position: absolute;
  border-radius: 1px;
  will-change: transform, opacity;
  animation-name: confettifly;
  animation-timing-function: cubic-bezier(0.25, 0.6, 0.45, 1);
  animation-fill-mode: forwards;
}
@keyframes confettifly {
  0% { transform: translate3d(0, 0, 0) rotate(0turn); opacity: 1; }
  85% { opacity: 1; }
  100% { transform: translate3d(var(--dx, 0), var(--dy, 120vh), 0) rotate(var(--spin, 3turn)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .win-flash .win-word { animation-name: winfade; transform: none; }
  .win-flash .win-sweep,
  .win-flash .confetti-bit { display: none; }
}
@keyframes winfade {
  0% { opacity: 0; }
  15% { opacity: 1; }
  72% { opacity: 1; }
  100% { opacity: 0; }
}

/* ---- settings hub (tabs + appearance) ---- */
.set-tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin: 2px 0 14px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 10px;
}
.set-tab {
  appearance: none;
  border: 1px solid var(--line-2);
  background: var(--panel);
  color: var(--muted);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.set-tab.on {
  border-color: var(--cta);
  color: var(--cta);
  background: rgba(54, 168, 106, 0.12);
}
.set-body {
  max-height: 60vh;
  overflow-y: auto;
}
.set-section-label {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin: 14px 0 8px;
}
.wood-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(74px, 1fr));
  gap: 8px;
}
.wood-cell {
  appearance: none;
  border: 1px solid var(--line-2);
  background: var(--panel);
  border-radius: 8px;
  padding: 4px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.wood-cell img {
  width: 100%;
  height: 46px;
  object-fit: cover;
  border-radius: 5px;
  display: block;
}
.wood-cell .wood-name {
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wood-cell.cur {
  border-color: var(--cta);
  box-shadow: 0 0 0 1px var(--cta);
}
.wood-cell.cur .wood-name {
  color: var(--cta);
  font-weight: 700;
}
/* card-back picker — card-shaped previews (the SVG back itself), mirrors .wood-cell */
.cardback-cell {
  appearance: none;
  border: 1px solid var(--line-2);
  background: var(--panel);
  border-radius: 8px;
  padding: 4px;
  cursor: pointer;
}
.cardback-cell img {
  width: 100%;
  aspect-ratio: 41 / 50;
  object-fit: cover;
  border-radius: 5px;
  display: block;
}
.cardback-cell.cur {
  border-color: var(--cta);
  box-shadow: 0 0 0 1px var(--cta);
}
/* card-back gallery grouped by provenance (source) then color family */
.cardback-search {
  width: 100%;
  margin: 8px 0 2px;
  padding: 7px 10px;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  background: var(--input-bg, #161616);
  color: var(--text);
  font: inherit;
  font-size: 13px;
}
.cardback-search:focus-visible {
  outline: none;
  border-color: var(--cta);
  box-shadow: 0 0 0 1px var(--cta);
}
.cardback-groups {
  display: flex;
  flex-direction: column;
}
.cardback-src {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text);
  margin: 14px 0 2px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.cardback-src:first-child {
  border-top: none;
  padding-top: 0;
  margin-top: 4px;
}
.cardback-hue {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  color: var(--muted);
  margin: 9px 0 6px 2px;
}
.cardback-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
  flex: 0 0 auto;
}

/* seat-symbol emoji picker (sit-down modal) — scrollable grid, mirrors .wood-gallery */
.emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
  gap: 5px;
  max-height: 180px;
  overflow-y: auto;
  padding: 2px;
}
.emoji-btn {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 7px;
  padding: 4px 0;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
}
.emoji-btn:hover {
  background: rgba(255, 255, 255, 0.07);
}
.emoji-btn.none {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-2);
}
.emoji-btn.sel {
  border-color: var(--cta);
  box-shadow: 0 0 0 1px var(--cta);
}
.toggle-pills {
  display: inline-flex;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  overflow: hidden;
}
.toggle-pills .pill {
  appearance: none;
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.toggle-pills .pill.on {
  background: rgba(54, 168, 106, 0.2);
  color: var(--cta);
}

/* ============================================================================
   HAND HISTORY — last-hand teaser link + the full transcript / showdown modal
   ============================================================================ */
/* text-only "Full hand history →" link under the single game-log entry */
.log-history-link {
  appearance: none;
  background: none;
  border: none;
  margin: 6px 0 2px;
  padding: 0 6px;
  font: inherit;
  font-size: 12px;
  color: var(--muted-2);
  cursor: pointer;
}
.log-history-link:hover {
  color: var(--cta);
  text-decoration: underline;
}

/* wide, scrollable modal — fits 8 players × the aligned grid (hole + 5 best = 7 cards) + the transcript */
.modal-history {
  width: min(900px, 100%);
  --hhc: 36px; /* hand-history card width; drives .card.hh + the showdown grid columns */
}
.hh-pick {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 12px;
}
.hh-pick-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hh-select {
  flex: 1;
  min-width: 0;
  background: var(--input-bg);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  color: var(--text);
  padding: 7px 10px;
  font-size: 13px;
}
.hh-select:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 1px;
  border-color: var(--cta);
}
.hh-note {
  font-size: 11px;
  color: var(--muted-2);
  margin: -6px 0 10px;
}
.hh-detail {
  max-height: 64vh;
  overflow-y: auto;
  padding-right: 4px;
}
.hh-loading,
.hh-empty {
  color: var(--muted);
  padding: 16px 4px;
}

/* small card variant — fixed px (the modal isn't a container-query context) */
.card.hh {
  width: var(--hhc, 26px);
  border-radius: 4px;
  font-size: calc(var(--hhc, 26px) * 0.5);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* one unified section/divider label — echoes .side-log-title / .ledger-head */
.hh-label {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  font-weight: 700;
}
.hh-label-note {
  margin-left: 8px;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 600;
  color: var(--gold);
}

/* header — Hand #N + stakes + pot on line 1, Button/SB/BB chips on line 2 */
.hh-header {
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line-2);
}
.hh-h-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.hh-h-num {
  font-weight: 800;
  font-size: 15px;
}
.hh-h-stakes {
  color: var(--gold);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.hh-h-pot {
  color: var(--muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.hh-h-pot b {
  color: var(--text);
  font-weight: 700;
}
.hh-h-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 9px;
}
.hh-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 2px 9px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.02);
  font-size: 11.5px;
}
.hh-chip-k {
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hh-chip-v {
  color: var(--text);
  font-weight: 600;
}

/* board strip — community cards once, subtle gap between flop | turn | river */
.hh-board-sect,
.hh-boards {
  margin: 0 0 16px;
}
.hh-board-sect > .hh-label,
.hh-boards > .hh-label {
  margin-bottom: 7px;
}
.hh-boards > .hh-label:not(:first-child) {
  margin-top: 13px;
}
.hh-board {
  display: flex;
  align-items: center;
  gap: 4px;
}
.hh-board-sep {
  width: 9px;
}

/* showdown grid — one fixed column template shared by every row so columns line up
   across rows (mirrors .ledger-row); still carries a per-row .place-N medal accent */
.hh-showdown {
  margin-bottom: 18px;
}
.hh-showdown > .hh-label {
  margin-bottom: 8px;
}
.hh-row {
  display: grid;
  grid-template-columns: 24px minmax(64px, 1fr) calc(var(--hhc, 26px) * 2 + 5px) calc(var(--hhc, 26px) * 5 + 18px) 96px 70px;
  gap: 10px;
  align-items: center;
  padding: 6px 4px 6px 7px;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid transparent; /* .place-N fills this */
}
.hh-rank {
  font-size: 14px;
  line-height: 1;
  text-align: center;
  color: var(--muted-2);
}
.hh-namecell {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.hh-name {
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hh-stack {
  font-size: 10px;
  color: var(--muted-2);
  font-variant-numeric: tabular-nums;
}
.hh-hole,
.hh-best {
  display: flex;
  align-items: center;
  gap: 3px;
}
.hh-best {
  padding: 2px;
  border-radius: 6px;
}
/* winner's best five get the gold ring */
.hh-best.hh-win {
  box-shadow: 0 0 0 2px var(--gold), 0 0 10px 1px rgba(240, 198, 74, 0.4);
  background: rgba(240, 198, 74, 0.06);
}
.hh-cat {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.25;
}
.hh-best.hh-win + .hh-cat {
  color: var(--gold);
}
.hh-net {
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.hh-net.up {
  color: var(--net-up);
}
.hh-net.down {
  color: var(--net-down);
}
/* medal accents reused on the grid rows */
.hh-row.place-1 {
  border-left-color: var(--medal-gold);
}
.hh-row.place-1 .hh-name {
  color: var(--medal-gold);
}
.hh-row.place-2 {
  border-left-color: var(--medal-silver);
}
.hh-row.place-2 .hh-name {
  color: var(--medal-silver);
}
.hh-row.place-3 {
  border-left-color: var(--medal-bronze);
}
.hh-row.place-3 .hh-name {
  color: var(--medal-bronze);
}
/* folded players stay in the grid: muted, with a tag spanning the best + category columns */
.hh-row.hh-folded {
  opacity: 0.6;
}
.hh-folded-tag {
  grid-column: span 2;
  align-self: center;
  font-size: 11px;
  font-style: italic;
  color: var(--muted-2);
}

/* transcript — ACTION label, then clean labeled street dividers on a hairline rule */
.hh-transcript > .hh-label {
  margin-bottom: 2px;
}
.hh-street {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 13px 0 5px;
}
.hh-street .hh-label {
  flex: none;
}
.hh-rule {
  flex: 1;
  height: 1px;
  background: var(--line);
}
/* per-street board build-up: prior cards dimmed, this street's new card(s) lit */
.hh-sboard {
  display: flex;
  align-items: center;
  gap: 4px;
}
.card.hh-dim {
  opacity: 0.4;
}
.card.hh-new {
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4);
}
/* who is still in the hand at this phase — a count pill + the contesting players */
.hh-live {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  margin: 1px 0 5px 2px;
  font-size: 11px;
}
.hh-live-n {
  flex: none;
  min-width: 16px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
  font-weight: 700;
  font-size: 10px;
  text-align: center;
}
.hh-live-names {
  color: var(--muted-2);
}
.hh-action {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 8px;
  padding: 2px 0 2px 4px;
  font-size: 12.5px;
  line-height: 1.5;
}
.hh-actor {
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hh-act {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.hh-amt {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.hh-allin {
  margin-left: 6px;
  padding: 0 5px;
  border-radius: 4px;
  background: rgba(240, 198, 74, 0.14);
  color: var(--gold);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* narrow screens — shrink the cards + columns so the grid reflows without horizontal scroll */
@media (max-width: 560px) {
  /* shrink the hand-history card (and thus its grid columns) on narrow screens */
  .modal-history {
    --hhc: 26px;
  }
  .hh-row {
    /* name column (minmax 0) yields first as the modal narrows, so the card columns never scroll */
    grid-template-columns: 22px minmax(0, 1fr) calc(var(--hhc) * 2 + 5px) calc(var(--hhc) * 5 + 18px) 80px 58px;
    gap: 7px;
  }
  .hh-action {
    grid-template-columns: 76px 1fr;
  }
}
/* very small phones: shrink the showdown grid further so 7 cards + columns still fit */
@media (max-width: 400px) {
  .modal-history {
    --hhc: 22px;
  }
  .hh-row {
    grid-template-columns: 18px minmax(0, 1fr) calc(var(--hhc) * 2 + 4px) calc(var(--hhc) * 5 + 16px) 64px 50px;
    gap: 5px;
  }
}
