/* ==========================================================================
   iOS-Douz — stylesheet
   --------------------------------------------------------------------------
   A native-feeling iOS interface for a classic Tic-Tac-Toe game.

   Design system:
     * Colour tokens are semantic CSS custom properties, defined once for the
       light appearance and overridden for the dark appearance. No colour is
       hard-coded inside a component rule.
     * Dark mode is enabled with a `data-theme="dark"` attribute on <html>.
       It is chosen in js/ui.js from the saved preference, or from the
       `prefers-color-scheme` media query when the preference is "auto".
     * Hairline separators use a 0.5px border, which iOS renders as a true
       single-pixel line on high-density screens.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens — LIGHT APPEARANCE
   Palette reference: Apple iOS system colours (systemBlue, systemRed,
   systemGreen, systemGray, systemGray3, separator, systemGroupedBackground).
   -------------------------------------------------------------------------- */
:root {
  /* Semantic colours */
  --color-primary: #007AFF;            /* iOS systemBlue — interactive elements, player X */
  --color-destructive: #FF3B30;        /* iOS systemRed — reset / dangerous actions */
  --color-success: #34C759;            /* iOS systemGreen — player O, winning line */
  --color-secondary-text: #8E8E93;     /* iOS systemGray — captions. On --color-background
                                          this is 3.4:1 (large text / AA non-text). Body-size
                                          secondary text uses --color-tertiary-text instead. */
  --color-tertiary-text: #6B6B70;      /* 5.4:1 on --color-background — AA for body text */

  --color-background: #F2F2F7;         /* systemGroupedBackground — page */
  --color-surface: #FFFFFF;            /* cards, cells, alerts, sheets */
  --color-elevated: #FFFFFF;           /* floating layers (action bar) */
  --color-fill-secondary: rgba(120, 120, 128, 0.16); /* iOS secondary fill */
  --color-fill-tertiary: rgba(118, 118, 128, 0.12); /* pressed states, thumb */
  --color-separator: rgba(60, 60, 67, 0.18);        /* hairline separators */
  --color-separator-opaque: #C6C6C8;

  --color-label: #1C1C1E;              /* label — near-black, never pure #000 */
  --color-on-accent: #FFFFFF;

  /* Player tints (used for score cards and win highlighting) */
  --color-x-tint: rgba(0, 122, 255, 0.10);
  --color-o-tint: rgba(52, 199, 89, 0.12);
  --color-draw-tint: rgba(142, 142, 147, 0.14);

  /* Elevation */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 20px rgba(0, 0, 0, 0.06);
  --shadow-float: 0 -1px 0 var(--color-separator), 0 -8px 24px rgba(0, 0, 0, 0.06);
  --shadow-alert: 0 20px 60px rgba(0, 0, 0, 0.22);

  /* Geometry */
  --radius-cell: 18px;
  --radius-card: 18px;
  --radius-control: 12px;
  --radius-sheet: 20px;
  --radius-alert: 20px;
  --hairline: 0.5px;

  /* Typography (rem-based so a browser font-size change scales everything,
     the web equivalent of iOS Dynamic Type) */
  --font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
                 "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --text-large-title: 2rem;
  --text-title3: 1.25rem;
  --text-headline: 1.0625rem;
  --text-body: 1.0625rem;
  --text-callout: 0.9375rem;
  --text-footnote: 0.8125rem;
  --text-caption: 0.75rem;

  /* Motion: spring-like cubic-béziers, matching iOS easing curves */
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);   /* overshoot, for marks and switches */
  --ease-out: cubic-bezier(0.25, 0.1, 0.25, 1);
  --duration-fast: 140ms;
  --duration-base: 260ms;
  --duration-slow: 420ms;

  color-scheme: light;
}

/* --------------------------------------------------------------------------
   2. Design tokens — DARK APPEARANCE
   Layers are separated by lightness rather than by shadow, semantic colours
   are the darker iOS variants, and text is off-white instead of pure white.
   -------------------------------------------------------------------------- */
