:root {
  /* "Chip & Copper" palette (2026-09-12 rebrand) - oxblood/espresso in
     place of the black-and-green felt, copper in place of gold. Picked
     specifically to share no hue with prefloptrainer.com's near-black +
     gold-spade-badge look, while keeping the same dark, premium, felt-at-
     night feeling the app had before. */
  --felt: #4a1a17;
  --felt-dark: #200a09;
  --rail: #2a1815;
  --rail-dark: #120a08;
  --bg: #1c1210;
  --surface: #241715;
  --surface-2: #2e1e1a;
  --border: #3d2a24;
  --text: #f3e9e2;
  --text-dim: #b09585;
  --text-faint: #7d685c;
  --accent: #c9793f;
  --accent-dim: #9c5c2c;
  --good: #34d399;
  --bad: #f87171;
  --info: #60a5fa;
  --card-bg: #fefefe;
  --card-red: #d1352b;
  --card-black: #1a1a1a;
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);
  --radius: 14px;
  --radius-sm: 8px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Work Sans", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* This is a single-page app with no content that legitimately needs to
     scroll wider than the viewport (the range-grid/chart tables get their
     own overflow-x:auto containers) - so any horizontal scroll at all is
     always a bug, never a feature. Guard against it outright rather than
     chasing every possible sub-pixel cause (a stray flex child's intrinsic
     min-width, a font-rendering difference, dynamic type, etc.). */
  overflow-x: hidden;
}

button, input {
  font-family: inherit;
}

.app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ---- navbar ---- */

.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand-logo {
  width: 26px;
  height: 26px;
  border-radius: 6px;
}

.brand-name {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 600;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.nav-stats {
  display: flex;
  gap: 16px;
}

.nav-stat {
  display: flex;
  align-items: baseline;
  gap: 2px;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.nav-stat b {
  color: var(--text);
  font-size: 0.95rem;
}

.nav-stat label {
  margin-left: 5px;
  font-size: 0.7rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.nav-stat.streak b { color: var(--accent); }
.nav-stat.best b { color: var(--text-dim); font-size: 0.85rem; }

.nav-player {
  font-size: 0.85rem;
  color: var(--text-dim);
  padding: 4px 10px;
  background: var(--surface-2);
  border-radius: 999px;
  border: 1px solid var(--border);
}

/* ---- buttons ---- */

button {
  cursor: pointer;
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 600;
  font-size: 0.9rem;
  transition: transform 0.08s ease, filter 0.15s ease, background 0.15s ease;
}

button:hover { filter: brightness(1.15); }
button:active { transform: scale(0.97); }

.btn-ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--text-dim);
  padding: 7px 14px;
  font-size: 0.85rem;
}

.btn-primary {
  background: linear-gradient(180deg, #e2a262, var(--accent));
  color: #241206;
  font-weight: 700;
  border: none;
  box-shadow: var(--shadow-sm);
}

.btn-primary.btn-large {
  padding: 14px 32px;
  font-size: 1.02rem;
  border-radius: 10px;
}

.btn-secondary {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  width: 100%;
  margin-top: 8px;
}

.btn-secondary.locked {
  opacity: 0.6;
  cursor: default;
  color: var(--text-faint);
}

.btn-secondary.btn-large {
  padding: 12px 28px;
  font-size: 0.95rem;
  border-radius: 10px;
}

.mode-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 6px 0 14px;
  color: var(--text-faint);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.mode-divider::before,
.mode-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.secondary-row {
  display: flex;
  gap: 8px;
  width: 100%;
  margin-top: 8px;
}

.secondary-row .btn-secondary {
  width: auto;
  flex: 1;
  margin-top: 0;
}

.btn-link {
  background: none;
  border: none;
  color: var(--text-faint);
  font-weight: 500;
  font-size: 0.78rem;
  text-decoration: underline;
  padding: 4px;
}

.btn-link:hover { color: var(--text-dim); filter: none; }

/* ---- start screen ---- */

.start-screen {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  background:
    radial-gradient(ellipse at top, rgba(74, 26, 23, 0.45), transparent 60%),
    var(--bg);
}

.start-card {
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
  padding: 36px 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  animation: fadeInUp 0.4s ease both;
}

.start-logo {
  width: 64px;
  height: 64px;
  border-radius: 16px;
  box-shadow: var(--shadow-md);
  margin-bottom: 10px;
}

.start-card h1 {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 600;
  font-size: 1.55rem;
  margin: 0;
  letter-spacing: -0.01em;
}

.joke-line {
  color: var(--accent-dim);
  font-size: 0.78rem;
  font-style: italic;
  margin: 5px 0 0;
}

.tagline {
  color: var(--text-dim);
  font-size: 0.92rem;
  line-height: 1.5;
  max-width: 360px;
  margin: 6px 0 18px;
}

.feature-row {
  display: flex;
  justify-content: center;
  gap: 10px;
  width: 100%;
  margin-bottom: 22px;
}

.feature {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.72rem;
  color: var(--text-dim);
  line-height: 1.3;
}

.feature-icon {
  font-size: 1.15rem;
}

.profile-row {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  margin-bottom: 16px;
}

.profile-row label {
  font-size: 0.78rem;
  color: var(--text-dim);
  font-weight: 600;
}

.profile-row input {
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
}

.profile-row input:focus {
  outline: none;
  border-color: var(--accent-dim);
}

.profile-row input.error {
  border-color: var(--bad);
}

.field-error {
  color: var(--bad);
  font-size: 0.76rem;
  margin: 2px 0 0;
}

/* Seat glossary in the How This Works modal. Grid rather than a plain <dl>
   so every definition starts on the same x - the abbreviations are the
   thing being looked up, so they need to form a scannable column. */
.seat-glossary {
  margin: 10px 0 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.seat-glossary > div {
  display: grid;
  grid-template-columns: 54px 1fr;
  gap: 10px;
  align-items: baseline;
}

.seat-glossary dt {
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.seat-glossary dd {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text-dim);
}

.seat-glossary-note {
  margin: 10px 0 0;
  font-size: 0.8rem;
  color: var(--text-faint);
}

/* ---- chip-stack level ---- */

/* Bottom-aligned so the chips sit on the text baseline rather than floating
   mid-line, and never shrink in a tight row. */
.chip-badge {
  vertical-align: -0.35em;
  margin-right: 7px;
  flex: none;
}

.level-card {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin-bottom: 12px;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.level-card:hover {
  border-color: var(--accent-dim);
}

.level-card-chevron {
  color: var(--text-faint);
  font-size: 0.8rem;
  flex: none;
}

.level-card:hover .level-card-chevron { color: var(--accent); }

.level-badge {
  display: flex;
  align-items: flex-end;
  flex: none;
}

.level-badge .chip-badge { margin-right: 0; vertical-align: baseline; }

.level-meta {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  flex: 1;
}

.level-meta b {
  font-size: 0.92rem;
  color: var(--text);
}

.level-meta span {
  font-size: 0.74rem;
  color: var(--text-faint);
}

.level-track {
  height: 5px;
  border-radius: 999px;
  background: var(--bg);
  overflow: hidden;
}

.level-track i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-dim), var(--accent));
  transition: width 0.4s ease;
}

/* ---- level progression modal ---- */

.level-now {
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  margin-bottom: 12px;
}

.level-now-badge { display: flex; align-items: flex-end; flex: none; }
.level-now-badge .chip-badge { margin-right: 0; vertical-align: baseline; }

.level-now-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1;
}

