/* Dark is the default palette; the light theme overrides these tokens under
   html[data-theme='light']. Everything that changes between themes reads a token here —
   no theme-specific colour is hardcoded in a rule below. */
:root {
  --bg: #0b0b0f;
  --inactive-text: #6e6e7a;
  --delay: #2ecc71;
  --reserve: #f5a623;
  --low: #f40009;
  --control-bar: #15151c;
  --control-text: #e6e6ec;
  --accent: #0176d3;
  --card: #1e1e28;
  --target: #f2c94c; /* gold — the match target (a goal label, not a clock state) */
  --app-max: 480px; /* cap the width so it stays phone-shaped on desktop */
  --die-body: #f4f4f6; /* dice colour (user-selectable) */
  --die-pip: #101017;

  /* Semantic surface/line/icon tokens (so both themes share one set of rules). */
  --rail-bg: #16161f; /* score-rail column */
  --floor-text: #ffffff; /* live score number in the rail */
  --hairline: rgba(255, 255, 255, 0.14); /* dividers / borders */
  --surface: #1e1e28; /* dialogs, scoring cards, pills */
  --btn-bg: #2a2a34; /* secondary buttons (cog, ctrl, dialog, mode) */
  --switch-off: #3a3a44; /* toggle track when off */
  --icon-filter: brightness(0) invert(1); /* emoji → solid white silhouette */
  --overlay: rgba(10, 10, 15, 0.97); /* doubling-cube offer card */
  --scrim: rgba(0, 0, 0, 0.55); /* modal backdrop */
}

/* Light theme — a bright, paper-like surface with darker state colours for contrast. */
html[data-theme='light'] {
  --bg: #eef0f4;
  --inactive-text: #8b909c;
  --delay: #17924a;
  --reserve: #c9770a;
  --low: #d40008;
  --control-bar: #dfe2ea;
  --control-text: #1b1c24;
  --accent: #0176d3;
  --card: #ffffff;
  --target: #b8860b;

  --rail-bg: #e3e6ee;
  --floor-text: #1b1c24;
  --hairline: rgba(0, 0, 0, 0.14);
  --surface: #ffffff;
  --btn-bg: #d6dae3;
  --switch-off: #c2c6d0;
  --icon-filter: brightness(0); /* emoji → solid black silhouette */
  --overlay: rgba(238, 240, 244, 0.97);
  --scrim: rgba(0, 0, 0, 0.4);
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  /* Remove the tap-to-switch latency (double-tap-zoom disambiguation) while keeping
     scroll/pan. Makes the turn-switch feel instant and reliable. */
  touch-action: manipulation;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--control-text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  overflow: hidden;
  overscroll-behavior: none;
}

#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  /* viewport-fit=cover lets the app fill the screen. Inset only the TOP so the top seat
     clears the status bar / Dynamic Island; the app runs flush to the bottom edge (the
     home indicator is a thin translucent bar and the bottom clock is centred well clear
     of it). env() is 0 on devices without insets (e.g. desktop). */
  padding-top: env(safe-area-inset-top, 0px);
  /* Stay phone-shaped and centred on wide (desktop) screens; full width on mobile. */
  max-width: var(--app-max);
  margin: 0 auto;
}

/* The full-screen overlays (settings sheet, scoring, match-over) are position:fixed with
   inset:0, so they ignore #app's max-width. With left:0/right:0 already set, a max-width
   plus auto inline margins centres them to the same column on desktop. */
.options,
.scoring {
  max-width: var(--app-max);
  margin-inline: auto;
}