[data-theme="dark"] {
  --color-primary: #0A84FF;
  --color-destructive: #FF453A;
  --color-success: #30D158;
  --color-secondary-text: #98989F;     /* systemGray (dark) — 5.2:1 on --color-background */
  --color-tertiary-text: #AEAEB2;      /* systemGray2 (dark) — 7.4:1 on --color-background */

  --color-background: #000000;         /* page, the deepest layer */
  --color-surface: #1C1C1E;            /* cards, cells */
  --color-elevated: rgba(38, 38, 40, 0.82); /* translucent floating bar */
  --color-fill-secondary: rgba(120, 120, 128, 0.32);
  --color-fill-tertiary: rgba(118, 118, 128, 0.24);
  --color-separator: rgba(84, 84, 88, 0.6);
  --color-separator-opaque: #38383A;

  --color-label: #F2F2F7;              /* off-white, not #FFFFFF */

  --color-x-tint: rgba(10, 132, 255, 0.16);
  --color-o-tint: rgba(48, 209, 88, 0.16);
  --color-draw-tint: rgba(152, 152, 159, 0.18);

  --shadow-card: 0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 10px 26px rgba(0, 0, 0, 0.5);
  --shadow-float: 0 -1px 0 var(--color-separator), 0 -8px 24px rgba(0, 0, 0, 0.5);
  --shadow-alert: 0 20px 60px rgba(0, 0, 0, 0.6);

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

/* The `hidden` attribute must always win: several components below declare
   `display: flex`, which would otherwise override the UA style and leave the
   alert and sheet backdrops visible on load. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  font-family: var(--font-family);
  font-size: var(--text-body);
  line-height: 1.35;
  letter-spacing: -0.011em;
  color: var(--color-label);
  background-color: var(--color-background);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Theme changes cross-fade instead of snapping. */
  transition: background-color var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  overscroll-behavior-y: none;
}

button { font: inherit; color: inherit; }

code {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--color-fill-tertiary);
  padding: 0.1em 0.35em;
  border-radius: 5px;
}

/* Visually hidden, still announced by assistive technology. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Visible keyboard focus ring — removed for pointer users. */
:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   4. Navigation bar — translucent, blurred, large-title collapse is omitted
      to keep the layout simple, but the material is authentic.
   -------------------------------------------------------------------------- */
.nav-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background-color: var(--color-background);           /* fallback where color-mix is unsupported */
  background-color: color-mix(in srgb, var(--color-background) 78%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: var(--hairline) solid var(--color-separator);
  padding-top: env(safe-area-inset-top, 0px);
}

.nav-bar__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  max-width: 520px;
  margin: 0 auto;
  min-height: 44px;                 /* iOS navigation bar height */
  padding: 0.25rem 0.5rem;
}

.nav-bar__title {
  margin: 0;
  font-size: var(--text-headline);
  font-weight: 600;
  letter-spacing: -0.022em;
  text-align: center;
}

.nav-bar__side { display: flex; align-items: center; min-width: 44px; }
.nav-bar__side--trailing { justify-content: flex-end; }

/* Bar button: blue, icon-only, minimum 44x44 pt touch target. */
.bar-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0.375rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--color-primary);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--spring);
}

.bar-button:hover { background-color: var(--color-fill-tertiary); }
.bar-button:active { background-color: var(--color-fill-secondary); transform: scale(0.9); }

.bar-button__icon svg { display: block; width: 22px; height: 22px; }

/* --------------------------------------------------------------------------
   5. Page layout
   -------------------------------------------------------------------------- */
.app {
  max-width: 520px;
  margin: 0 auto;
  padding: 1.25rem 1rem 9rem;        /* room for the sticky action bar */
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* --------------------------------------------------------------------------
   6a. Match mode — opponent picker and AI options
   -------------------------------------------------------------------------- */
.match { display: flex; flex-direction: column; gap: 0.625rem; }

.match__options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  animation: options-in var(--duration-base) var(--spring);
}

@keyframes options-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.match__you { display: flex; align-items: center; gap: 0.5rem; }

.match__you-label {
  font-size: var(--text-footnote);
  font-weight: 500;
  color: var(--color-tertiary-text);
}

.segmented-control--marks .segmented-control__item { min-width: 44px; }

/* While the AI "thinks", squares lose the pointer affordance. */
.board.is-locked .cell:not(:disabled) { cursor: progress; }

/* --------------------------------------------------------------------------
   6. Turn indicator — iOS segmented control
   -------------------------------------------------------------------------- */
.turn { text-align: center; }

.turn__caption {
  margin: 0 0 0.5rem;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-secondary-text);
}

.turn__hint {
  margin: 0.625rem 0 0;
  font-size: var(--text-callout);
  color: var(--color-tertiary-text);
  min-height: 1.2em;
}

.segmented-control {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  padding: 2px;
  border-radius: 10px;
  background-color: var(--color-fill-secondary);
  max-width: 320px;
  margin: 0 auto;
}

.segmented-control--compact { max-width: 220px; margin: 0; }