.level-now-meta b { font-size: 1.02rem; }
.level-now-meta span { font-size: 0.78rem; color: var(--text-dim); }

.level-ladder {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.ladder-row {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  /* Denominations you haven't reached stay legible rather than invisible -
     the path ahead is the motivating part, so dimming it too far defeats
     the point of showing it. */
  opacity: 0.45;
}

.ladder-row.reached { opacity: 1; }

.ladder-row.is-now {
  background: rgba(201, 121, 63, 0.12);
  border-color: var(--accent-dim);
  opacity: 1;
}

.ladder-art {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 44px;
}

.ladder-art .chip-badge { margin-right: 0; vertical-align: baseline; }

/* The last denomination is the trophy - give it room, centre it against
   the stacks above, and let it glow rather than sit flush like a row. */
.ladder-row.is-final { padding: 12px; }
.ladder-row.is-final .ladder-art { align-items: center; }
.ladder-row.is-final .chip-face {
  filter: drop-shadow(0 3px 10px rgba(0, 0, 0, 0.55));
}
.ladder-row.is-final.reached .chip-face {
  filter: drop-shadow(0 0 12px rgba(201, 121, 63, 0.45)) drop-shadow(0 3px 10px rgba(0, 0, 0, 0.55));
}

.ladder-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
}

.ladder-name em {
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-faint);
}

.ladder-here {
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}

.lifetime-stats {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  row-gap: 12px;
  justify-content: space-between;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 4px;
}

/* Secondary records (Expert/Sizing best) as small pills below the main
   stats card, rather than extra equal-sized tiles that wrap awkwardly as
   more modes get added - this stays tidy regardless of how many exist. */
.lifetime-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 10px 0 18px;
}

.lifetime-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
}

.lifetime-pill b {
  color: var(--accent);
  font-size: 0.82rem;
}

.lifetime-stat {
  /* Basis rather than flex:1 so five tiles reflow onto a second row on a
     narrow phone instead of crushing each other. */
  flex: 1 1 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.lifetime-stat b {
  font-size: 1.15rem;
  color: var(--accent);
}

.lifetime-stat span {
  font-size: 0.68rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.leak-hint {
  width: 100%;
  background: rgba(201, 121, 63, 0.08);
  border: 1px solid var(--accent-dim);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-size: 0.78rem;
  color: var(--accent);
  margin-bottom: 16px;
  text-align: left;
}

.filter-section {
  width: 100%;
  text-align: left;
  margin-bottom: 20px;
}

.filter-label {
  display: block;
  font-size: 0.78rem;
  color: var(--text-dim);
  font-weight: 600;
  margin-bottom: 8px;
}

.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.filter-chip {
  padding: 7px 12px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-faint);
}

.filter-chip.active {
  background: rgba(201, 121, 63, 0.14);
  border-color: var(--accent-dim);
  color: var(--accent);
}

.expert-toggle {
  width: 100%;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 700;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-faint);
}

.expert-toggle.locked {
  cursor: default;
  opacity: 0.65;
}

.expert-toggle.unlocked {
  color: var(--text-dim);
}

.expert-toggle.on {
  background: rgba(201, 121, 63, 0.14);
  border-color: var(--accent-dim);
  color: var(--accent);
}

.expert-caption {
  margin: 6px 0 0;
  font-size: 0.74rem;
  color: var(--text-faint);
  text-align: left;
}

/* Deliberately accent-coloured rather than faint: it's a trade-off being
   made right now, not fine print. */
.filter-streak-note {
  margin: 8px 0 0;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--accent);
  text-align: left;
}

.practice-badge {
  color: var(--accent);
  background: rgba(201, 121, 63, 0.14);
}

.expert-badge {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--accent);
  background: rgba(201, 121, 63, 0.12);
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  padding: 3px 9px;
  white-space: nowrap;
}

.start-card .btn-primary.btn-large {
  width: 100%;
}

.daily-btn {
  width: 100%;
  margin-top: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.daily-badge {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent);
  background: rgba(201, 121, 63, 0.14);
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  padding: 2px 8px;
}

.options-toggle {
  margin: 4px 0 0;
  align-self: center;
}

.options-toggle #moreOptionsChevron {
  display: inline-block;
  transition: transform 0.15s ease;
}

.options-toggle[aria-expanded="true"] #moreOptionsChevron {
  transform: rotate(180deg);
}

.more-options {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 10px;
  animation: fadeInUp 0.2s ease both;
}

.more-options .feature-row {
  margin-bottom: 12px;
}

.more-options .filter-section:last-child {
  margin-bottom: 4px;
}

.fine-print {
  color: var(--text-faint);
  font-size: 0.72rem;
  margin-top: 16px;
  line-height: 1.4;
}