/* --- Player seats: score rail on each player's own left + centred clock --- */
.seat {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  min-width: 0;
}
.seat.flip {
  transform: rotate(180deg);
}
.clock {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* --- Score rail: an elevator shaft with a lift "car" that rides to the score's floor --- */
.rail {
  flex: 0 0 70px;
  display: flex;
  flex-direction: column;
  background: var(--rail-bg);
  border-right: 1px solid var(--hairline);
}
.rail[hidden] {
  display: none;
}
/* Target score at the top of each player's column (their goal). */
.rail-target {
  flex: 0 0 auto;
  text-align: center;
  padding: 8px 0 2px;
  /* Same font as the live score, but gold — a distinct "goal" label, not the grey of a
     disabled control. */
  font-size: clamp(30px, 9vw, 44px);
  font-weight: 800;
  color: var(--target);
  font-variant-numeric: tabular-nums;
}
/* Penthouse: where the cube rests when this player owns it. */
.cube-home {
  flex: 0 0 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Delineator: the cube (doubling) is functionally separate from the score below. */
  border-bottom: 1px solid var(--hairline);
}
.cube-home[hidden] {
  display: none;
}
/* The shaft is a real flex column of one cell per point-level; the score number lives in
   its own cell (blank elsewhere). Cells are generated per match length. */
.shaft {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin: 0 8px 10px;
}
.floor {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid var(--hairline);
  font-size: clamp(20px, 6vw, 34px);
  font-weight: 800;
  color: var(--floor-text);
  font-variant-numeric: tabular-nums;
}
.floor:last-child {
  border-bottom: none;
}

/* --- Doubling cube: docked in the centre bar (unowned) or on the owner's penthouse --- */
.cube[hidden] {
  display: none;
}
.cube {
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 9px;
  background: #f4f4f6;
  color: #101017;
  font-size: 22px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
.cube-val {
  display: inline-block;
}
.cube[data-offerable='true'] {
  outline: 2px solid var(--delay);
  outline-offset: 2px;
}
/* A cube that can't be offered right now (not this player's turn, or not the owner) is
   dimmed so only the actionable one stands out — enforcing the turn rule visually. */
.cube:not([data-offerable='true']) {
  opacity: 0.4;
}
.cube:active {
  opacity: 0.7;
}

/* --- Player halves --- */
.half {
  flex: 1;
  display: flex;
  align-items: stretch;
  border: none;
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--inactive-text);
  font: inherit;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.half[data-state='inactive'] {
  color: var(--inactive-text);
}
.half[data-state='delay'] {
  color: var(--delay);
}
.half[data-state='reserve'] {
  color: var(--reserve);
}
.half[data-state='low'] {
  color: var(--low);
}
.half[data-state='ready'] {
  color: var(--control-text);
}
/* Pre-game invitation shown in place of the delay countdown. Height stays fixed (see
   .delay) so switching to the running "10s" text doesn't reflow the clock. */
.half[data-state='ready'] .delay {
  font-size: clamp(16px, 5vw, 22px);
  font-weight: 700;
  letter-spacing: 3px;
}
.half[data-state='win'] {
  color: var(--delay);
}

/* Game-over status shown on the clock itself. */
.half .delay.status {
  font-size: clamp(24px, 7vw, 36px);
  font-weight: 800;
  letter-spacing: 2px;
}

.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: inherit;
}
.content.flip {
  transform: rotate(180deg);
}

.reserve-label {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 4px;
  height: 20px;
  line-height: 20px;
  margin-bottom: 4px;
  color: inherit;
}
.reserve {
  font-size: clamp(72px, 22vw, 128px);
  font-weight: 200;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: inherit;
}
.delay {
  font-size: clamp(28px, 9vw, 44px);
  font-weight: 600;
  margin-top: 8px;
  /* Fixed height + min-width so the text changing (10s->9s, or TAP TO START->10s)
     never reflows or recentres the clock. */
  height: 48px;
  line-height: 48px;
  min-width: 96px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: inherit;
}

/* --- Dice (auto-rolled for the player on the clock) --- */
/* Fixed-height slot reserved on both halves (when dice are enabled) so a roll appearing
   or clearing on a turn switch never reflows the clock. Sits inside the seat, so the top
   player's dice are oriented correctly for free. */
.dice {
  height: 44px;
  margin-top: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.dice[hidden] {
  display: none;
}
/* Ivory die with dark pips — matches the doubling cube's material. */
.die {
  width: 44px;
  height: 44px;
  padding: 6px;
  box-sizing: border-box;
  background: var(--die-body);
  border-radius: 9px;
  /* Inner hairline keeps a dark die's edge visible against the dark background. */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 2px 8px rgba(0, 0, 0, 0.5);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
}
.die .cell {
  display: flex;
  align-items: center;
  justify-content: center;
}
.die .cell.on::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--die-pip);
}
/* The received roll shown on the undo-review card: the dice slot sits inside the card's own
   gap, so drop its default top margin. */
.undo-dice {
  margin-top: 0;
}
/* Lively drop-and-tumble on a fresh roll (skipped when the animation setting is off):
   the die falls in with a couple of fast spins, overshoots, then settles with a small
   bounce. The two dice are staggered so they don't land in lockstep. */