/* The sliding "thumb" behind the selected segment. */
.segmented-control__thumb {
  position: absolute;
  top: 2px; bottom: 2px;
  border-radius: 8px;
  background-color: var(--color-surface);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.12), 0 1px 1px rgba(0, 0, 0, 0.06);
  transition: transform var(--duration-base) var(--spring),
              width var(--duration-base) var(--spring);
  z-index: 0;
}

.segmented-control__item {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-height: 36px;
  padding: 0.375rem 0.75rem;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font-size: var(--text-callout);
  font-weight: 500;
  color: var(--color-label);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out);
}

.segmented-control__item:not(.is-selected) { color: var(--color-tertiary-text); }
.segmented-control__item.is-selected { font-weight: 600; }

.segmented-control__item--interactive:active { opacity: 0.6; }

.segmented-control__label { white-space: nowrap; }

/* --------------------------------------------------------------------------
   7. Scoreboard
   -------------------------------------------------------------------------- */
.scores {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}

.score-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
  padding: 0.75rem;
  border-radius: var(--radius-card);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-card);
  transition: transform var(--duration-base) var(--spring),
              box-shadow var(--duration-base) var(--ease-out);
}

.score-card__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  background-color: var(--color-x-tint);
}

.score-card__badge svg { width: 16px; height: 16px; }
.score-card--o .score-card__badge { background-color: var(--color-o-tint); }
.score-card__badge--draws { background-color: var(--color-draw-tint); }

.score-card__meta { display: flex; flex-direction: column; }
.score-card__label { font-size: var(--text-caption); color: var(--color-tertiary-text); }

.score-card__value {
  font-size: var(--text-title3);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.score-card__unit {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-secondary-text);
}

/* Winning player is highlighted with colour *and* a label change ("winner"),
   so the state never depends on colour alone. */
.score-card.is-winner { transform: translateY(-2px) scale(1.02); }
.score-card.is-winner .score-card__unit { color: var(--color-primary); }
.score-card--o.is-winner .score-card__unit { color: var(--color-success); }

/* Bump animation played when a score changes. */
@keyframes score-bump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.28); }
  100% { transform: scale(1); }
}
.score-card__value.is-bumped { animation: score-bump 420ms var(--spring); }

/* --------------------------------------------------------------------------
   8. Board
   -------------------------------------------------------------------------- */
.board-wrap { display: flex; flex-direction: column; align-items: center; gap: 0.625rem; }

.board {
  position: relative;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 1 / 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 6px;
  padding: 6px;
  border-radius: calc(var(--radius-cell) + 6px);
  background-color: var(--color-separator-opaque); /* shows through the gaps as hairlines */
  box-shadow: var(--shadow-card);
}

.cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;                  /* Apple Human Interface minimum touch target */
  min-height: 44px;
  border: 0;
  border-radius: var(--radius-cell);
  background-color: var(--color-surface);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--spring);
}

.cell:hover:not(:disabled) { background-color: var(--color-fill-tertiary); }
.cell:hover:not(:disabled) { background-color: color-mix(in srgb, var(--color-primary) 6%, var(--color-surface)); }
.cell:active:not(:disabled) { transform: scale(0.96); background-color: var(--color-fill-tertiary); }

.cell:disabled { cursor: default; }

/* A filled square loses its hover affordance. */
.cell.is-filled { cursor: default; }
.cell.is-filled:hover { background-color: var(--color-surface); }

/* Winning squares get a tinted background plus a scale pulse. The tint
   follows the winner's colour, never relying on the line alone. */
.cell.is-winning {
  background-color: var(--color-o-tint);              /* fallback */
  background-color: color-mix(in srgb, var(--color-success) 16%, var(--color-surface));
  animation: cell-win 520ms var(--spring);
}

.board[data-winner="X"] .cell.is-winning {
  background-color: var(--color-x-tint);              /* fallback */
  background-color: color-mix(in srgb, var(--color-primary) 16%, var(--color-surface));
}

@keyframes cell-win {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.07); }
  100% { transform: scale(1); }
}

/* Shake played on an invalid tap (square already taken). */
@keyframes cell-shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-5px); }
  50%      { transform: translateX(5px); }
  75%      { transform: translateX(-3px); }
}
.cell.is-shaking { animation: cell-shake 320ms var(--ease-out); }

.board__hint {
  margin: 0;
  font-size: var(--text-footnote);
  color: var(--color-secondary-text);
}

/* --------------------------------------------------------------------------
   9. X and O marks — drawn as SVG strokes so they match the icon language
      (round caps, even weight) and can animate themselves into place.
   -------------------------------------------------------------------------- */
.mark { display: block; }
.mark--xs { width: 16px; height: 16px; }

.cell .mark { width: 56%; height: 56%; }