/* ---- table screen ---- */

main#tableScreen {
  flex: 1;
  max-width: 900px;
  width: 100%;
  margin: 0 auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.table-wrap {
  position: relative;
  width: 100%;
  padding-top: 62%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, var(--felt) 0%, var(--felt-dark) 100%);
  border: 14px solid var(--rail);
  outline: 4px solid var(--rail-dark);
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.5), var(--shadow-lg);
}

/* C2: table becomes tappable-to-skip while a reveal is in flight - the
   cursor and hint pill are the only visible cue, everything else about the
   table's own layout is untouched. */
.table-wrap.reveal-active {
  cursor: pointer;
}

.skip-reveal-hint {
  position: absolute;
  bottom: 6%;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 999px;
  pointer-events: none;
  z-index: 5;
  animation: fadeInUp 0.3s ease both;
}

.fast-deal-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--text-dim);
  margin-top: 4px;
  cursor: pointer;
}

.fast-deal-hint {
  color: var(--text-faint);
  font-size: 0.74rem;
}

.table-logo {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 15%;
  min-width: 56px;
  max-width: 100px;
  border-radius: 22%;
  opacity: 0.8;
  pointer-events: none;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}

/* Swapped in for .table-logo only under the Expert theme - see the
   "EXPERT THEME" block near the end of this file, which is the only place
   that shows it (this base rule just keeps it inert/invisible otherwise). */
.table-logo-expert {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  align-items: center;
  justify-content: center;
  pointer-events: none;
  white-space: nowrap;
}

.seat {
  position: absolute;
  width: 92px;
  transform: translate(-50%, -50%);
  text-align: center;
  transition: opacity 0.25s ease;
}

.seat .name {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text);
  background: rgba(0, 0, 0, 0.45);
  border-radius: 6px;
  padding: 2px 4px;
  white-space: nowrap;
}

.seat.hero .name { color: #241206; background: var(--accent); }

.seat .cards {
  display: flex;
  justify-content: center;
  gap: 2px;
  margin: 3px 0;
  min-height: 34px;
}

.mini-card {
  width: 20px;
  height: 28px;
  border-radius: 3px;
  background: linear-gradient(135deg, #294a8a, #17305e);
  border: 1px solid #0c1a33;
}

.mini-card.back {
  background-image: repeating-linear-gradient(45deg, #294a8a, #294a8a 3px, #17305e 3px, #17305e 6px);
}

.seat .action-badge {
  display: inline-block;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--text-dim);
  min-height: 14px;
  padding: 0 6px;
  border-radius: 999px;
  background: transparent;
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity 0.2s ease, transform 0.2s ease, background 0.2s ease;
}

.seat .action-badge.show { opacity: 1; transform: translateY(0); }
.seat .action-badge.fold { color: #7a8593; }
.seat .action-badge.call { color: #0b1a2a; background: var(--info); }
.seat .action-badge.raise { color: #241206; background: var(--accent); }
.seat .action-badge.check { color: #0b1a2a; background: var(--info); }
.seat .action-badge.post { color: var(--text-faint); background: transparent; font-style: italic; }

.seat.folded { opacity: 0.4; }
.seat.dealt-out .cards { visibility: hidden; }

.seat.acting .cards {
  animation: actingPulse 0.85s ease infinite;
}

@keyframes actingPulse {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(201, 121, 63, 0)); }
  50% { filter: drop-shadow(0 0 6px rgba(201, 121, 63, 0.85)); }
}

.dealer-btn {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #f3f5f8;
  color: #10141a;
  font-size: 0.62rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-sm);
  border: 1px solid #cfd4da;
}

.chip-stack {
  display: flex;
  justify-content: center;
  gap: 2px;
  height: 10px;
  margin-top: 2px;
}

.chip-stack .chip {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: repeating-conic-gradient(var(--accent) 0% 25%, #7a4a24 0% 50%);
  border: 1px solid #4a2e16;
  align-self: flex-end;
}

/* ---- hero panel ---- */

.hero-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: var(--shadow-md);
}

.hero-panel.fade {
  animation: fadeIn 0.3s ease both;
}

.hero-cards-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 16px;
}

.stack-badge {
  grid-column: 3;
  justify-self: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  min-width: 64px;
}

.stack-badge-value {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--accent);
}

.session-progress {
  grid-column: 2;
  justify-self: center;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--text-faint);
  white-space: nowrap;
}