.dice.rolling .die {
  animation: dieRoll 0.62s cubic-bezier(0.2, 0.75, 0.35, 1) both;
  transform-origin: center 60%;
}
.dice.rolling .die:first-child {
  animation-delay: 0s;
}
.dice.rolling .die:last-child {
  animation-delay: 0.1s;
}
@keyframes dieRoll {
  0% {
    transform: translateY(-90%) rotate(-260deg) scale(0.45);
    opacity: 0.3;
  }
  35% {
    transform: translateY(12%) rotate(-40deg) scale(1.16);
    opacity: 1;
  }
  55% {
    transform: translateY(-10%) rotate(20deg) scale(0.94);
  }
  72% {
    transform: translateY(5%) rotate(-9deg) scale(1.05);
  }
  86% {
    transform: translateY(-3%) rotate(4deg) scale(0.99);
  }
  100% {
    transform: translateY(0) rotate(0) scale(1);
  }
}

/* Respect a reduced-motion preference: keep the roll instant, no tumble. */
@media (prefers-reduced-motion: reduce) {
  .dice.rolling .die {
    animation: none;
  }
}

/* --- Roll history: each player's last few rolls as mini-dice pairs, pinned to their own edge
   of the screen. The strip lives inside each .half and is positioned per seat so it reads
   upright for that player (the top player's is rotated 180° like the rest of their view). --- */
.history {
  position: absolute;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px; /* between roll pairs */
  padding: 6px 10px;
  z-index: 3; /* above the clock, below the doubling-cube offer card (z-index 5) */
  pointer-events: none; /* purely informational — never intercept taps that switch turns */
}
.history[hidden] {
  display: none;
}
/* Bottom player: along the bottom edge, mirroring the top player's 6px. (We deliberately do NOT
   add safe-area-inset-bottom here — on iPhone that ~34px inset pushes the strip up into the
   centred clock's dice. The strip is non-interactive, and the app already runs flush to the
   bottom edge, so sitting near the home indicator is consistent with the rest of the UI.) */
#half-1 .history {
  bottom: 6px;
}
/* Top player: along the top edge, rotated so it faces them. */
#half-0 .history {
  top: 6px;
  transform: rotate(180deg);
}
/* Centre the strip under the CLOCK rather than the whole half: when the score rail is shown
   (3+ point matches, marked with .has-rail), inset past the 70px rail on the side it occupies —
   screen-left for the bottom seat, screen-right for the top (rotated) seat — so the dice line up
   under the clock. Falls back to full-width-centred for 1-point matches (no rail). */
#half-1.has-rail .history {
  left: 70px;
}
#half-0.has-rail .history {
  right: 70px;
}
.hist-pair {
  display: flex;
  gap: 2px; /* between the two dice of one roll */
  overflow: hidden; /* lets the width collapse cleanly when a pair leaves */
}
/* New roll fades up into the slot on the end. */
.hist-pair.enter {
  animation: histEnter 0.3s ease-out;
}
@keyframes histEnter {
  0% {
    opacity: 0;
    transform: translateY(10px) scale(0.75);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
/* Oldest roll fades out and collapses its width, so the remaining pairs slide along to fill. */
.hist-pair.leave {
  animation: histLeave 0.3s ease-in forwards;
}
@keyframes histLeave {
  0% {
    opacity: 1;
    max-width: 46px;
    transform: translateX(0) scale(1);
  }
  100% {
    opacity: 0;
    max-width: 0;
    margin-left: -8px; /* also eat the flex gap so the slide is smooth */
    transform: translateX(-6px) scale(0.7);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hist-pair.enter,
  .hist-pair.leave {
    animation: none;
  }
}
/* Mini die — same 3×3 pip grid as the main die, scaled down and tinted to the player's colour. */
.mini-die {
  width: 18px;
  height: 18px;
  padding: 2px;
  box-sizing: border-box;
  background: var(--die-body);
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14), 0 1px 2px rgba(0, 0, 0, 0.45);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
}
.mini-die .cell {
  display: flex;
  align-items: center;
  justify-content: center;
}
.mini-die .cell.on::after {
  content: '';
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--die-pip);
}

/* Flash cue (replaces haptics on iOS). */
.half.flash {
  animation: flash 0.5s ease-out;
}
@keyframes flash {
  0% {
    background: var(--flash-color, #ffffff);
  }
  100% {
    background: var(--bg);
  }
}

/* --- Doubling-cube offer card (covers the opponent's half) --- */
.offer-card {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
}
.offer-card.flip {
  transform: rotate(180deg);
}
.offer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 24px;
  text-align: center;
}
.offer-title {
  font-size: 22px;
  font-weight: 800;
}
.offer-sub {
  color: var(--inactive-text);
  font-size: 15px;
  margin-top: -8px;
}
.offer-cube {
  width: 76px;
  height: 76px;
  border-radius: 14px;
  background: #f4f4f6;
  color: #101017;
  font-size: 38px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.55);
}
.offer-timer {
  font-size: 20px;
  font-weight: 700;
  color: var(--reserve);
  font-variant-numeric: tabular-nums;
}
.offer-actions {
  display: flex;
  gap: 12px;
  margin-top: 4px;
}
.offer-btn {
  border: none;
  border-radius: 12px;
  padding: 14px 26px;
  font-size: 18px;
  font-weight: 700;
  cursor: pointer;
}
.offer-btn.accept {
  background: var(--delay);
  color: #08210f;
}
.offer-btn.decline {
  background: var(--btn-bg);
  color: var(--control-text);
}
.offer-btn:active {
  opacity: 0.7;
}