.mark__stroke {
  fill: none;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.mark__stroke--x { stroke: var(--color-primary); }
.mark__stroke--o { stroke: var(--color-success); }
.mark__stroke--draws { stroke: var(--color-secondary-text); stroke-width: 2.2; }

/* Draw-on animation: the stroke is revealed by animating stroke-dashoffset. */
@keyframes mark-draw {
  from { stroke-dashoffset: var(--mark-length); }
  to   { stroke-dashoffset: 0; }
}

@keyframes mark-pop {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

.cell .mark {
  stroke-dasharray: var(--mark-length);
  stroke-dashoffset: var(--mark-length);
  animation: mark-pop var(--duration-slow) var(--spring) both,
             mark-draw var(--duration-slow) var(--ease-out) both;
  transform-origin: center;
}

/* Winning line overlay */
.win-line {
  position: absolute;
  pointer-events: none;
  overflow: visible;
}

.win-line path {
  fill: none;
  stroke: var(--color-success);   /* default: player O */
  stroke-width: 6;
  stroke-linecap: round;
  opacity: 0.95;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.18));
}

@keyframes win-line-draw {
  from { stroke-dashoffset: var(--line-length); }
  to   { stroke-dashoffset: 0; }
}

.win-line.is-visible path {
  stroke-dasharray: var(--line-length);
  animation: win-line-draw 460ms var(--ease-out) forwards;
}

/* The line takes the winner's colour as well. */
.board[data-winner="X"] .win-line path { stroke: var(--color-primary); }

/* --------------------------------------------------------------------------
   10. Settings — iOS grouped list
   -------------------------------------------------------------------------- */
.settings__group {
  border-radius: var(--radius-card);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.settings__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: 48px;
  padding: 0.625rem 1rem;
  /* Hairline inset separator, exactly like a UITableView. */
  border-bottom: var(--hairline) solid var(--color-separator);
}

.settings__row:last-child { border-bottom: 0; }

.settings__label {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--text-body);
  color: var(--color-label);
}

.settings__icon svg { display: block; width: 20px; height: 20px; color: var(--color-secondary-text); }

.settings__footnote {
  margin: 0.5rem 0.25rem 0;
  font-size: var(--text-footnote);
  line-height: 1.4;
  color: var(--color-secondary-text);
}

/* --------------------------------------------------------------------------
   11. iOS switch — pure CSS
   -------------------------------------------------------------------------- */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 51px;
  min-height: 44px;                 /* hit area is 44pt even though the track is 31pt */
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.switch__track {
  position: relative;
  width: 51px;
  height: 31px;
  border-radius: 999px;
  background-color: var(--color-fill-secondary);
  transition: background-color var(--duration-base) var(--ease-out);
}

.switch__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background-color: #FFFFFF;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.16);
  transition: transform var(--duration-base) var(--spring),
              width var(--duration-fast) var(--ease-out);
}

.switch[aria-checked="true"] .switch__track { background-color: var(--color-success); }
.switch[aria-checked="true"] .switch__thumb { transform: translateX(20px); }

/* iOS stretches the thumb while the control is being pressed. */
.switch:active .switch__thumb { width: 31px; }
.switch[aria-checked="true"]:active .switch__thumb { transform: translateX(16px); }

/* --------------------------------------------------------------------------
   12. Buttons
   -------------------------------------------------------------------------- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.75rem 1.25rem;
  border: 0;
  border-radius: var(--radius-control);
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: -0.011em;
  cursor: pointer;
  transition: transform var(--duration-fast) var(--spring),
              background-color var(--duration-fast) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out);
}

.button__icon svg { display: block; width: 20px; height: 20px; }
.button--small { min-height: 32px; padding: 0.375rem 0.875rem; font-size: var(--text-callout); }
.button--primary { background-color: var(--color-primary); color: var(--color-on-accent); }
.button--primary:hover { opacity: 0.88; }
.button--primary:hover { background-color: color-mix(in srgb, var(--color-primary) 88%, #000); opacity: 1; }
.button--destructive { background-color: var(--color-fill-secondary); color: var(--color-destructive); }
.button--destructive { background-color: color-mix(in srgb, var(--color-destructive) 12%, transparent); color: var(--color-destructive); }
.button--destructive:hover { background-color: var(--color-fill-secondary); }
.button--destructive:hover { background-color: color-mix(in srgb, var(--color-destructive) 20%, transparent); }
.button:active { transform: scale(0.96); opacity: 0.85; }

.action-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 15;
  display: flex;
  justify-content: center;
  padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
  background-color: var(--color-elevated);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  box-shadow: var(--shadow-float);
}

.action-bar .button { width: 100%; max-width: 520px; }

/* --------------------------------------------------------------------------
   13. Alert — iOS UIAlertController
   -------------------------------------------------------------------------- */