.stack-badge-caption {
  font-size: 0.62rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.hero-cards-big {
  grid-column: 2;
  justify-self: center;
  display: flex;
  justify-content: center;
  gap: 8px;
  perspective: 600px;
}

.big-card {
  width: 56px;
  height: 78px;
  border-radius: 8px;
  background: var(--card-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.65rem;
  font-weight: 700;
  box-shadow: var(--shadow-sm);
}

.big-card.red { color: var(--card-red); }
.big-card.black { color: var(--card-black); }

.big-card.back {
  background-image: repeating-linear-gradient(45deg, #294a8a, #294a8a 5px, #17305e 5px, #17305e 10px);
  border: 1px solid #0c1a33;
}

.big-card.flip-in {
  animation: cardFlipIn 0.32s ease both;
}

@keyframes cardFlipIn {
  from { transform: rotateY(90deg); opacity: 0.3; }
  to { transform: rotateY(0deg); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .big-card.flip-in { animation: none; }
}

.bonus-badge {
  display: block;
  width: fit-content;
  margin: 0 auto 10px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
  background: rgba(201, 121, 63, 0.12);
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  padding: 4px 12px;
}

.situation {
  text-align: center;
  color: var(--text-dim);
  font-size: 0.92rem;
  line-height: 1.5;
  max-width: 520px;
  margin: 0 auto;
}

.situation b { color: var(--text); }

.actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

.actions button {
  min-width: 96px;
  padding: 13px 18px;
  font-weight: 700;
  font-size: 0.95rem;
  border-radius: 10px;
}

.actions button.fold { border-color: #6b3030; background: #2a1616; }
.actions button.check, .actions button.call { border-color: #1e4e68; background: #14293a; }
.actions button.raise { border-color: #8a5a28; background: #2a1c10; color: var(--accent); }
.actions button.raise.allin { border-color: #8a2020; background: #3a1414; color: #ff9b9b; }

/* Set the all-in apart when a sized raise is also on offer.

   The two used to sit side by side as same-size, same-shape siblings that
   both read as "the raise option", with the all-in the brighter of the two
   and last in the row - the natural end-of-row target. At 22bb, "raise to
   3.5bb" and "all-in for 22bb" are wildly different decisions being
   presented as near-identical twins, and picking the wrong one is then
   graded as a poker mistake. On a trainer that is worse than an ordinary
   misclick: you conclude your judgement was off when your finger was.

   The sibling selector matters. Below ~20bb the sized raise isn't offered
   at all and the all-in is the only way to raise - there it must stay a
   full-weight primary action, so this only applies when a sized raise
   actually precedes it. */
.actions button.raise:not(.allin) ~ button.raise.allin {
  margin-left: 14px;
  font-size: 0.85rem;
  padding: 13px 14px;
  min-width: 0;
  opacity: 0.72;
  background: #2a1414;
}

.actions button.raise:not(.allin) ~ button.raise.allin:hover,
.actions button.raise:not(.allin) ~ button.raise.allin:focus-visible {
  opacity: 1;
}

/* The gap does the separating on a wide row; on a wrapped one the margin
   would just indent it oddly, so drop it once the row is stacking. */
@media (max-width: 520px) {
  .actions button.raise:not(.allin) ~ button.raise.allin { margin-left: 0; }
}

/* Bet Sizing mode: bb amount as the headline, the multiplier it works out
   to underneath - the multiplier is the part that transfers between spots,
   but the bb figure is what you'd actually announce at the table. */
.actions button.size-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 108px;
  padding: 12px 16px;
  border-color: #8a5a28;
  background: #2a1c10;
}

.actions button.size-option b {
  font-size: 1.05rem;
  color: var(--accent);
}

.actions button.size-option span {
  font-size: 0.72rem;
  font-style: italic;
  font-weight: 600;
  color: var(--text-faint);
}

.actions button.size-option.allin { border-color: #8a2020; background: #3a1414; }
.actions button.size-option.allin b { color: #ff9b9b; }

/* Bet Sizing Expert mode: free-entry slider instead of 3 buttons. Ticks are
   labelled in multiples of whatever's being raised over, so the player only
   ever needs to know the rule ("3x the open") rather than do the
   multiplication themselves - the number is already sitting on the track. */
.sizing-slider {
  width: 100%;
  max-width: 360px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.slider-readout {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.slider-readout .slider-bb {
  font-size: 1.7rem;
  font-weight: 800;
  color: var(--accent);
}

.slider-readout .slider-mult {
  font-size: 0.8rem;
  font-style: italic;
  font-weight: 600;
  color: var(--text-faint);
}

.slider-track-wrap {
  width: 100%;
  padding-bottom: 20px;
  position: relative;
}

.slider-track-wrap input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  outline: none;
}

.slider-track-wrap input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--accent-dim);
  cursor: pointer;
  margin-top: -1px;
}

.slider-track-wrap input[type="range"]::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--accent-dim);
  cursor: pointer;
}

.slider-ticks {
  position: relative;
  width: 100%;
  height: 16px;
}

.slider-tick {
  position: absolute;
  top: 4px;
  transform: translateX(-50%);
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-faint);
  white-space: nowrap;
}

.slider-tick.slider-tick-allin {
  color: #ff9b9b;
}

/* ---- feedback ---- */

.feedback {
  display: none;
  border-radius: var(--radius-sm);
  padding: 16px;
  gap: 6px;
  flex-direction: column;
  animation: fadeInUp 0.25s ease both;
}

.feedback.show { display: flex; }
.feedback.correct { background: rgba(52, 211, 153, 0.1); border: 1px solid var(--good); }
.feedback.incorrect { background: rgba(248, 113, 113, 0.1); border: 1px solid var(--bad); }

.feedback .verdict {
  font-weight: 700;
  font-size: 1.05rem;
  display: flex;
  align-items: center;
  gap: 8px;
}

.feedback.correct .verdict { color: var(--good); }
.feedback.incorrect .verdict { color: var(--bad); }

.feedback .explanation { color: var(--text-dim); font-size: 0.88rem; line-height: 1.45; }

.next-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.next-row .btn-secondary {
  width: auto;
  margin-top: 0;
  padding: 12px 20px;
}

/* ---- motion ---- */

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .start-card, .hero-panel.fade, .feedback { animation: none; }
}

/* ---- stats / history modal ---- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 11, 0.65);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
  animation: fadeIn 0.15s ease both;
}

.modal-card {
  width: 100%;
  max-width: 520px;
  max-height: 85vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  animation: fadeInUp 0.2s ease both;
}

.modal-card.modal-card-wide {
  max-width: 640px;
}

.charts-note {
  font-size: 0.82rem;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin: 6px 0 16px;
  line-height: 1.45;
}

.charts-note b { color: var(--accent); }

.chip-select {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip-select button {
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-faint);
}

.chip-select button.active {
  background: rgba(201, 121, 63, 0.14);
  border-color: var(--accent-dim);
  color: var(--accent);
}

#leaderboardTabs {
  margin-bottom: 12px;
}

.chart-controls {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 14px 0;
}

.chart-control-group label {
  display: block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
  margin-bottom: 6px;
}

.chart-legend {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 0.76rem;
  color: var(--text-dim);
}

.chart-legend .swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  margin-right: 5px;
  vertical-align: middle;
}

.range-grid {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
}

.sizing-breakdown {
  max-width: 480px;
  margin: 0 auto;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
}

.sizing-breakdown .sizing-result {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent);
  text-align: center;
  margin-bottom: 4px;
}

.sizing-breakdown .sizing-result span {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  font-style: italic;
  color: var(--text-faint);
  margin-top: 2px;
}

.sizing-breakdown .sizing-formula {
  text-align: center;
  font-size: 0.82rem;
  color: var(--text-dim);
  margin: 10px 0;
  padding: 8px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.sizing-breakdown .sizing-why {
  font-size: 0.85rem;
  color: var(--text-dim);
  line-height: 1.55;
  margin-top: 10px;
}

.sizing-breakdown .sizing-source {
  font-size: 0.72rem;
  color: var(--text-faint);
  margin-top: 10px;
  font-style: italic;
}

/* ---- bet sizing chart: multiway extras (isolate/squeeze scaling, the
   4-bet-squeeze note) appended below the main headline/formula/why block
   inside .sizing-breakdown - see renderSizingChart() ---- */

.sizing-extra {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.sizing-extra h5 {
  margin: 0 0 6px;
  font-size: 0.85rem;
  color: var(--text);
  text-align: center;
}

.sizing-extra h5 span {
  font-weight: 400;
  font-size: 0.76rem;
  color: var(--text-faint);
}

.multiway-formula {
  font-size: 0.84rem;
  color: var(--text-dim);
  text-align: center;
  margin: 0 0 10px;
}

.multiway-formula b { color: var(--accent); }

.multiway-table-wrap {
  overflow-x: auto;
  margin: 10px 0;
}

.multiway-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
  white-space: nowrap;
}

.multiway-table th, .multiway-table td {
  padding: 7px 10px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

.multiway-table th:first-child, .multiway-table td:first-child {
  text-align: left;
  color: var(--text-dim);
  font-weight: 600;
}

.multiway-table thead th {
  color: var(--text-faint);
  font-weight: 600;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.multiway-table tbody td:not(:first-child) {
  color: var(--accent);
  font-weight: 700;
}

.multiway-table tbody td span {
  display: block;
  font-size: 0.68rem;
  font-weight: 600;
  font-style: italic;
  color: var(--text-faint);
  margin-top: 1px;
}

.multiway-caption {
  font-size: 0.78rem;
  color: var(--text-faint);
  line-height: 1.5;
  margin: 10px 0 0;
}

/* Marks the column matching the hand actually being reviewed (Review
   Chart only - see the highlightHc-gated liveN in renderSizingChart) so
   the table still answers "what did THIS hand need" at a glance, the way
   the single-number headline used to before it became a table. Framed
   fully inside each cell (box-shadow, not a border/outline that could
   affect layout) since the table sits in a horizontally-scrolling wrap -
   nothing here should ever poke outside a cell's own box. */
.multiway-table th.is-live {
  color: var(--accent);
  background: rgba(201, 121, 63, 0.14);
  border-radius: 6px 6px 0 0;
  box-shadow: inset 0 2px 0 var(--accent);
}

.multiway-table td.is-live {
  background: rgba(201, 121, 63, 0.16);
  border-radius: 0 0 6px 6px;
  box-shadow: inset 0 0 0 2px rgba(201, 121, 63, 0.55);
  animation: liveColumnIn 1.4s ease-out 1;
}

.multiway-table td.is-live,
.multiway-table th.is-live {
  font-weight: 800;
}

@keyframes liveColumnIn {
  0% { box-shadow: inset 0 0 0 2px rgba(201, 121, 63, 0.55), 0 0 14px rgba(201, 121, 63, 0.6); }
  100% { box-shadow: inset 0 0 0 2px rgba(201, 121, 63, 0.55), 0 0 0 rgba(201, 121, 63, 0); }
}

.multiway-live-caption {
  font-size: 0.74rem;
  color: var(--accent);
  text-align: center;
  margin: 8px 0 0;
}

/* Deliberately quiet - a known gap worth naming, not a warning. No
   border/background card, just muted text. */
.multiway-unsolved {
  font-size: 0.76rem;
  color: var(--text-faint);
  line-height: 1.5;
  text-align: center;
  padding: 0 8px;
}

.multiway-unsolved b {
  color: var(--text-dim);
}

.range-grid-inner {
  display: grid;
  grid-template-columns: repeat(13, 1fr);
  gap: 2px;
}

.range-cell {
  position: relative;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  font-size: 0.56rem;
  font-weight: 700;
  line-height: 1;
}

/* One text colour per category background, reused everywhere a cell (or
   half of a split cell, see .cell-half below) needs to sit on that
   background - the single source of truth for range-grid contrast, so a
   new chart or a new split combination can't reintroduce a mismatched
   pairing. Fold's text was bumped from --text-faint (too low-contrast on
   its own dark background) to --text-dim - still visibly de-emphasised
   next to raise/call, just actually legible. */
.range-cell.cat-fold { background: var(--surface-2); color: var(--text-dim); }
.range-cell.cat-raise, .range-cell.cat-3bet { background: var(--accent); color: #241206; }
.range-cell.cat-call { background: var(--info); color: #0b1a2a; }

/* Track B: a genuine boundary/coin-flip hand (see nearestFlip) - top
   half painted fold's own grey, bottom half left transparent so the
   cell's real cat-* background shows through underneath. Reads as
   "half fold, half [whatever this cell actually is]" for any category,
   without needing to know the specific other action per hand. */
.range-cell.cell-mixed {
  background-image: linear-gradient(to bottom, var(--surface-2) 0 50%, transparent 50% 100%);
}

/* Same idea as cell-mixed above, but for a genuine raise/call 50/50 (no
   fold involved) - top half painted the raise/3-bet colour instead of
   fold's grey, over a cat-call base. Used by the 4-Bet Range chart, whose
   solver-sourced ties are almost all raise-vs-call, not fold-involved. */
.range-cell.cell-mixed-raise {
  background-image: linear-gradient(to bottom, var(--accent) 0 50%, transparent 50% 100%);
}

/* A split cell's two backgrounds each need their OWN correctly-contrasted
   text colour - a single `color` on the cell can't be right for both
   halves at once (this was the actual bug: a dark raise/call text colour,
   meant for a bright background, was bleeding into the dark fold-grey
   half above it and reading as barely-visible dark-on-dark). Stacked as
   two ordinary half-height flex rows rather than overlapping absolutely-
   positioned copies - an earlier version tried centering two full-size
   copies on the whole cell and clipping each to its half, which just
   reassembled into one word with mismatched glyph-halves at the seam,
   not two clean labels. Each row carries the cat-* class for whatever
   colour that half's background actually is - see renderRangeGrid's
   mixed-cell branch in app.js. */
.range-cell.cell-mixed, .range-cell.cell-mixed-raise {
  flex-direction: column;
  align-items: stretch;
}
.cell-half {
  flex: 1 1 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  font-size: 0.85em;
}
.cell-half.cat-fold { color: var(--text-dim); }
.cell-half.cat-raise, .cell-half.cat-3bet { color: #241206; }
.cell-half.cat-call { color: #0b1a2a; }

.range-cell.cell-marked {
  position: relative;
  z-index: 1;
  outline: 2px solid #ffffff;
  outline-offset: -2px;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.35), var(--shadow-md);
  transform: scale(1.18);
}

.chart-caption {
  text-align: center;
  color: var(--text-dim);
  font-size: 0.82rem;
  margin: 14px 0 4px;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--surface);
}

.modal-header h2 {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 600;
  margin: 0;
  font-size: 1.15rem;
}

.modal-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.modal-header-actions .btn-ghost#chartsHowItWorksBtn {
  padding: 7px 12px;
  font-weight: 700;
}

#introModal .modal-body p {
  line-height: 1.55;
  color: var(--text-dim);
}

#introModal .modal-body h3:first-of-type {
  margin-top: 4px;
}

#introModal .chart-legend {
  margin: 10px 0;
}

#introModal #introGotItBtn {
  width: 100%;
  margin-top: 16px;
}

.modal-body {
  padding: 8px 20px 22px;
}

.modal-body h3 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
  margin: 18px 0 10px;
}

.summary-headline {
  text-align: center;
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--accent);
  margin: 6px 0 14px;
}

.summary-adaptive {
  background: rgba(201, 121, 63, 0.08);
  border: 1px solid var(--accent-dim);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-size: 0.8rem;
  color: var(--accent);
  margin: 4px 0 0;
  text-align: left;
}

/* Your own row when you didn't make the visible list. Set off with a gap
   and a top border so it reads as "and here's you", not as rank 101. */
.own-row-pinned {
  margin-top: 10px;
  border-top: 1px dashed var(--border);
  padding-top: 12px;
}

/* Home, in the left slot during a hand - where the brand sits on the home
   screen. It replaces the brand rather than crowding in beside it, because
   the navbar is already tight on a phone once the session stats are up. */
.nav-home {
  flex: none;
  white-space: nowrap;
  font-weight: 600;
}

/* Profile button. Home screen only - see setNavMode. */
.profile-btn {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-dim);
  font: 700 0.9rem "Work Sans", sans-serif;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 10px;
  padding: 0;
}