/* --- Center control bar --- */
.bar {
  background: var(--control-bar);
  /* No horizontal padding: each side group must reach the screen edge so its cog slot
     lines up with the player's rail (which starts at the very edge). */
  padding: 12px 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
/* Each player's settings live on the middle bar. The cog sits in a slot the same width
   as the rail below (70px) so the cog's centre lines up with the doubling cube / score
   column in that player's rail. The bottom player's group is at screen-left; the top
   player's mirrors it at screen-right with its icons flipped 180° to read for that side.
   Equal flex on both sides keeps the centre action button centred. */
.bar-settings {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.bar-settings.left {
  justify-content: flex-start;
}
.bar-settings.right {
  justify-content: flex-end;
}
.bar-settings.right .bar-cog,
.bar-settings.right .bar-mode {
  transform: rotate(180deg);
}
/* Cog slot matches the rail width so the cog centres over the rail's column below. */
.bar-cog-slot {
  flex: 0 0 70px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bar-cog {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 10px;
  background: var(--btn-bg);
  color: var(--control-text);
  cursor: pointer;
}
.bar-cog[hidden] {
  display: none;
}
.bar-cog:active {
  opacity: 0.6;
}
.bar-mode {
  flex: 0 0 auto;
  border: none;
  background: transparent;
  padding: 4px;
  margin: 0;
  font-size: 26px;
  line-height: 1;
  color: inherit;
  cursor: pointer;
  /* Render the colour emoji as a solid white silhouette so the hare and tortoise share
     one flat look (rather than a white rabbit next to a green turtle). */
  filter: var(--icon-filter);
}
.bar-mode:active {
  opacity: 0.6;
}
.buttons {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Reserve the row height so hiding the buttons (during a double offer) doesn't
     collapse the bar and shift the clocks. */
  min-height: 44px;
}
button.ctrl {
  padding: 10px 24px;
  border-radius: 10px;
  border: none;
  background: var(--btn-bg);
  color: var(--control-text);
  font-size: 17px;
  font-weight: 700;
  min-width: 110px;
  cursor: pointer;
}
button.ctrl.emphasis {
  background: var(--accent);
}
button.ctrl:active {
  opacity: 0.6;
}
/* Icon controls (pause, undo): centre the glyph, with a fixed height so pause and undo match
   regardless of their differently-sized glyphs (the undo SVG is taller than the pause bars; equal
   padding alone left undo taller). Pause keeps the wide 110px pill on its own. */
button.ctrl.ctrl-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 18px;
}
/* While the transient undo button shares the row, both icon buttons go compact so the centre
   cluster stays narrow and clear of the mode icons (two wide pills overflowed the row and collided
   with the hare/tortoise). When undo hides, pause drops this class and returns to the wide pill. */
button.ctrl.ctrl-icon.ctrl-compact {
  min-width: 0;
  /* Equal fixed width so undo and pause match while sharing the row (their glyphs differ in
     width — the circular arrow is wider than the two pause bars). */
  width: 54px;
  padding: 0;
}
/* Two vertical bars — a symmetric pause glyph that reads the same from either seat. */
.ico-pause {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  justify-content: center;
}
.ico-pause::before,
.ico-pause::after {
  content: '';
  width: 5px;
  height: 20px;
  border-radius: 2px;
  background: currentColor;
}

/* --- Options screen --- */
.options {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 10;
}
.options-inner {
  height: 100%;
  padding: max(48px, env(safe-area-inset-top, 0)) 24px 40px;
  display: flex;
  flex-direction: column;
}
/* Face the top player when they opened the sheet. */
.options-inner.flip {
  transform: rotate(180deg);
}
.options h1 {
  font-size: 34px;
  font-weight: 800;
  margin: 0 0 20px;
  text-align: center;
}

/* Tabbed settings: a two-tab bar over a scrollable panel area, with Confirm + footer
   pinned below so a tall tab scrolls internally instead of overflowing the sheet. */
.tabs {
  display: flex;
  margin-bottom: 22px;
  /* Shared baseline the tabs sit on; the active tab's underline overlaps it. */
  border-bottom: 1px solid var(--hairline);
}
.tab {
  flex: 1;
  padding: 12px 4px 14px;
  border: none;
  background: transparent;
  color: var(--inactive-text);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px; /* sit the underline on the baseline rule */
}
.tab.selected {
  color: var(--control-text);
  border-bottom-color: var(--accent);
}
.tab:active {
  opacity: 0.7;
}
.tab-panels {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.tab-panel[hidden] {
  display: none;
}

/* --- Match settings sections --- */
.section {
  margin-bottom: 22px;
}
.section-label {
  color: var(--inactive-text);
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 10px;
}
.section-hint {
  color: var(--inactive-text);
  font-size: 14px;
  margin-top: 10px;
  line-height: 1.4;
}
.segmented {
  display: flex;
  gap: 12px;
}
.seg-btn {
  flex: 1;
  padding: 16px 8px;
  border-radius: 12px;
  border: none;
  background: var(--card);
  color: var(--control-text);
  font-size: 22px;
  font-weight: 700;
  cursor: pointer;
}
.seg-btn.selected {
  background: var(--accent);
}
.seg-ico {
  /* Match the button label: the icon and text share --icon-filter/--control-text, so both
     are dark in light mode and light in dark mode, on the card and the selected accent alike. */
  filter: var(--icon-filter);
}
.seg-btn:active {
  opacity: 0.7;
}
/* The Speed row carries three buttons (Fast / Standard / Casual), each stacking a name line
   over a compact "delay / reserve" summary. Shrink type + icon (vs the default 22px) so the
   three narrower thirds fit on one line. */
#seg-speed .seg-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  font-size: 17px;
  padding: 12px 6px;
  line-height: 1.15;
}
#seg-speed .seg-ico {
  font-size: 20px;
}
/* Name line: icon + label, kept on one row and centred. */
.seg-main {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
/* The timing summary under the name — quieter, tabular so the digits line up across buttons. */
.seg-sub {
  font-size: 12px;
  font-weight: 600;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* Doubling-cube toggle */
.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: var(--card);
  border: none;
  border-radius: 14px;
  padding: 18px 20px;
  color: var(--control-text);
  font-size: 20px;
  font-weight: 600;
  cursor: pointer;
}
.toggle-row.disabled {
  opacity: 0.4;
}
.toggle-row + .toggle-row {
  margin-top: 12px;
}
/* Dice colour chips — same card shell as a toggle-row, label left, swatches right. */
.chips-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 12px;
  background: var(--card);
  border-radius: 14px;
  padding: 14px 18px;
}
/* First colour row sits directly under its section heading (like other sections' content),
   rather than adding its inter-row top margin on top of the label's spacing. */
.section-label + .chips-row {
  margin-top: 0;
}
.chips-row.disabled {
  opacity: 0.4;
}
.chips-label {
  color: var(--control-text);
  font-size: 20px;
  font-weight: 600;
}
.chips {
  display: flex;
  gap: 10px;
}
.chip {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 8px;
  padding: 0;
  cursor: pointer;
  background: var(--chip-color);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.chip.selected {
  outline: 3px solid var(--control-text);
  outline-offset: 2px;
}
.chip:active {
  opacity: 0.7;
}
.toggle-row .switch {
  flex: 0 0 auto;
  width: 56px;
  height: 32px;
  border-radius: 16px;
  background: var(--switch-off);
  position: relative;
  transition: background 0.15s ease;
}
.toggle-row .knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #fff;
  transition: left 0.15s ease;
}
.toggle-row.on .switch {
  background: var(--accent);
}
.toggle-row.on .knob {
  left: 27px;
}
.done {
  background: var(--accent);
  border: none;
  border-radius: 12px;
  padding: 18px;
  color: #fff;
  font-size: 20px;
  font-weight: 700;
  margin-top: auto;
  cursor: pointer;
}
.app-footer {
  margin-top: 16px;
  text-align: center;
  color: var(--inactive-text);
  font-size: 13px;
  letter-spacing: 0.3px;
}
.app-footer a {
  color: var(--accent);
  text-decoration: none;
}
.app-footer a:hover {
  text-decoration: underline;
}
/* A plain navigational link inside a settings section (e.g. the sound-board link). */
.settings-link {
  display: inline-block;
  color: var(--accent);
  text-decoration: none;
  font-size: 16px;
  font-weight: 600;
}
.settings-link:active {
  opacity: 0.6;
}

/* --- Pause dialog --- */
.dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--scrim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.dialog {
  background: var(--surface);
  border-radius: 20px;
  padding: 28px 24px;
  width: 100%;
  max-width: 360px;
  text-align: center;
}
.dialog-title {
  font-size: 26px;
  font-weight: 800;
}
.dialog-sub {
  color: var(--inactive-text);
  font-size: 16px;
  margin: 6px 0 22px;
}
.dialog-btn {
  display: block;
  width: 100%;
  border: none;
  border-radius: 14px;
  padding: 16px;
  font-size: 19px;
  font-weight: 700;
  cursor: pointer;
  background: var(--btn-bg);
  color: var(--control-text);
  margin-top: 12px;
}
.dialog-btn.primary {
  background: var(--accent);
  color: #fff;
}
/* Destructive: end the match (scores discarded, back to settings). */
.dialog-btn.danger {
  color: var(--low);
}

/* --- Speed picker (per player, from the hare/tortoise icon) --- */
#speed-inner.flip {
  transform: rotate(180deg);
}
.speed-opt {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  border: none;
  border-radius: 14px;
  padding: 14px 16px;
  margin-top: 12px;
  background: var(--btn-bg);
  color: var(--control-text);
  cursor: pointer;
  text-align: left;
}
.speed-opt.selected {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.speed-opt:active {
  opacity: 0.7;
}
.speed-ico {
  flex: 0 0 auto;
  font-size: 34px;
  line-height: 1;
  filter: var(--icon-filter); /* solid silhouette, matching the bar icons */
}
.speed-text {
  display: flex;
  flex-direction: column;
}
.speed-name {
  font-size: 20px;
  font-weight: 700;
}
.speed-desc {
  font-size: 14px;
  color: var(--inactive-text);
  font-variant-numeric: tabular-nums;
}
.dialog-btn:active {
  opacity: 0.7;
}

/* --- Scoring screen (split like the clock) --- */
.scoring {
  position: fixed;
  inset: 0;
  z-index: 15;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
.score-half {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 24px;
  overflow: hidden;
}
.score-center {
  padding: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.match-pill {
  background: var(--surface);
  color: var(--inactive-text);
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 600;
}
.score-status {
  color: var(--inactive-text);
  font-size: 20px;
  font-weight: 700;
  text-align: center;
}
.cry {
  font-size: 72px;
  text-align: center;
  margin-top: 8px;
}
.score-options {
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.score-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: none;
  border-radius: 14px;
  padding: 18px 20px;
  cursor: pointer;
  background: var(--surface);
  color: var(--control-text);
  font-size: 22px;
  font-weight: 700;
}
.score-opt .pts {
  color: var(--inactive-text);
  font-size: 18px;
  font-weight: 600;
}
.score-opt:active {
  opacity: 0.7;
}
.score-caption {
  color: var(--inactive-text);
  font-size: 14px;
  text-align: center;
  margin-top: 14px;
}

/* --- Match over (split; each half faces its player) --- */
.mo-result {
  font-size: clamp(34px, 11vw, 52px);
  font-weight: 800;
  letter-spacing: 1px;
}
.mo-result.win {
  color: var(--delay);
}
.mo-result.lose {
  color: var(--inactive-text);
}
.mo-sub {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--inactive-text);
  margin-top: 2px;
  text-transform: uppercase;
}
.mo-score {
  font-size: clamp(28px, 9vw, 40px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
}
.mo-actions {
  gap: 10px;
}
.mo-btn {
  border: none;
  border-radius: 10px;
  padding: 10px 22px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  background: var(--btn-bg);
  color: var(--control-text);
}
.mo-btn.primary {
  background: var(--accent);
  color: #fff;
}
.mo-btn:active {
  opacity: 0.7;
}

[hidden] {
  display: none !important;
}