.alert-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  /* The page behind the alert is blurred and dimmed, not just darkened. */
  background-color: rgba(0, 0, 0, 0.28);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  animation: fade-in var(--duration-base) var(--ease-out) both;
}

.alert {
  width: 100%;
  max-width: 280px;
  border-radius: var(--radius-alert);
  background-color: var(--color-surface);             /* fallback */
  background-color: color-mix(in srgb, var(--color-surface) 92%, transparent);
  box-shadow: var(--shadow-alert);
  overflow: hidden;
  text-align: center;
  animation: alert-in var(--duration-slow) var(--spring) both;
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes alert-in {
  from { opacity: 0; transform: scale(0.86); }
  to   { opacity: 1; transform: scale(1); }
}

.alert__title {
  margin: 0;
  padding: 1.125rem 1rem 0.25rem;
  font-size: var(--text-headline);
  font-weight: 600;
}

.alert__message {
  margin: 0;
  padding: 0 1rem 1.125rem;
  font-size: var(--text-callout);
  line-height: 1.4;
  color: var(--color-tertiary-text);
}

.alert__actions { border-top: var(--hairline) solid var(--color-separator); }

.alert__action {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 0.75rem 1rem;
  border: 0;
  border-bottom: var(--hairline) solid var(--color-separator);
  background: transparent;
  font-size: var(--text-body);
  font-weight: 400;
  color: var(--color-primary);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}

.alert__action:last-child { border-bottom: 0; }
.alert__action:hover { background-color: var(--color-fill-tertiary); }
.alert__action--bold { font-weight: 600; }
.alert__action--destructive { color: var(--color-destructive); }

/* --------------------------------------------------------------------------
   14. Sheet — slides up from the bottom
   -------------------------------------------------------------------------- */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 45;
  display: flex;
  align-items: flex-end;
  background-color: rgba(0, 0, 0, 0.3);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: fade-in var(--duration-base) var(--ease-out) both;
}

.sheet {
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  max-height: 86dvh;
  overflow-y: auto;
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  background-color: var(--color-surface);
  box-shadow: var(--shadow-alert);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  animation: sheet-up var(--duration-slow) var(--spring) both;
}

@keyframes sheet-up {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

/* Closing plays the reverse animation before the element is hidden. */
.sheet-backdrop.is-closing { animation: fade-in var(--duration-base) var(--ease-out) reverse both; }
.sheet-backdrop.is-closing .sheet { animation: sheet-up var(--duration-base) var(--ease-out) reverse both; }

.sheet__handle {
  display: block;
  width: 36px;
  height: 5px;
  margin: 0.5rem auto 0;
  border-radius: 999px;
  background-color: var(--color-fill-secondary);
}

.sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  border-bottom: var(--hairline) solid var(--color-separator);
}

.sheet__title {
  margin: 0;
  font-size: var(--text-headline);
  font-weight: 600;
}

.sheet__body { padding: 1.25rem 1.25rem 1.5rem; text-align: center; }

.app-badge {
  width: 64px;
  height: 64px;
  margin: 0 auto 0.75rem;
  border-radius: 15px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 122, 255, 0.28);
}
.app-badge svg { display: block; width: 100%; height: 100%; }

.sheet__app-name { margin: 0; font-size: var(--text-title3); font-weight: 700; }
.sheet__version { margin: 0.125rem 0 0.75rem; font-size: var(--text-footnote); color: var(--color-secondary-text); }
.sheet__text { margin: 0; font-size: var(--text-callout); line-height: 1.5; color: var(--color-tertiary-text); }

.sheet__links {
  display: flex;
  justify-content: center;
  gap: 1.25rem;
  margin-top: 1.25rem;
}

.sheet__link {
  font-size: var(--text-callout);
  font-weight: 500;
  color: var(--color-primary);
  text-decoration: none;
}
.sheet__link:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   15. Responsive adjustments (mobile-first)
   -------------------------------------------------------------------------- */
@media (max-width: 380px) {
  .segmented-control__label { display: none; }   /* keep the turn indicator compact */
  .score-card__unit { display: none; }
  .scores { gap: 0.375rem; }
}

@media (min-width: 768px) {
  .app { padding-top: 2rem; gap: 1.5rem; }
  .board { max-width: 400px; }
  .action-bar { position: static; box-shadow: none; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; padding: 0; }
  .app { padding-bottom: 2.5rem; }
  .action-bar .button { max-width: 280px; }
}