/* Named accounts get the accent treatment, so the button doubles as an
   at-a-glance "are my scores being recorded?" indicator. */
.profile-btn.named {
  background: var(--accent);
  border-color: var(--accent);
  color: #241206;
}

.profile-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.profile-card .filter-label { display: block; margin-bottom: 6px; }

.profile-card input[type="text"] {
  width: 100%;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  font-size: 1rem;
}

.profile-note { font-size: 0.8rem; color: var(--text-faint); margin: 10px 0 0; }

/* "Put this on the leaderboard?" - the ask, moved to where it's earned. */
.claim-row {
  margin: 16px 0 0;
  padding: 14px 16px;
  background: rgba(201, 121, 63, 0.1);
  border: 1px solid var(--accent-dim);
  border-radius: var(--radius-sm);
}

.claim-row b { display: block; font-size: 0.92rem; margin-bottom: 10px; }

.claim-input-row { display: flex; gap: 8px; }

.claim-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 0.95rem;
}

.claim-input-row button { flex: none; white-space: nowrap; }

/* Seat-mapping note under the feedback. Quiet by design - it explains a
   simplification, it isn't part of the verdict. */
.seat-note {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 0.78rem;
  color: var(--text-faint);
  line-height: 1.5;
}

/* Reassurance that a reload didn't lose the hand. Green rather than the
   leak-hint's accent, because this is good news, not a warning. */
.resume-hint {
  background: rgba(122, 168, 99, 0.1);
  border-color: rgba(122, 168, 99, 0.4);
  color: #9ec287;
}

/* "Nice try... Dad". Centred and short - it exists to be read at a glance
   and dismissed, not studied. */
.busted-card {
  text-align: center;
  padding: 30px 26px 26px;
  max-width: 380px;
  border: 1px solid var(--accent);
}

.busted-emoji { font-size: 2.6rem; line-height: 1; margin-bottom: 10px; }

.busted-card h2 {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-size: 1.7rem;
  color: var(--accent);
  margin: 0 0 10px;
}

.busted-card p {
  color: var(--text-dim);
  font-size: 0.92rem;
  margin: 0 0 20px;
}

.busted-card button { width: 100%; }

/* Day streak. Deliberately louder than the share card below it - returning
   tomorrow is worth more than a share, so it wins the visual priority. */
.day-streak {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0 0;
  padding: 14px 16px;
  background: rgba(201, 121, 63, 0.1);
  border: 1px solid var(--accent-dim);
  border-radius: var(--radius-sm);
}

.day-streak-flame { font-size: 1.5rem; line-height: 1; flex: none; }

.day-streak b {
  font-size: 1.35rem;
  color: var(--accent);
  margin-right: 5px;
}

.day-streak > div > span { font-size: 0.85rem; color: var(--text-dim); }

.day-streak-note {
  margin-left: auto;
  text-align: right;
  font-size: 0.78rem;
  color: var(--text-faint);
  max-width: 46%;
}

/* Add-to-home-screen prompt. Quiet by design: it appears unasked-for, so it
   reads as an offer rather than an interruption. */
/* Stacked at every width on purpose. This was previously side-by-side with
   a max-width:480px media query dropping it to a column, which left every
   viewport between 481px and the modal's own width laying two buttons
   beside the copy with no room - "Not now" ran off the right edge on a
   normal Android phone. A breakpoint that has to guess the device is the
   wrong tool when the container is a modal whose width the viewport only
   partly determines; stacking needs no guess. */
.install-prompt {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 12px 0 0;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.install-copy { min-width: 0; }
.install-copy b { display: block; font-size: 0.92rem; margin-bottom: 2px; }
.install-copy span { font-size: 0.82rem; color: var(--text-dim); }

.install-actions { display: flex; gap: 8px; align-items: stretch; width: 100%; }

/* min-width:0 lets a button shrink below its text width instead of forcing
   the row wider than its container, which is what actually pushed the
   second button off-screen. Text wraps rather than overflowing. */
.install-actions button { flex: 1 1 0; min-width: 0; white-space: normal; }

@media (max-width: 480px) {
  .day-streak-note { margin-left: 0; max-width: none; text-align: left; flex-basis: 100%; }
  .day-streak { flex-wrap: wrap; }
  .install-actions { margin-left: 0; flex-basis: 100%; }
  .install-actions button { flex: 1; }
}

/* Daily share card. Sits directly under the score because that's the moment
   the player is most likely to want to post it - burying it below the
   leaderboard and the missed-hands list would mean scrolling past the two
   things most likely to make them close the modal. */
.daily-share {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: 16px 0 4px;
  padding: 16px 12px 18px;
  background: var(--surface-2);
  border: 1px solid var(--accent-dim);
  border-radius: var(--radius-sm);
}

/* The grid alone didn't say what the block was for, so the primary action
   on this screen read as an afterthought below the score. */
.daily-share-title {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}

/* The grid is the hero of this block, so it gets to be big. letter-spacing
   separates the circles, which otherwise butt together into one blob at
   this size. user-select makes the manual-copy fallback in
   shareDailyResult() actually possible.

   nowrap + a vw-scaled size is deliberate: all ten circles have to sit on
   one line to read as a single result. Left to wrap, a 375px phone broke
   them 8 + 2, which looks like a rendering fault rather than a score. The
   clamp shrinks the circles on narrow screens instead. */
.daily-share-grid {
  font-size: clamp(0.95rem, 4.4vw, 1.35rem);
  line-height: 1.2;
  letter-spacing: 0.08em;
  white-space: nowrap;
  user-select: all;
  -webkit-user-select: all;
  text-align: center;
}

.daily-share .btn-primary {
  width: 100%;
}

.daily-share-status {
  font-size: 0.8rem;
  color: var(--accent);
}

.daily-share-fallback {
  margin: 0;
  padding: 10px 12px;
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text);
  text-align: center;
  white-space: pre-wrap;
  word-break: break-word;
  user-select: all;
  -webkit-user-select: all;
}

.summary-actions {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.summary-actions button {
  flex: 1;
}

.stat-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.stat-row {
  display: grid;
  grid-template-columns: 100px 1fr 74px;
  align-items: center;
  gap: 10px;
  font-size: 0.82rem;
}

.stat-row.low-n { opacity: 0.6; }

.stat-row .stat-label { color: var(--text-dim); }

.stat-row .stat-bar-track {
  background: var(--surface-2);
  border-radius: 999px;
  height: 8px;
  overflow: hidden;
}

.stat-row .stat-bar-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-dim), var(--accent));
}

.stat-row.weak .stat-bar-fill { background: linear-gradient(90deg, #b34848, var(--bad)); }

.stat-row .stat-pct {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  font-weight: 700;
  color: var(--text);
  line-height: 1.2;
}

.stat-row .stat-n {
  font-size: 0.66rem;
  font-weight: 500;
  color: var(--text-faint);
}

.stat-empty {
  color: var(--text-faint);
  font-size: 0.82rem;
  font-style: italic;
}

.leaderboard-row {
  grid-template-columns: 1fr auto;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.leaderboard-row .stat-label { color: var(--text); font-weight: 600; }

.leaderboard-row.is-me {
  background: rgba(201, 121, 63, 0.12);
  border: 1px solid var(--accent-dim);
}

.leaderboard-row.is-me .stat-label { color: var(--accent); }

.leaderboard-streak {
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* Level tab only - the unit sits under the number rather than trailing it,
   which the Daily tab's "10/10 1m24s" pairing deliberately doesn't do. */
.leaderboard-streak.stacked {
  text-align: right;
  line-height: 1.15;
}

.leaderboard-streak.stacked .stat-n {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.history-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
}

.history-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 0.78rem;
}

.history-row .mark {
  font-weight: 800;
  width: 16px;
  text-align: center;
}

.history-row.right .mark { color: var(--good); }
.history-row.wrong .mark { color: var(--bad); }

.history-row .hist-pos {
  font-weight: 700;
  width: 46px;
}

.history-row .hist-desc {
  color: var(--text-dim);
  flex: 1;
}

/* ---- toast ---- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  background: var(--surface-2);
  border: 1px solid var(--accent-dim);
  color: var(--accent);
  font-weight: 700;
  font-size: 0.9rem;
  padding: 10px 20px;
  border-radius: 999px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 200;
  pointer-events: none;
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 640px) {
  /* Navbar: fit everything on one row instead of letting Home/Stats wrap
     onto their own line, which was eating ~90px of vertical space before
     the game even started. Brand wordmark and the "this session" counter
     are the least essential things on screen mid-game, so they're what
     gives way first. */
  .navbar { padding: 7px 10px; flex-wrap: nowrap; gap: 6px; }
  .brand-name { display: none; }
  .nav-right { gap: 8px; }
  .nav-stats { gap: 8px; }
  .nav-stats .nav-stat:first-child { display: none; }
  .nav-stat label { margin-left: 3px; font-size: 0.62rem; }
  .nav-player { display: none; }
  .btn-ghost { padding: 6px 9px; font-size: 0.78rem; }

  .start-card { padding: 26px 20px; border-radius: 16px; }
  .feature-row { flex-direction: column; }
  .feature { flex-direction: row; justify-content: flex-start; text-align: left; }

  /* Table screen: tighten every gap/padding and flatten the table itself
     so the action buttons and Next Hand land on-screen without scrolling
     on a real phone (Safari's chrome eats a lot more height than a bare
     viewport number suggests). */
  main#tableScreen { padding: 10px; gap: 8px; }
  .table-wrap { padding-top: 78%; border-width: 10px; }
  .seat { width: 60px; }
  .seat .name { font-size: 0.64rem; padding: 1px 3px; }
  .seat .cards { margin: 2px 0; min-height: 24px; }
  .seat .action-badge { font-size: 0.62rem; min-height: 11px; }
  .mini-card { width: 13px; height: 18px; }
  .big-card { width: 46px; height: 64px; font-size: 1.3rem; }
  .stack-badge { padding: 6px 9px; min-width: 52px; }
  .stack-badge-value { font-size: 0.92rem; }
  .hero-panel { padding: 12px; gap: 8px; }
  .situation { font-size: 0.85rem; }
  .actions { gap: 8px; }
  .actions button { min-width: 0; padding: 10px 12px; font-size: 0.82rem; }
  .feedback { padding: 12px; }
  .next-row { gap: 8px; }

  .stat-row { grid-template-columns: 76px 1fr 64px; font-size: 0.76rem; }
  .modal-body { padding: 6px 14px 18px; }
  .range-cell { font-size: 0.48rem; }
}


/* =========================================================================
   EXPERT THEME - "Darkroom + Obsidian Table" (2026-09-12 redesign).
   Self-contained and fully reversible: toggled purely by a "theme-expert"
   class on the top-level .app element (see applyModeTheme()/applyHomeTheme()
   in app.js, the only places that class is ever set) while playing Classic
   Expert Mode or Sizing Expert Mode, or while sitting on the home screen
   with either toggle on. To back the whole feature out, delete this block
   and those two call sites; nothing else references "theme-expert".

   The previous version overrode --accent to hot pink, which retinted every
   accent-bearing element at once and left pink text on an oxblood ground -
   less readable than what it replaced, for no gain beyond "it's a different
   colour". So the rule here is: DO NOT TOUCH --accent. Copper is the brand
   and it stays put in both modes.

   What changes instead is light and material:
     - the lights come down (a darker ground, a vignette closing in on the
       table, chrome dimmed back) so contrast goes UP, not down; and
     - the felt itself turns obsidian with a copper rail - you've been moved
       to the table in the back room. Obsidian is also the final chip
       denomination in the level system, so the hardest mode is played on
       the highest table.
   ========================================================================= */

/* Darkroom: everything recedes a stop. Only --bg and the two surfaces move,
   so text/accent tokens keep their exact relationships and every contrast
   pair in the app gets better rather than worse. */
.app.theme-expert {
  --bg: #0d0807;
  --surface: #160e0c;
  --surface-2: #1e1411;
  --border: #32211c;
  /* body is .app's PARENT, so overriding --bg here can't reach the page
     background - .app has to paint the darker ground itself. It's
     min-height:100vh, so this covers the viewport. */
  background: var(--bg);
}

/* Obsidian table: near-black felt, copper rail. The only colour change on
   the table, and it touches no text. */
.app.theme-expert .table-wrap {
  --felt: #2a2229;
  --felt-dark: #0f0c10;
  --rail: #7a4a24;
  --rail-dark: #150d08;
  border-color: #7a4a24;
  outline-color: #150d08;
  box-shadow:
    inset 0 0 46px rgba(0, 0, 0, 0.72),
    var(--shadow-lg),
    0 0 58px 10px rgba(201, 121, 63, 0.11);
}

/* The "lamp over the table" falloff is baked into the felt's own gradient
   rather than layered over anything. Two earlier attempts were worse: a
   full-viewport overlay dimmed the situation text and action buttons (the
   same legibility complaint that sank the pink theme, arriving a different
   way), and an overlay confined to .table-wrap still sat on top of the seat
   labels. As a background there is nothing to stack over and nothing that
   can be dimmed by accident. */
.app.theme-expert .table-wrap {
  background:
    radial-gradient(ellipse 74% 74% at 50% 44%,
      var(--felt) 0%,
      #17131b 58%,
      var(--felt-dark) 100%);
}

/* Chrome recedes: the nav is scaffolding, not the hand in front of you. */
.app.theme-expert .navbar {
  opacity: 0.62;
  transition: opacity 0.25s ease;
}

.app.theme-expert .navbar:hover,
.app.theme-expert .navbar:focus-within {
  opacity: 1;
}

/* The expert flag on the felt: an etched wordmark where the app icon sits in
   Classic, stamped into the table the way a maker's mark would be. Sized off
   the table rather than fixed, so it holds its proportion on a phone. The
   dark shadow above and light below is what reads as "cut into" rather than
   "printed on". */
.app.theme-expert .table-logo {
  opacity: 0;
}

.app.theme-expert .table-logo-expert {
  display: flex;
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 600;
  font-size: clamp(0.8rem, 3.4vw, 1.35rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(243, 233, 226, 0.13);
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(243, 233, 226, 0.07);
}

/* A hairline rule either side of the wordmark, like an engraved cartouche.
   Scaled in em so they track the text at every size. */
.app.theme-expert .table-logo-expert::before,
.app.theme-expert .table-logo-expert::after {
  content: "";
  display: block;
  width: 1.6em;
  height: 1px;
  background: rgba(243, 233, 226, 0.12);
}

.app.theme-expert .table-logo-expert::before { margin-right: 0.7em; }
.app.theme-expert .table-logo-expert::after { margin-left: 0.7em; }

/* Badge: outlined rather than filled, and no pulse. The old one throbbed
   pink on a 2.4s loop, which is what made it read as a warning notice. */
.app.theme-expert .expert-badge {
  background: transparent;
  border: 1px solid var(--accent-dim);
  color: var(--accent);
}

/* Start screen has no table to carry the obsidian cue, so the darkroom does
   the work there: a single low copper wash instead of the pink one. */
.app.theme-expert .start-screen {
  background:
    radial-gradient(ellipse at top, rgba(201, 121, 63, 0.10), transparent 62%),
    var(--bg);
}

.app.theme-expert .start-card {
  border-color: rgba(201, 121, 63, 0.22);
  box-shadow: var(--shadow-lg), 0 0 44px rgba(0, 0, 0, 0.5);
}
/* ==== END EXPERT THEME ================================================== */
