﻿:root {
  color-scheme: light dark;
  /* sky / page background */
  --sky-1: #8fd8d2;  --sky-2: #f7e8c9;  --sky-mid: #c3e0d6;
  /* surfaces */
  --surface: #fdf8ec;          /* dock, cards */
  --surface-raised: #ffffff;   /* chips, inputs */
  --sign-face: #2b3a3a;        /* dark sign boards (market, menus) */
  --sign-post: #d94f2b;        /* market post / primary sign color */
  /* ink */
  --ink: #2b3a3a;  --ink-muted: rgba(43, 58, 58, 0.72);   /* >=4.5:1 on --surface (AA) */
  --ink-on-dark: #fff8ea;      /* text on sign-face */
  /* board */
  --cell: #cfe7e2;  --cell-border: #9fc9c1;   /* pool-water cells */
  --board-frame: rgba(255, 255, 255, 0.42);
  --drag-ghost-veil: rgba(255, 255, 255, 0.42);   /* must stay translucent: a covered tile shows through it */
  /* the one tile */
  --tile-face: #fdf6e3;  --tile-ink: #2b3a3a;  --tile-points: #b8532a;
  --tile-top-sheen: rgba(255, 255, 255, 0.75);
  --tile-bottom-shade: rgba(43, 58, 58, 0.14);
  --tile-wildcard-ring: rgba(255, 255, 255, 0.58);
  --tile-wildcard-dash: rgba(35, 49, 58, 0.42);
  --on-accent-ink: #ffffff;
  /* accents */
  --coral: #d94f2b;   --coral-deep: #9c3517;
  --orange: #f0783c;  --orange-deep: #b8532a;   /* active placement */
  --teal: #3aa6a0;    --teal-deep: #237873;  --teal-soft: #5fc0b8;
  --gold: #ffd97a;    --gold-deep: #e0a32f;
  --pink-neon: #ff9ecb;  --cyan-neon: #58ead9;  /* mostly night; day fallback ok */
  --red-neon: #ff425f;   /* night electric red, parallels --cyan-neon */
  --red-glow: rgba(255, 66, 95, 0.6);   /* red neon glow (glow-strength gated) */
  --ring-dark: #3f2611;  /* Saturn ring's dark gaps — darker than the gold planet */
  /* "hot" accent: now-playing badge bg + username + negative/spent score.
     Day = the coral MARKET post (--sign-post); night = electric red. */
  --hot-accent: var(--sign-post);
  /* effects */
  --glow-strength: 0;          /* 0 by day; night mode turns glows on */
  --shadow-soft: rgba(43, 58, 58, 0.25);
  --orange-glow: rgba(240, 120, 60, 0.55);   /* active-placement ring glow */
  --tile-glow: rgba(242, 230, 216, 0.3);     /* night tile glow (day: inert, no drop shadow swap) */
  --teal-glow: rgba(58, 166, 160, 0.5);      /* night letter-bonus cell glow */
  --gold-glow: rgba(255, 217, 122, 0.5);     /* night word-bonus/start cell glow */
  --coral-glow: rgba(217, 79, 43, 0.55);     /* night triple-word cell glow */
  --gold-wash: rgba(255, 217, 122, 0.35);    /* always-on gold tint (rank #1 / winner highlight gradients), not glow-gated */
  --sheen-soft: rgba(255, 255, 255, 0.3);    /* generic light inset sheen (sign posts/boards) */
  --shade-soft: rgba(43, 58, 58, 0.35);      /* generic dark text/inset shadow */
  --rainbow-1: #d94f2b;  --rainbow-2: #ffd97a;  --rainbow-3: #3aa6a0;
  --rainbow-4: #6a8fd8;  --rainbow-5: #c96a9e;
  --brand-facebook: #1877f2;   /* brand-locked, identical in both themes */
  --play-width: min(72vh, 90vw, 560px);
  /* rules highway */
  --road-asphalt: rgba(43, 58, 58, 0.16);      /* day: soft asphalt tint from --sign-face */
  --road-centerline: var(--gold);
  --road-centerline-glow: rgba(255, 217, 122, 0);  /* day: no glow */
  --sign-wood: #a9612f;   --sign-wood-deep: #7a4420;   /* signpost timber */
}
html[data-theme="dark"] { /* night overrides */
  --sky-1: #0b1026; --sky-2: #3d1f2e;  --sky-mid: #1c1230;
  --surface: #120c22; --surface-raised: #17102b;
  --sign-face: #10091d; --sign-post: #2a0f14;
  --ink: #f2e6d8; --ink-muted: rgba(242, 230, 216, 0.6); --ink-on-dark: #f2e6d8;
  --cell: #171230; --cell-border: #2c2450;
  --board-frame: #1b1c33;   /* solid: the gaps between cells hide Saturn behind the board */
  --drag-ghost-veil: rgba(27, 28, 51, 0.55);   /* NOT --board-frame: that is opaque at night and would mask the covered tile */
  --tile-face: #f2e6d8;                        /* tiles STAY cream at night */
  --tile-wildcard-ring: rgba(255, 255, 255, 0.58);
  --tile-wildcard-dash: rgba(35, 49, 58, 0.42);
  --on-accent-ink: #ffffff;
  --glow-strength: 1;
  --hot-accent: var(--red-neon);   /* night: electric red for now-playing/username/negative */
  --red-glow: rgba(255, 66, 95, 0.75);
  --shadow-soft: rgba(0, 0, 0, 0.5);
  --orange-glow: rgba(240, 120, 60, 0.65);
  --tile-glow: rgba(242, 230, 216, 0.32);
  --teal-glow: rgba(88, 234, 217, 0.5);
  --gold-glow: rgba(255, 217, 122, 0.55);
  --coral-glow: rgba(255, 92, 138, 0.55);
  --gold-wash: rgba(255, 217, 122, 0.16);
  --sheen-soft: rgba(255, 255, 255, 0.1);
  --shade-soft: rgba(0, 0, 0, 0.45);
  --rainbow-1: #d94f2b;  --rainbow-2: #ffd97a;  --rainbow-3: #3aa6a0;
  --rainbow-4: #6a8fd8;  --rainbow-5: #c96a9e;
  --brand-facebook: #1877f2;
  --teal-soft: #5fc0b8;
  /* rules highway: night */
  --road-asphalt: rgba(0, 0, 0, 0.45);           /* darker night asphalt */
  --road-centerline: var(--gold);
  --road-centerline-glow: rgba(255, 217, 122, 0.55);  /* faint centerline glow at night */
  --sign-wood: #7d4d2a;   --sign-wood-deep: #4a2c16;   /* lighter at night so posts read against the dark sky */
}

/* Night pass: tile / board (structural — cream glow replaces drop shadow, bonus/start cells gain glow borders) */
html[data-theme="dark"] .tile {
  box-shadow:
    inset 0 2px 0 var(--tile-top-sheen),
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    0 0 calc(9px * var(--glow-strength)) var(--tile-glow);
}

html[data-theme="dark"] .tile-wildcard {
  box-shadow:
    inset 0 0 0 0.18rem var(--tile-wildcard-ring),
    inset 0 2px 0 var(--tile-top-sheen),
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    0 0 calc(9px * var(--glow-strength)) var(--tile-glow);
}

html[data-theme="dark"] .board .tile,
html[data-theme="dark"] .rules-example .tile,
html[data-theme="dark"] .rules-board-example .tile {
  box-shadow:
    inset 0 2px 0 var(--tile-top-sheen),
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    0 0 calc(7px * var(--glow-strength)) var(--tile-glow);
}

html[data-theme="dark"] .board-cell-bonus-doubleLetter,
html[data-theme="dark"] .board-cell-bonus-tripleLetter {
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--teal-glow);
}

html[data-theme="dark"] .board-cell-bonus-doubleWord,
html[data-theme="dark"] .board-cell-start {
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--gold-glow);
}

html[data-theme="dark"] .board-cell-bonus-tripleWord {
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--coral-glow);
}

* {
  box-sizing: border-box;
}

html {
  scrollbar-gutter: stable;
}

body {
  position: relative;
  min-height: 100vh;
  margin: 0;
  overflow-x: hidden;
  overflow-y: auto;
  background: linear-gradient(180deg, var(--sky-1), var(--sky-mid), var(--sky-2));
  color: var(--ink);
  font-family: system-ui, sans-serif;
  display: flex;
  flex-direction: column;
}

/* Scenery: faint gutter ornaments on the page background, day = starbursts +
   dot planets, night = star field + ringed Saturn. Gutter-positioned (<=15% /
   >=85%) so they never sit under the centered content column; decorative only. */
body::before,
body::after {
  content: "";
  position: fixed;
  z-index: -2; /* star field sits behind the Saturn div (z-index: -1) */
  pointer-events: none;
  opacity: 0.5;
}

body::before {
  inset: 0 auto auto 0;
  width: 40vw;
  height: 60vh;
  background:
    radial-gradient(circle at 8% 12%, var(--gold) 0 3px, transparent 4px),
    radial-gradient(circle at 4% 30%, var(--coral) 0 2px, transparent 3px),
    conic-gradient(from 0deg at 10% 20%, transparent 0deg 80deg, var(--gold) 82deg 84deg, transparent 86deg 170deg, var(--gold) 172deg 174deg, transparent 176deg 260deg, var(--gold) 262deg 264deg, transparent 266deg 350deg, var(--gold) 352deg 354deg, transparent 356deg 360deg);
  mask-image: radial-gradient(circle at 10% 20%, black 0 3rem, transparent 6rem);
}

body::after {
  inset: 0 0 auto auto;
  width: 40vw;
  height: 60vh;
  background:
    radial-gradient(circle at 92% 18%, var(--teal) 0 2px, transparent 3px),
    radial-gradient(circle at 88% 8%, var(--coral) 0 3px, transparent 4px),
    conic-gradient(from 0deg at 90% 14%, transparent 0deg 80deg, var(--teal) 82deg 84deg, transparent 86deg 170deg, var(--teal) 172deg 174deg, transparent 176deg 260deg, var(--teal) 262deg 264deg, transparent 266deg 350deg, var(--teal) 352deg 354deg, transparent 356deg 360deg);
  mask-image: radial-gradient(circle at 90% 14%, black 0 2.4rem, transparent 5rem);
}

html[data-theme="dark"] body::before {
  background:
    radial-gradient(circle at 6% 10%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 12% 22%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 4% 38%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 9% 48%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 3% 60%, var(--ink-on-dark) 0 1px, transparent 2px);
  mask-image: none;
}

/* Night right-gutter star field (Saturn itself is the .saturn div below). */
html[data-theme="dark"] body::after {
  background:
    radial-gradient(circle at 93% 44%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 84% 56%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 96% 66%, var(--ink-on-dark) 0 1px, transparent 2px),
    radial-gradient(circle at 88% 78%, var(--ink-on-dark) 0 1px, transparent 2px);
  mask-image: none;
}

/* Ringed Saturn — a real element (night only), fixed in the top-right, fully
   below the top edge. The opaque planet is painted AFTER the ring so the ring
   passes BEHIND it: only the tilted ring tips show either side. */
.saturn {
  display: none;
}

html[data-theme="dark"] .saturn {
  display: block;
  position: fixed;
  top: 2.25rem;
  right: -2rem;
  width: 14rem;
  height: 11rem;
  z-index: -1;
  pointer-events: none;
  opacity: 0.6;
}

.saturn-ring,
.saturn-planet {
  position: absolute;
  top: 50%;
  left: 50%;
}

.saturn-ring {
  width: 14rem;
  height: 4.6rem;
  transform: translate(-50%, -50%) rotate(-18deg);
  /* multi-band ring: light bands + dark Cassini-style gaps (--ring-dark) */
  background: radial-gradient(ellipse closest-side at 50% 50%,
    transparent 0 55%,
    var(--gold) 58% 63%,
    var(--ring-dark) 65% 68%,
    var(--gold-deep) 70% 82%,
    var(--ring-dark) 84% 86%,
    var(--gold) 88% 96%,
    transparent 99%);
}

/* Ring-back sits behind the planet (DOM order); the planet occludes its far
   half. Ring-front is the same ellipse clipped to only its near (bottom) arc
   and painted after the planet, so it crosses IN FRONT of the planet — the
   two together give a real Saturn instead of "ears". */
.saturn-ring-front {
  clip-path: inset(50% 0 0 0);
}

.saturn-planet {
  width: 9rem;
  height: 9rem;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, var(--tile-face), var(--gold) 45%, var(--gold-deep) 90%);
}

/* Scale the whole planet+ring up on larger screens, anchored to the corner. */
@media (min-width: 1024px) {
  html[data-theme="dark"] .saturn {
    transform: scale(1.45);
    transform-origin: 100% 0;
  }
}

.font-script {
  font-family: "Pacifico", "Brush Script MT", cursive;
}

.font-display {
  font-family: "Righteous", "Trebuchet MS", sans-serif;
}

main {
  min-height: calc(100vh - 3.4rem);
  width: min(100vw, 1080px);
  margin: 0 auto;
  padding: clamp(2rem, 7vw, 5rem) clamp(0.5rem, 2vw, 1.25rem);
  display: grid;
  place-items: center;
  gap: 1.25rem;
  text-align: center;
  flex: 1 0 auto;
}

.site-footer {
  width: min(100vw, 1080px);
  margin: 0 auto;
  padding: 0.7rem clamp(0.5rem, 2vw, 1.25rem) 1rem;
  color: var(--ink-muted);
  text-align: center;
  font: 700 0.78rem/1.35 system-ui, sans-serif;
  flex: 0 0 auto;
}

.site-footer-links {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  margin-right: 0.55rem;
}

.site-footer a {
  color: var(--coral);
  font-weight: 900;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.15rem;
}

.site-footer-copy {
  white-space: nowrap;
}

.masthead {
  display: grid;
  width: 100%;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  justify-items: stretch;
  gap: 1rem 1.25rem;
  transition: transform 220ms ease, padding 220ms ease;
}

/* Brand road-sign wordmark rules live in public/brand.css (shared with
   privacy.html + terms.html). App-only masthead placement stays below. */

.game-controls {
  display: grid;
  justify-self: end;
  justify-items: end;
  gap: 0.75rem;
}

.identity-panel,
.identity-bar,
.identity-menu {
  display: none;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
}

.identity-panel {
  position: relative;
  grid-column: 1 / -1;
  gap: 0.95rem;
  justify-items: center;
  margin-top: 0.9rem;
  padding: 1.6rem 1.1rem 1.1rem;
  border: 2px solid var(--cell-border);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 0.4rem 0 var(--shadow-soft), 0 0 calc(16px * var(--glow-strength)) var(--pink-neon);
}

.identity-panel::before {
  content: "VACANCY";
  position: absolute;
  top: -0.85rem;
  left: 50%;
  transform: translateX(-50%) rotate(-2deg);
  padding: 0.3rem 0.85rem;
  border-radius: 999px;
  background: var(--gold);
  color: var(--sign-face);
  font: 800 0.68rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  box-shadow: 0.12rem 0.12rem 0 var(--gold-deep), 0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
}

.identity-bar {
  position: relative;
  align-items: center;
  flex-wrap: nowrap;
  color: var(--ink);
  font: 700 0.92rem/1.25 system-ui, sans-serif;
}

.identity-current {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.identity-current .ww-icon {
  color: var(--hot-accent);
  flex: 0 0 auto;
  width: 1.55em;
  height: 1.55em;
  /* flat by day (matches the MARKET board), electric-red glow by night */
  filter: drop-shadow(0 0 calc(7px * var(--glow-strength)) var(--red-glow));
}

.identity-name {
  color: var(--hot-accent);
  /* Flat fill so it reads as the same solid color as the MARKET board by day
     (no crisp white offset); night adds only the electric-red neon glow. */
  font-family: "Pacifico", "Brush Script MT", cursive;
  font-weight: 400;
  font-size: 1.2em;
  line-height: 1.1;
  -webkit-text-stroke: 0.6px currentColor;
  text-shadow: 0 0 calc(14px * var(--glow-strength)) var(--red-glow);
  overflow-wrap: anywhere;
  cursor: help;
}

.identity-name:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 3px;
  border-radius: 4px;
}

html[data-theme="dark"] .identity-name:focus-visible {
  outline-color: var(--gold);
}

.identity-provider {
  display: none;
  color: var(--ink-muted);
  font: 800 0.68rem/1 system-ui, sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.identity-account-tooltip {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.45rem);
  right: 0;
  display: grid;
  gap: 0.2rem;
  width: max-content;
  max-width: min(18rem, calc(100vw - 1rem));
  padding: 0.55rem 0.65rem;
  border: 2px solid var(--ink);
  border-radius: 6px;
  background: var(--surface-raised);
  color: var(--ink);
  box-shadow: 0.14rem 0.14rem 0 var(--gold);
  text-align: left;
  font: 700 0.78rem/1.25 system-ui, sans-serif;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-0.2rem);
  transition: opacity 140ms ease, transform 140ms ease;
}

.identity-account-tooltip[hidden] {
  display: none;
}

.identity-account-tooltip::before {
  content: "";
  position: absolute;
  top: -0.45rem;
  right: 1rem;
  width: 0.7rem;
  height: 0.7rem;
  border-top: 2px solid var(--ink);
  border-left: 2px solid var(--ink);
  background: var(--surface-raised);
  transform: rotate(45deg);
}

.identity-current.tooltip-open .identity-account-tooltip,
.identity-name:hover ~ .identity-account-tooltip,
.identity-name:focus ~ .identity-account-tooltip {
  opacity: 1;
  transform: translateY(0);
}

.identity-tooltip-line {
  overflow-wrap: anywhere;
}

.identity-tooltip-label {
  color: var(--ink-muted);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.name-login-control {
  display: none;
}

html.local-name-login-allowed .name-login-control {
  display: inline-block;
}

.oauth-buttons {
  display: none;
  justify-items: stretch;
  gap: 0.55rem;
  width: min(82vw, 22rem);
}

html.oauth-login-available .oauth-buttons {
  display: grid;
}

.oauth-button {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 0.62rem;
  width: 100%;
  border-color: var(--cell-border);
}

.oauth-button:focus-visible {
  outline: none;
  border-color: var(--coral);
  box-shadow: 0.18rem 0.18rem 0 var(--cell-border), 0 0 0 3px var(--orange-glow);
}

html[data-theme="dark"] .oauth-button:focus-visible {
  border-color: var(--gold);
  box-shadow: 0.18rem 0.18rem 0 var(--cell-border), 0 0 0 3px var(--gold-glow);
}

html.oauth-google-available .oauth-button.google,
html.oauth-facebook-available .oauth-button.facebook {
  display: inline-flex;
}

.oauth-icon {
  display: inline-grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  flex: 0 0 auto;
  font: 900 1rem/1 Arial, sans-serif;
}

.oauth-button.google .oauth-icon svg {
  display: block;
  width: 1.2rem;
  height: 1.2rem;
}

.oauth-button.facebook .oauth-icon svg {
  display: block;
  width: 1.2rem;
  height: 1.2rem;
  fill: var(--brand-facebook);
}

.leaderboard-button-with-icon,
.game-list-button-with-icon,
.rules-button-with-icon,
.changelog-button-with-icon,
.create-game-button-with-icon,
.logout-button-with-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 3.1875rem;
  padding-block: 0;
}

.game-button.public-leaderboard-button {
  padding: 0.7rem 1.1rem;
  width: min(82vw, 22rem);
}

.leaderboard-crown-icon,
.game-list-crossword-icon,
.rules-guide-icon,
.changelog-history-icon,
.create-game-playlist-icon,
.logout-icon {
  color: var(--gold-deep);
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
}

.game-list-crossword-icon {
  color: var(--teal-deep);
}

.rules-guide-icon {
  color: var(--coral);
}

.changelog-history-icon {
  color: var(--teal-deep);
}

.create-game-playlist-icon {
  color: var(--coral);
}

.logout-icon {
  color: currentColor;
}

body.screen-leaderboard .public-leaderboard-button {
  display: none;
}

.menu-button {
  position: relative;
  width: 2.75rem;
  min-width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  line-height: 1;
}

.menu-notification-count {
  position: absolute;
  top: -0.35rem;
  left: -0.35rem;
  display: none;
  min-width: 1.3rem;
  height: 1.3rem;
  place-items: center;
  padding-inline: 0.28rem;
  border: 2px solid var(--on-accent-ink);
  border-radius: 999px;
  background: var(--coral-deep);
  color: var(--on-accent-ink);
  font: 900 0.72rem/1 system-ui, sans-serif;
  box-shadow: 0.08rem 0.08rem 0 var(--shadow-soft);
}

.menu-button.has-notifications .menu-notification-count {
  display: grid;
}

.game-button.menu-button {
  padding: 0;
  padding-inline: 0;
}

.ww-icon {
  width: 1.35em;
  height: 1.35em;
  flex: 0 0 auto;
  fill: currentColor;
  vertical-align: -0.24em;
  display: inline-block;
  line-height: 1;
}

.identity-menu {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 10;
  min-width: 10rem;
  padding: 0.55rem;
  border: 2px solid var(--sign-post);
  border-radius: 8px;
  background: var(--sign-face);
  color: var(--ink-on-dark);
  box-shadow: 0.25rem 0.25rem 0 var(--gold), 0 0 calc(14px * var(--glow-strength)) var(--pink-neon);
}

.identity-menu .game-button.secondary {
  border-color: var(--gold-deep);
  background: transparent;
  color: var(--ink-on-dark);
  box-shadow: none;
}

.identity-menu .game-button.secondary:hover {
  background: color-mix(in srgb, var(--gold) 12%, transparent);
}

.identity-menu .leaderboard-crown-icon,
.identity-menu .game-list-crossword-icon,
.identity-menu .rules-guide-icon,
.identity-menu .changelog-history-icon,
.identity-menu .create-game-playlist-icon,
.identity-menu .logout-icon {
  color: var(--gold);
}

body.menu-open .identity-menu {
  display: grid;
}

.identity-menu > .game-button {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.45rem;
  text-align: left;
}

.identity-menu > .game-button:not(.identity-menu-checkbox):not(.create-game-button-with-icon):not(.game-list-button-with-icon):not(.leaderboard-button-with-icon):not(.rules-button-with-icon):not(.changelog-button-with-icon):not(.logout-button-with-icon)::before {
  content: "";
  width: 1.15rem;
  height: 1.15rem;
  flex: 0 0 auto;
}

.identity-menu-checkbox {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.45rem;
  text-align: left;
  user-select: none;
}

.identity-menu-checkbox[hidden] {
  display: none;
}

.identity-menu-checkbox input {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--gold);
  flex: 0 0 auto;
}

.identity-menu-checkbox[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.58;
}

.menu-waiting-games {
  display: none;
  width: 100%;
  gap: 0.75rem;
  padding-top: 0.55rem;
  border-top: 2px solid var(--sign-post);
}

.menu-waiting-games.has-games {
  display: grid;
}

.menu-waiting-title {
  margin: 0;
  color: var(--ink-on-dark);
  opacity: 0.65;
  font: 900 0.68rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
}

.menu-waiting-game {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  min-height: 3.15rem;
  padding: 0.7rem 1.1rem;
  text-align: left;
}

.identity-menu .menu-waiting-game {
  min-height: 3.15rem;
}

.menu-waiting-game-id {
  overflow: hidden;
  color: var(--gold);
  font-weight: 900;
  text-overflow: ellipsis;
}

.menu-waiting-game-turn {
  color: var(--ink-on-dark);
  opacity: 0.65;
  font-size: 0.78rem;
  font-weight: 900;
  white-space: nowrap;
}

.player-setup {
  display: none;
  justify-items: center;
  gap: 0.65rem;
  width: 100%;
  max-width: 42rem;
}

.player-name-list {
  display: grid;
  gap: 0.45rem;
}

.invite-setup {
  display: grid;
  justify-items: stretch;
  gap: 0.65rem;
  width: min(82vw, 32rem);
  font: 700 0.9rem/1.35 system-ui, sans-serif;
  text-align: left;
}

/* Postcard panel: cream card, dashed coral border, stamp corner (matches .invite-link-panel) */
.friend-invite-panel {
  position: relative;
  display: grid;
  gap: 0.5rem;
  padding: 0.65rem;
  border: 2px dashed var(--coral);
  border-radius: 8px;
  background: var(--surface);
}

html[data-theme="dark"] .friend-invite-panel {
  border-color: var(--pink-neon);
  background: var(--surface-raised);
}

.friend-invite-panel h3 {
  margin: 0;
  color: var(--ink-muted);
  font: 400 0.85rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.friend-invite-list {
  display: grid;
  gap: 0.4rem;
}

.friend-invite-empty,
.invite-copy,
.invite-link-copy {
  margin: 0;
  color: var(--ink-muted);
  font: 700 0.86rem/1.35 system-ui, sans-serif;
}

.friend-invite-option {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  padding: 0.48rem 0.65rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface-raised);
}

.friend-invite-option input {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--coral);
}

.friend-invite-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-weight: 900;
}

.friend-invite-recency {
  color: var(--ink-muted);
  font-size: 0.78rem;
  font-weight: 800;
  white-space: nowrap;
}

/* Invite panel: postcard styling with a coral dashed border + stamp corner */
.invite-link-panel {
  display: none;
  position: relative;
  justify-items: center;
  gap: 0.42rem;
  width: min(82vw, 32rem);
  padding: 0.65rem;
  border: 2px dashed var(--coral);
  border-radius: 8px;
  background: var(--surface);
  font: 700 0.9rem/1.35 system-ui, sans-serif;
}

.invite-link-panel::after {
  content: "\2709";
  position: absolute;
  top: -0.55rem;
  right: 0.65rem;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border: 1px solid var(--gold-deep);
  border-radius: 3px;
  background: var(--gold);
  color: var(--ink);
  font-size: 0.85rem;
  transform: rotate(6deg);
  pointer-events: none;
}

html[data-theme="dark"] .invite-link-panel {
  border-color: var(--pink-neon);
  background: var(--surface-raised);
}

html[data-theme="dark"] .invite-link-panel::after {
  border-color: var(--cyan-neon);
  background: var(--sign-face);
  color: var(--cyan-neon);
}

body.screen-play .invite-link-panel {
  display: grid;
}

body.screen-play .invite-link-panel[hidden],
.invite-link-panel[hidden] {
  display: none;
}

.invite-link-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.invite-link-value {
  max-width: 100%;
  overflow-wrap: anywhere;
  color: var(--coral);
  font: 800 0.82rem/1.35 system-ui, sans-serif;
}

html[data-theme="dark"] .invite-link-value {
  color: var(--cyan-neon);
}

.player-name-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.45rem;
  padding: 0.3rem;
  border: 2px dashed var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
}

html[data-theme="dark"] .player-name-row {
  border-color: var(--cell-border);
  background: var(--surface-raised);
}

.player-name-row.locked .player-name-input {
  grid-column: 1 / -1;
}

.game-length-control {
  display: grid;
  gap: 0.5rem;
  justify-items: center;
  font: 800 0.86rem/1 system-ui, sans-serif;
}

.game-length-control legend {
  color: var(--ink-muted);
  font: 400 0.78rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.game-length-options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.55rem;
}

/* Billboard card: cream face, coral border + lift when its radio is checked */
.game-length-option {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.75rem;
  padding: 0.5rem 0.85rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0.14rem 0.14rem 0 var(--shadow-soft);
  cursor: pointer;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

.game-length-option:has(input:checked) {
  border-color: var(--coral);
  background: var(--surface-raised);
  box-shadow: 0.18rem 0.18rem 0 var(--coral-deep);
  transform: translateY(-0.08rem);
}

html[data-theme="dark"] .game-length-option:has(input:checked) {
  border-color: var(--gold);
  box-shadow:
    0.18rem 0.18rem 0 var(--coral-deep),
    0 0 calc(12px * var(--glow-strength)) var(--gold-glow);
}

.game-length-option input:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

html[data-theme="dark"] .game-length-option input:focus-visible {
  outline-color: var(--gold);
}

.game-length-copy {
  display: grid;
  gap: 0.12rem;
}

.game-length-name {
  color: var(--ink);
  font: 400 1rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.02em;
}

.game-length-pool {
  color: var(--ink-muted);
  font: 800 0.68rem/1 system-ui, sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.player-name-input {
  min-height: 2.75rem;
  width: min(82vw, 22rem);
  border: 2px solid var(--cell-border);
  border-radius: 999px;
  padding: 0.65rem 1.05rem;
  background: var(--surface-raised);
  color: var(--ink);
  font: 700 1rem/1 system-ui, sans-serif;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}

.player-name-input:focus-visible {
  outline: none;
  border-color: var(--coral);
  box-shadow: 0 0 0 3px var(--orange-glow);
}

html[data-theme="dark"] .player-name-input:focus-visible {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-glow);
}

.player-name-remove {
  min-width: 2.75rem;
  padding-inline: 0.75rem;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  clip-path: inset(50%);
}

.game-button {
  min-height: 2.75rem;
  border: 2px solid var(--ink);
  border-radius: 999px;
  padding: 0.7rem 1.1rem;
  background: var(--coral);
  color: var(--on-accent-ink);
  cursor: pointer;
  font: 700 1rem/1 system-ui, sans-serif;
  box-shadow: 0.18rem 0.18rem 0 var(--coral-deep);
}

.game-button.secondary {
  background: var(--surface-raised);
  color: var(--ink);
  box-shadow: 0.18rem 0.18rem 0 var(--cell-border);
}

.game-button:hover {
  background: var(--orange);
}

.game-button.secondary:hover {
  background: var(--surface);
}

.game-button:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

html[data-theme="dark"] .game-button:focus-visible {
  outline-color: var(--gold);
}

.oauth-button.game-button.secondary,
.public-leaderboard-button.game-button.secondary,
.identity-menu > .game-button.secondary,
.active-games-actions > .game-button.secondary {
  min-height: 3.1875rem;
}

.active-games {
  grid-column: 1 / -1;
  clear: both;
  justify-self: center;
  width: 100%;
  max-width: 42rem;
  display: none;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  gap: 0.65rem;
  justify-items: stretch;
  font: 700 0.95rem/1.35 system-ui, sans-serif;
}

.leaderboard-page {
  grid-column: 1 / -1;
  clear: both;
  justify-self: center;
  width: var(--play-width);
  max-width: var(--play-width);
  display: none;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  gap: 0.65rem;
  justify-items: stretch;
  font: 700 0.95rem/1.35 system-ui, sans-serif;
}

.leaderboard-title,
.game-list-title,
.rules-title,
.changelog-title,
.spectator-title,
.new-game-title {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.leaderboard-title .leaderboard-crown-icon,
.game-list-title .game-list-crossword-icon,
.rules-title .rules-guide-icon,
.changelog-title .changelog-history-icon,
.spectator-title .spectator-eyeglasses-icon,
.new-game-title .create-game-playlist-icon {
  width: 1.8rem;
  height: 1.8rem;
}

.display-name-page {
  grid-column: 1 / -1;
  clear: both;
  justify-self: center;
  width: min(92vw, 32rem);
  display: none;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  justify-items: stretch;
  gap: 1rem;
  padding: clamp(1rem, 3vw, 1.35rem);
  border: 2px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface-raised) 72%, transparent);
  box-shadow: 0.18rem 0.18rem 0 color-mix(in srgb, var(--teal) 18%, transparent);
  font: 700 0.95rem/1.35 system-ui, sans-serif;
}

.display-name-copy {
  margin: 0;
  color: var(--ink-muted);
  font: 700 0.98rem/1.35 system-ui, sans-serif;
  text-align: center;
}

.display-name-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
}

.display-name-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem;
  justify-content: flex-end;
}

@media (max-width: 520px) {
  .display-name-form {
    grid-template-columns: 1fr;
  }
}

.section-title {
  position: relative;
  margin: 0;
  color: var(--ink);
  font: 400 clamp(1.35rem, 4vw, 2rem)/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.02em;
  text-align: center;
}

.active-games-list {
  display: grid;
  gap: 0.8rem;
}

.leaderboard-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.55rem;
}

.leaderboard-summary-item,
.leaderboard-highlight-item {
  display: grid;
  min-width: 0;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0.12rem 0.12rem 0 var(--shadow-soft);
}

.leaderboard-summary-item {
  gap: 0.22rem;
  padding: 0.6rem 0.65rem;
}

.leaderboard-summary-value,
.leaderboard-highlight-value {
  min-width: 0;
  overflow: hidden;
  color: var(--coral);
  font: 950 1.02rem/1.08 system-ui, sans-serif;
  text-overflow: ellipsis;
  white-space: nowrap;
}

html[data-theme="dark"] .leaderboard-summary-value,
html[data-theme="dark"] .leaderboard-highlight-value {
  color: var(--gold);
}

.leaderboard-summary-label,
.leaderboard-highlight-label {
  color: var(--ink-muted);
  font: 950 0.62rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.leaderboard-highlights {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.8rem, 1fr));
  gap: 0.5rem;
  min-width: 0;
}

.leaderboard-highlight-item {
  display: grid;
  grid-template-rows: auto minmax(1.45rem, auto) auto auto;
  gap: 0.22rem;
  padding: 0.6rem 0.65rem;
}

.leaderboard-highlights a,
.leaderboard-highlights a:visited,
.leaderboard-highlights a:hover,
.leaderboard-highlights a:focus,
.leaderboard-highlight-link {
  color: inherit;
  text-decoration: none;
  text-decoration-line: none;
}

.leaderboard-highlight-link {
  cursor: pointer;
}

.leaderboard-highlight-link *,
.leaderboard-highlight-link *:visited {
  text-decoration: none;
  text-decoration-line: none;
}

.leaderboard-highlight-link:hover,
.leaderboard-highlight-link:focus-visible {
  border-color: var(--teal);
  box-shadow: 0.16rem 0.16rem 0 var(--teal-glow);
  outline: none;
}

.leaderboard-highlight-link:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

html[data-theme="dark"] .leaderboard-highlight-link:focus-visible {
  outline-color: var(--gold);
}

.leaderboard-highlight-detail {
  min-width: 0;
  overflow: hidden;
  color: var(--ink-muted);
  font: 750 0.74rem/1.12 system-ui, sans-serif;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-highlight-words {
  display: grid;
  gap: 0.12rem;
  min-width: 0;
  padding-top: 0.15rem;
}

.leaderboard-highlight-words span {
  min-width: 0;
  overflow: hidden;
  color: var(--ink);
  font: 950 0.78rem/1.05 system-ui, sans-serif;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-highlight-item-words-value .leaderboard-highlight-words {
  align-self: start;
  padding-top: 0;
}

.leaderboard-highlight-item-words-value .leaderboard-highlight-words span {
  color: var(--coral);
  font-size: 1.02rem;
  line-height: 1.08;
}

html[data-theme="dark"] .leaderboard-highlight-item-words-value .leaderboard-highlight-words span {
  color: var(--gold);
}

.leaderboard-table {
  display: grid;
  gap: 0.32rem;
  min-width: 0;
}

/* Zebra cream rows on the diner-style leaderboard table */
.leaderboard-row {
  display: grid;
  grid-template-columns: 3.3rem minmax(0, 1fr) minmax(5.4rem, auto) minmax(5.2rem, auto) minmax(4.2rem, auto) minmax(4.2rem, auto);
  align-items: center;
  gap: 0.5rem;
  min-height: 2.9rem;
  padding: 0.5rem 0.65rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
  font: 400 0.92rem/1.15 system-ui, sans-serif;
}

.leaderboard-row:not(.leaderboard-header):nth-of-type(even) {
  background: var(--surface-raised);
}

.leaderboard-row span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-row span:nth-child(1),
.leaderboard-row span:nth-child(n + 3) {
  text-align: right;
}

.leaderboard-row:not(.leaderboard-header) span:nth-child(2) {
  color: var(--ink);
  text-align: left;
}

.leaderboard-header {
  min-height: 2.2rem;
  background: transparent;
  color: var(--ink-muted);
  font: 950 0.66rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Rank #1 highlight row: gold fill, first data row right after the header.
   .leaderboard-table prefix keeps specificity >= the zebra rule above so the gold fill wins. */
.leaderboard-table .leaderboard-header + .leaderboard-row {
  border-color: var(--gold-deep);
  background: linear-gradient(135deg, var(--gold-wash), var(--surface-raised) 70%);
  box-shadow: 0.14rem 0.14rem 0 var(--gold-deep);
  font-weight: 800;
}

html[data-theme="dark"] .leaderboard-table .leaderboard-header + .leaderboard-row {
  border-color: var(--gold);
  background: linear-gradient(135deg, var(--gold-wash), var(--surface-raised) 70%);
  box-shadow: 0 0 calc(12px * var(--glow-strength)) var(--gold-glow);
}

.leaderboard-empty {
  display: grid;
  min-height: 4.5rem;
  place-items: center;
  border: 2px dashed var(--cell-border);
  border-radius: 8px;
  color: var(--ink-muted);
  font: 400 0.95rem/1.25 system-ui, sans-serif;
}

.active-games-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.65rem;
}

.new-game-disabled-link {
  display: none;
}

html.new-games-disabled .new-game-enabled-control {
  display: none;
}

html.new-games-disabled .new-game-disabled-link {
  display: inline-flex;
}

.active-games-group {
  display: grid;
  gap: 0.45rem;
}

.active-games-group + .active-games-group {
  margin-top: 0.55rem;
}

.active-games-group-title {
  justify-self: start;
  margin: 0;
  padding: 0.14rem 0.42rem;
  border: 2px solid var(--sign-face);
  border-radius: 5px;
  background: var(--surface);
  color: var(--ink);
  font: 400 0.72rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
}

/* Motel-sign card: cream name plate, coral border, gold YOUR TURN tab when it's your move */
.active-game-row {
  position: relative;
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.7rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
  text-align: left;
  box-shadow: 0.14rem 0.14rem 0 var(--shadow-soft);
}

/* No per-row "Your Turn" tab — the group heading already says it; the gold
   border/shadow alone marks waiting games. */
.active-game-row.waiting-player {
  border-color: var(--gold-deep);
  background: var(--surface-raised);
  box-shadow: 0.18rem 0.18rem 0 var(--gold-deep);
}

html[data-theme="dark"] .active-game-row.waiting-player {
  border-color: var(--gold);
  box-shadow: 0 0 calc(12px * var(--glow-strength)) var(--gold-glow);
}

.active-game-row.completed-game {
  border-color: var(--cell-border);
  background: var(--surface);
  opacity: 0.82;
}

.active-games-empty {
  display: grid;
  justify-items: start;
  gap: 0.3rem;
  padding: 1rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface);
  text-align: left;
  box-shadow: 0.18rem 0.18rem 0 var(--gold-glow);
}

.active-games-empty-title {
  margin: 0;
  color: var(--ink);
  font: 900 1.05rem/1.15 Georgia, "Times New Roman", serif;
}

.active-games-empty-copy {
  margin: 0;
  color: var(--ink-muted);
  font: 700 0.9rem/1.35 system-ui, sans-serif;
}

.active-game-id {
  align-self: center;
  display: grid;
  gap: 0.28rem;
  color: var(--ink);
  font: 900 0.95rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
}

.active-game-turn {
  color: var(--teal-deep);
  font: 800 0.78rem/1.25 system-ui, sans-serif;
  letter-spacing: 0;
}

html[data-theme="dark"] .active-game-turn {
  color: var(--cyan-neon);
}

.active-game-pool {
  color: var(--ink-muted);
  font: 800 0.72rem/1.2 system-ui, sans-serif;
  letter-spacing: 0;
}

.active-game-details {
  min-width: 0;
  display: grid;
  gap: 0.28rem;
}

.active-game-player-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, max-content));
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.active-game-player-score {
  display: inline-grid;
  grid-template-columns: minmax(0, 1fr) auto;
  /* center, not baseline: the winner name is an inline-flex with a star, whose
     synthesized baseline differs from plain text and shifted the score down. */
  align-items: center;
  gap: 0.25rem;
  min-width: 7rem;
  padding: 0.18rem 0.45rem;
  border: 1px solid var(--cell-border);
  border-radius: 6px;
  background: var(--surface-raised);
  white-space: nowrap;
}

.active-game-player-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

.active-game-player-points {
  justify-self: end;
  text-align: right;
  font-weight: 900;
}

.active-game-player-score.current-player {
  color: var(--teal-deep);
  font-weight: 900;
  border-color: var(--teal);
  background: var(--cell);
}

html[data-theme="dark"] .active-game-player-score.current-player {
  color: var(--cyan-neon);
}

.active-game-player-score.winner-player {
  color: var(--coral-deep);
  font-weight: 900;
  border-color: var(--gold-deep);
  background: linear-gradient(135deg, var(--gold-wash), var(--surface-raised) 68%);
  box-shadow: 0.1rem 0.1rem 0 var(--gold-deep);
}

html[data-theme="dark"] .active-game-player-score.winner-player {
  color: var(--gold);
  background: linear-gradient(135deg, var(--gold-wash), var(--surface-raised) 68%);
}

.active-game-player-score.conceded-player {
  color: var(--ink-muted);
  border-color: var(--cell-border);
  background: var(--cell);
  text-decoration: line-through;
}

.active-game-player-score.winner-player .active-game-player-name {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
}

.active-game-player-score.winner-player .active-game-player-name::before {
  content: "";
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  background-color: var(--gold-deep);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1 14 8.5 21.5 6.5 16 12 21.5 17.5 14 15.5 12 23 10 15.5 2.5 17.5 8 12 2.5 6.5 10 8.5Z' fill='%23000'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1 14 8.5 21.5 6.5 16 12 21.5 17.5 14 15.5 12 23 10 15.5 2.5 17.5 8 12 2.5 6.5 10 8.5Z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

.page-hero,
.rules-hero {
  display: grid;
  gap: 0.55rem;
  width: 100%;
  padding-bottom: 0.45rem;
  border-bottom: 3px solid var(--cell-border);
}

.page-hero .section-title,
.rules-hero .section-title {
  text-align: left;
}

/* Rules highway: a vertical road runs down the center of the page, signs
   (rules cards) are planted on alternating shoulders and slide in from
   their side of the road as the page scrolls. */
.rules-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 3.75rem 0;
  padding: 0.5rem 0 2.5rem;
}

/* Asphalt strip + dashed centerline, tokens only. Sits behind the cards. */
.rules-grid::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3rem;
  transform: translateX(-50%);
  background: var(--road-asphalt);
  background-image: linear-gradient(
    var(--road-centerline) 0,
    var(--road-centerline) 50%,
    transparent 50%,
    transparent 100%
  );
  background-repeat: repeat-y;
  background-position: center;
  background-size: 0.2rem 2.25rem;
  box-shadow: 0 0 1.5rem var(--road-centerline-glow);
  border-radius: 999px;
  pointer-events: none;
  z-index: 0;
}

/* Roadside postcard: cream card, coral border, gold drop shadow */
.rules-card {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 0.55rem;
  align-content: start;
  width: min(100%, 22rem);
  padding: 0.85rem;
  border: 2px solid var(--coral);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0.18rem 0.18rem 0 var(--gold-glow);
}

html[data-theme="dark"] .rules-card {
  border-color: var(--pink-neon);
  background: var(--surface-raised);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
}

.rules-card h3 {
  margin: 0;
  color: var(--ink);
  font: 900 1.08rem/1.1 Georgia, "Times New Roman", serif;
}

.rules-card p,
.rules-card ul {
  margin: 0;
  color: var(--ink);
  font-weight: 500;
  line-height: 1.42;
}

.rules-card ul {
  padding-left: 1.1rem;
}

/* Signpost: a single sturdy post planted under each sign. It tucks up
   behind the card (negative z-index inside the card's stacking context)
   so the joint stays hidden even with the card's tilt. */
.rules-card::after {
  content: "";
  position: absolute;
  /* flush below the border: the card's tilt creates a stacking context that
     keeps z-index:-1 pseudos ABOVE the card, so any overlap paints over the
     sign (100% only reaches the INNER border edge). The post rotates with
     the card, so a flush joint stays seamless. */
  top: calc(100% + 2px);
  left: 50%;
  width: 0.7rem;
  height: 2.5rem;
  transform: translateX(-50%);
  background: linear-gradient(90deg, var(--sign-wood-deep), var(--sign-wood) 45%, var(--sign-wood-deep));
  border-radius: 0 0 4px 4px;
  box-shadow: inset 1px 0 0 var(--sheen-soft);
  pointer-events: none;
  z-index: -1;
}

/* Odd cards: left shoulder, slight left-leaning tilt. */
.rules-card:nth-child(odd) {
  justify-self: start;
  margin-left: clamp(0.5rem, 6vw, 3rem);
  rotate: -1.4deg;
}

/* Even cards: right shoulder, slight right-leaning tilt. */
.rules-card:nth-child(even) {
  justify-self: end;
  margin-right: clamp(0.5rem, 6vw, 3rem);
  rotate: 1.4deg;
}

/* Letter-points table sign: bigger diner menu board on two real posts. */
.rules-card:has(.letter-points-table) {
  width: min(100%, 26rem);
}

.rules-card:has(.letter-points-table)::before {
  content: "";
  position: absolute;
  top: calc(100% + 2px);
  left: 20%;
  width: 0.7rem;
  height: 2.5rem;
  transform: translateX(-50%);
  background: linear-gradient(90deg, var(--sign-wood-deep), var(--sign-wood) 45%, var(--sign-wood-deep));
  border-radius: 0 0 4px 4px;
  box-shadow: inset 1px 0 0 var(--sheen-soft);
  pointer-events: none;
  z-index: -1;
}

.rules-card:has(.letter-points-table)::after {
  left: 80%;
}

/* Scroll-in slide: default styles ARE the rest state, so browsers without
   scroll-timeline support (or reduced-motion) simply render signs at rest.
   The animation only pulls FROM an offset TO that same rest state. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .rules-card:nth-child(odd) {
      animation: rules-sign-slide-in-left linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 65%;
    }

    .rules-card:nth-child(even) {
      animation: rules-sign-slide-in-right linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 65%;
    }

    @keyframes rules-sign-slide-in-left {
      from {
        translate: -6rem 0;
        rotate: -8deg;
        opacity: 0;
      }

      to {
        translate: 0 0;
        rotate: -1.4deg;
        opacity: 1;
      }
    }

    @keyframes rules-sign-slide-in-right {
      from {
        translate: 6rem 0;
        rotate: 8deg;
        opacity: 0;
      }

      to {
        translate: 0 0;
        rotate: 1.4deg;
        opacity: 1;
      }
    }
  }
}

/* Mobile: road moves to the left edge, every sign lines up in a single
   column to its right, offsets shrink so nothing can overflow. */
@media (max-width: 700px) {
  .rules-grid {
    gap: 2.75rem 0;
    padding-left: 1.6rem;
  }

  .rules-grid::before {
    left: 0.9rem;
    width: 1.6rem;
    transform: none;
    background-size: 0.14rem 1.6rem;
  }

  /* Leave a real right shoulder: full-width tilted cards otherwise rotate
     their corners past the container edge and get clipped by the section's
     overflow-x: clip. Gentler tilt + 0.85rem right margin keeps every corner
     (and the border glow) inside the viewport. */
  .rules-card,
  .rules-card:nth-child(odd),
  .rules-card:nth-child(even) {
    justify-self: start;
    width: calc(100% - 2.1rem);
    margin-left: 1.25rem;
    margin-right: 0.85rem;
  }

  .rules-card:nth-child(odd) {
    rotate: -0.8deg;
  }

  .rules-card:nth-child(even) {
    rotate: 0.8deg;
  }

  @media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
      @keyframes rules-sign-slide-in-left {
        from {
          translate: -2.5rem 0;
          rotate: -6deg;
          opacity: 0;
        }
      }

      @keyframes rules-sign-slide-in-right {
        from {
          translate: 2.5rem 0;
          rotate: 6deg;
          opacity: 0;
        }
      }
    }
  }
}

/* Diner menu board: dark header row, cream body rows */
.letter-points-table {
  width: 100%;
  border-collapse: collapse;
  overflow: hidden;
  border: 2px solid var(--sign-face);
  border-radius: 6px;
  background: var(--surface);
  font: 500 0.9rem/1.25 system-ui, sans-serif;
}

.letter-points-table th,
.letter-points-table td {
  padding: 0.32rem 0.48rem;
  border-bottom: 1px solid var(--cell-border);
  font-weight: 500;
  text-align: left;
}

.letter-points-table thead th {
  color: var(--ink-on-dark);
  background: var(--sign-face);
  font: 400 0.76rem/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.letter-points-table tbody th {
  width: 4.4rem;
  color: var(--coral);
  text-align: center;
}

html[data-theme="dark"] .letter-points-table tbody th {
  color: var(--gold);
}

.letter-points-table tbody tr:last-child th,
.letter-points-table tbody tr:last-child td {
  border-bottom: 0;
}

.letter-points-table td {
  color: var(--ink);
}

.changelog-list {
  display: grid;
  gap: 0.85rem;
  width: var(--play-width);
  justify-self: center;
}

/* "What's New" diner menu card */
.changelog-entry {
  display: grid;
  gap: 0.55rem;
  padding: 0.85rem;
  border: 2px solid var(--teal);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: 0.18rem 0.18rem 0 var(--teal-deep);
}

html[data-theme="dark"] .changelog-entry {
  border-color: var(--cyan-neon);
  background: var(--surface-raised);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--teal-glow);
}

.changelog-entry h3,
.changelog-entry p {
  margin: 0;
}

.changelog-entry h3 {
  color: var(--ink);
  font: 900 1.08rem/1.1 Georgia, "Times New Roman", serif;
}

.changelog-entry .changelog-date {
  color: var(--ink-muted);
  font-size: 0.86rem;
  font-weight: 800;
}

.changelog-entry p {
  color: var(--ink);
  font-weight: 400;
  line-height: 1.42;
}

.rules-example,
.rules-board-example {
  --rules-board-cell-size: calc((var(--play-width) - 10px) / 9);
}

.rules-example {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
}

.rules-example .board-cell {
  width: var(--rules-board-cell-size);
  flex: 0 0 var(--rules-board-cell-size);
  aspect-ratio: 1;
}

.rules-board-example {
  display: grid;
  grid-template-columns: repeat(4, var(--rules-board-cell-size));
  grid-auto-rows: var(--rules-board-cell-size);
  gap: 2px;
  width: max-content;
  max-width: 100%;
  padding: 5px;
  border-radius: 10px;
  background: var(--board-frame);
}

.rules-board-example .board-cell {
  width: auto;
  flex: initial;
}

.rules-board-example-stack {
  grid-template-columns: repeat(3, var(--rules-board-cell-size));
}

.rules-example-bottom {
  margin-top: auto;
}

.rules-equation {
  color: var(--coral);
  font: 900 0.92rem/1.2 system-ui, sans-serif;
}

html[data-theme="dark"] .rules-equation {
  color: var(--gold);
}

.game-area {
  display: none;
  width: 100%;
  justify-items: center;
  gap: 1rem;
}

body.screen-play .masthead {
  margin-bottom: 0.75rem;
}

body.screen-play:not(.has-player) .masthead {
  margin-bottom: 0;
}

.rules-page,
.changelog-page {
  display: none;
  grid-column: 1 / -1;
  width: 100%;
  max-width: 54rem;
  gap: 1rem;
  text-align: left;
  font: 700 0.98rem/1.45 system-ui, sans-serif;
}

/* The highway's sliding signs animate via translate, which can nudge a sign
   past its own box during the scroll-in; clip locally so it never creates a
   page-level horizontal scrollbar. Scoped to this section only -- never on
   body/html ancestors of the game area. */
.rules-page {
  overflow-x: clip;
}

body.screen-rules .rules-page,
body.screen-changelog .changelog-page {
  margin-top: calc(clamp(1.5rem, 3vw, 2.25rem) - 0.75rem);
}

body.screen-display-name .display-name-page {
  margin-top: clamp(0.35rem, 1.5vw, 0.8rem);
}

body.screen-rules .rules-hero,
body.screen-changelog .page-hero {
  width: var(--play-width);
  justify-self: center;
}

body.screen-welcome:not(.has-player) .identity-panel {
  display: grid;
  gap: 0.85rem;
}

body.screen-leaderboard:not(.has-player) .identity-panel {
  display: grid;
  gap: 0.85rem;
}

body.screen-play:not(.has-player) .identity-panel {
  display: grid;
  gap: 0.85rem;
}

body.screen-welcome:not(.has-player) .masthead {
  grid-template-columns: 1fr;
  justify-items: center;
  align-self: start;
}

body.screen-leaderboard:not(.has-player) .masthead,
body.screen-play:not(.has-player) .masthead {
  width: var(--play-width);
  grid-template-columns: 1fr;
  justify-items: center;
  align-self: start;
}

body.screen-welcome:not(.has-player) .brand,
body.screen-welcome:not(.has-player) .game-controls {
  justify-self: center;
}

body.screen-leaderboard:not(.has-player) .brand,
body.screen-play:not(.has-player) .brand,
body.screen-leaderboard:not(.has-player) .game-controls {
  justify-self: center;
}

body.screen-play:not(.has-player) .game-controls {
  justify-self: center;
}

body.screen-welcome:not(.has-player) .brand {
  --brand-scale: clamp(2.2rem, 8.4vw, 4.4rem); /* match privacy/terms sign size */
  margin-bottom: 0.18em;
}

body.screen-leaderboard:not(.has-player) .brand {
  --brand-scale: 1.5rem;
  margin-bottom: 0;
}

body.screen-play:not(.has-player) .brand {
  --brand-scale: 1.5rem;
  margin-bottom: 0;
}

body.screen-welcome:not(.has-player) main {
  align-content: start;
  padding-top: clamp(0.85rem, 2.3vw, 1.55rem);
}

body.screen-leaderboard:not(.has-player) main,
body.screen-play:not(.has-player) main {
  align-content: start;
  gap: 0.75rem;
  padding-top: clamp(0.85rem, 2vw, 1.35rem);
}

body.screen-welcome.welcome-demo .game-area {
  display: grid;
  gap: 1rem;
  margin-top: 1rem;
}

body.screen-welcome.welcome-demo .invite-link-panel,
body.screen-welcome.welcome-demo .rack-controls,
body.screen-welcome.welcome-demo .redraw-confirm,
body.screen-welcome.welcome-demo .pass-confirm,
body.screen-welcome.welcome-demo .game-log,
body.screen-welcome.welcome-demo .concede-game-control,
body.screen-welcome.welcome-demo .winner-banner,
body.screen-welcome.welcome-demo .player-score-list,
body.screen-welcome.welcome-demo #view-pool-button,
body.screen-welcome.welcome-demo .game-sheet {
  display: none;
}

body.screen-welcome.welcome-demo .rack {
  background: color-mix(in srgb, var(--teal) 12%, transparent);
}

body.screen-welcome.welcome-demo .rack-shuffle-button {
  display: grid;
}

body.screen-welcome.welcome-demo .tile-movable {
  cursor: grab;
}

body.screen-welcome.welcome-demo .tile-movable:active {
  cursor: grabbing;
}

body.screen-welcome.welcome-leaderboard .leaderboard-page {
  display: grid;
  margin-top: 1rem;
}

body.screen-welcome.welcome-leaderboard .leaderboard-page .page-hero {
  justify-items: center;
  text-align: center;
}

body.screen-display-name main {
  align-content: start;
  gap: 0.75rem;
  padding-top: clamp(0.85rem, 2vw, 1.35rem);
}

body.screen-display-name .masthead {
  width: var(--play-width);
  row-gap: 0;
  column-gap: 1rem;
  align-self: start;
}

body.screen-display-name .brand {
  font-size: 2.2rem;
  margin-bottom: 0;
}

body.has-player .identity-bar {
  display: flex;
}

body.screen-setup .player-setup {
  display: grid;
}

body.screen-list .active-games,
body.screen-leaderboard .leaderboard-page {
  display: grid;
}

body.screen-display-name .display-name-page {
  display: grid;
}

body.screen-rules .rules-page,
body.screen-changelog .changelog-page {
  display: grid;
}

body.screen-play .game-area {
  display: grid;
}

.spectator-hero {
  display: none;
  width: var(--play-width);
}

.spectator-title .spectator-eyeglasses-icon {
  color: var(--teal-deep);
}

body.screen-play.spectator-mode .spectator-hero {
  display: grid;
}

.board {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, minmax(0, 1fr));
  width: var(--play-width);
  aspect-ratio: 1;
  background: var(--board-frame);
  border-radius: 10px;
  gap: 2px;
  padding: 5px;
}

.board-cell {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--cell);
  border: 1px solid var(--cell-border);
  border-radius: 4px;
}

.board-cell.drop-ready {
  background: var(--teal);
  opacity: 0.75;
}

.board-cell > .tile,
.board-cell > .marketplace-item {
  z-index: 3;
}

.board-cell-bonus-doubleLetter {
  background: var(--teal-soft);
  border-color: var(--teal-deep);
  color: var(--tile-ink); /* theme-stable dark ink: AA on the light teal fill */
}

.board-cell-bonus-tripleLetter {
  background: var(--teal-deep);
  border-color: var(--teal-deep);
  color: var(--on-accent-ink);
}

.board-cell-bonus-doubleWord {
  background: var(--gold);
  border-color: var(--gold-deep);
  color: var(--tile-ink); /* theme-stable: --ink flips to cream in dark, cream-on-gold fails */
}

.board-cell-bonus-tripleWord {
  background: var(--coral);
  border-color: var(--coral-deep);
  color: var(--ink-on-dark);
}

.board-cell-start {
  background: var(--gold);
  border-color: var(--gold-deep);
  color: var(--tile-ink); /* theme-stable: --ink flips to cream in dark, cream-on-gold fails */
}

.board-bonus-label {
  position: absolute;
  inset: 0.2rem;
  display: grid;
  align-content: center;
  place-items: center;
  gap: 0.08rem;
  font: 800 clamp(0.44rem, 1.15vw, 0.58rem)/1 system-ui, sans-serif;
  color: currentColor;
  text-align: center;
  text-transform: lowercase;
  pointer-events: none;
  user-select: none;
}

.board-bonus-multiplier,
.board-bonus-scope {
  display: block;
}

.board-start-label {
  position: absolute;
  inset: 0.2rem;
  display: grid;
  place-items: center;
  border-radius: 6px;
  color: var(--coral);
  font: 900 clamp(0.5rem, 1.35vw, 0.68rem)/1 system-ui, sans-serif;
  letter-spacing: 0.02em;
  text-align: center;
  text-transform: uppercase;
  pointer-events: none;
  user-select: none;
}

.board-start-label::before {
  content: "\2605";
  margin-right: 0.15em;
}

.board-cell-bonus.drop-ready {
  filter: brightness(1.12);
}

/* Bottom dock: sticky at viewport bottom on mobile, "counter edge" teal top border */
.rack-wrap {
  position: sticky;
  /* Only the rack + action buttons pin to the viewport bottom. The
     game/turn/potential/pool stats row is a separate sibling below (see
     .game-state-summary) so it naturally sits below the fold and scrolls in —
     no fragile fixed offset that breaks when tile height changes. */
  bottom: 0;
  z-index: 5;
  width: 100%;
  max-width: var(--play-width);
  display: grid;
  gap: 0.6rem;
  justify-items: start;
  margin-top: 0.25rem;
  padding: 0.6rem clamp(0.5rem, 3vw, 0.85rem) calc(0.6rem + env(safe-area-inset-bottom, 0px));
  border-top: 3px solid var(--teal);
  background: var(--surface);
  box-shadow: 0 -4px 12px var(--shadow-soft);
}

html[data-theme="dark"] .rack-wrap {
  border-top-color: var(--cyan-neon);
  box-shadow: 0 0 calc(14px * var(--glow-strength)) var(--teal-glow);
}

@media (min-width: 1024px) {
  .rack-wrap {
    position: static;
  }
}

/* Wide viewports: the play column stays centered (identical flow to mobile,
   so the board sits on the true page centerline). At >=1280px — when there is
   room for half the board plus a 20rem panel beside it — the Scores & Log
   sheet detaches into a fixed panel floating to the right of the board, and
   its toggle disappears. Between 1024px and 1279px it remains the collapsible
   sheet under the dock. Fixed positioning is measured from the viewport
   centerline, which matches the board's centerline because the play column
   is centered. */
@media (min-width: 1280px) {
  body.screen-play .marketplace-wrap {
    anchor-name: --market-sign;
  }

  body.screen-play #game-sheet {
    position: fixed;
    /* Align the panel's top edge with the market sign. anchor() needs CSS
       anchor positioning; the rem value is the fallback for browsers that
       drop the anchor declaration at parse time. */
    top: 8.25rem;
    top: anchor(--market-sign top);
    left: calc(50vw + var(--play-width) / 2 + 1.75rem);
    width: 20rem;
    /* Content-sized (hugs short logs, so buttons keep their natural size),
       but capped so a long log scrolls INSIDE the panel instead of running
       off the bottom. 17rem ≈ market-sign top (~15.5rem) + bottom gap; the
       panel starts at the sign and ends ~1.5rem above the viewport bottom. */
    max-height: calc(100dvh - 17rem);
    overflow-y: auto;
    opacity: 1;
    padding: 0.85rem;
    z-index: 4;
    border: 2px solid var(--cell-border);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: 0.18rem 0.18rem 0 var(--shadow-soft);
  }

}

.rack {
  position: relative;
  anchor-name: --rack;
  width: 100%;
  min-height: 4.75rem;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: clamp(0.35rem, 1.8vw, 0.75rem);
  padding: calc(clamp(0.45rem, 1.8vw, 0.75rem) + 0.42rem) clamp(0.45rem, 1.8vw, 0.75rem) clamp(0.45rem, 1.8vw, 0.75rem);
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--cell);
}

body.screen-play.is-my-turn .rack {
  background: var(--cell);
  border-color: var(--teal);
}

.last-turn-notice {
  display: none;
  width: 100%;
  justify-self: center;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 2.2rem;
  padding: 0.36rem 0.75rem;
  border: 2px solid var(--gold-deep);
  border-radius: 8px;
  background: var(--gold);
  color: var(--ink);
  font: 900 0.9rem/1.15 system-ui, sans-serif;
  letter-spacing: 0.06em;
  text-align: center;
  text-transform: uppercase;
  box-shadow: 0.12rem 0.12rem 0 var(--shadow-soft);
}

html[data-theme="dark"] .last-turn-notice {
  background: var(--sign-face);
  color: var(--gold);
  border-color: var(--gold);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
}

.last-turn-notice .ww-icon {
  width: 1.15rem;
  height: 1.15rem;
}

body.screen-play.last-turn:not(.game-over) .last-turn-notice {
  display: flex;
}

.marketplace-wrap {
  width: var(--play-width);
  display: grid;
  gap: 0.35rem;
  justify-items: start;
  position: relative;
}

/* MARKET sign: coral post (stacked letters + gold starburst) + dark letter-board holding the tile rack */
.market-sign {
  display: flex;
  align-items: stretch;
  width: 100%;
}

.market-sign-post {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  padding: 0.6rem 0.4rem 0.5rem;
  border-radius: 8px 0 0 12px;
  background: var(--sign-post);
  box-shadow:
    inset 0 2px 0 var(--sheen-soft),
    0 0 calc(10px * var(--glow-strength)) var(--coral-glow);
  border: 1.5px solid var(--pink-neon);
  border-right: none;
}

html:not([data-theme="dark"]) .market-sign-post {
  border-color: transparent;
}

.market-sign-star {
  position: absolute;
  top: -0.95rem;
  left: 50%;
  transform: translateX(-50%);
  color: var(--gold);
  font-size: 1.4rem;
  line-height: 1;
  text-shadow:
    1px 1px 0 var(--coral-deep),
    0 0 calc(10px * var(--glow-strength)) var(--gold-glow),
    0 0 calc(20px * var(--glow-strength)) var(--gold-glow);
}

.market-sign-letters {
  font-size: 0.72rem;
  font-weight: 400;
  line-height: 1.28;
  text-align: center;
  color: var(--ink-on-dark);
  text-shadow: 1px 1px 0 var(--shade-soft);
}

html[data-theme="dark"] .market-sign-letters {
  color: var(--pink-neon);
  text-shadow:
    0 0 calc(7px * var(--glow-strength)) var(--coral-glow),
    0 0 calc(14px * var(--glow-strength)) var(--coral-glow);
}

.market-sign-board {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.5rem 0.5rem 0;
  border-radius: 0 14px 14px 6px;
  background: var(--sign-face);
  box-shadow:
    inset 0 2px 0 var(--sheen-soft),
    0 4px 10px var(--shadow-soft),
    0 0 calc(12px * var(--glow-strength)) var(--teal-glow);
  border: 1.5px solid var(--cyan-neon);
}

html:not([data-theme="dark"]) .market-sign-board {
  border-color: transparent;
}

.market-sign-open-tab {
  position: absolute;
  right: -0.5rem;
  top: -0.65rem;
  z-index: 4;
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  background: var(--teal);
  color: var(--on-accent-ink);
  font-size: 0.5rem;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transform: rotate(6deg);
  box-shadow: 0 2px 0 var(--teal-deep);
  pointer-events: none;
}

html[data-theme="dark"] .market-sign-open-tab {
  background: var(--sign-face);
  color: var(--cyan-neon);
  border: 1px solid var(--cyan-neon);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--teal-glow);
  text-shadow: 0 0 calc(6px * var(--glow-strength)) var(--teal-glow);
  animation: market-sign-open-tab-buzz 2600ms ease-in-out infinite;
}

/* The OPEN tab only shows when the market is actually open — renderGame()
   toggles these body classes for the Opening Soon and Closed states. */
body.marketplace-opening-soon .market-sign-open-tab,
body.marketplace-closed .market-sign-open-tab {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  html[data-theme="dark"] .market-sign-open-tab {
    animation: none;
  }
}

@keyframes market-sign-open-tab-buzz {
  0%, 88%, 100% {
    opacity: 1;
  }

  90% {
    opacity: 0.55;
  }

  92% {
    opacity: 1;
  }

  94% {
    opacity: 0.7;
  }
}

.marketplace {
  position: relative;
  width: 100%;
  min-height: 4.75rem;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: clamp(0.35rem, 1.8vw, 0.75rem);
  padding: clamp(0.45rem, 1.8vw, 0.75rem) clamp(0.45rem, 1.8vw, 0.75rem) 1.7rem;
}

.marketplace-closed-sign,
.marketplace-opening-soon-sign {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 6;
  display: grid;
  place-items: center;
  min-width: min(12rem, 62%);
  min-height: 2.75rem;
  padding: 0.4rem 1rem;
  border-radius: 6px;
  font: 400 clamp(1rem, 4.6vw, 1.6rem)/1 "Righteous", "Trebuchet MS", sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transform: translate(-50%, -50%) rotate(-5deg);
  pointer-events: none;
}

.marketplace-opening-soon-sign {
  min-width: min(17rem, 84%);
  border: 3px solid var(--coral);
  background: var(--sign-face);
  color: var(--gold);
  box-shadow:
    0.18rem 0.22rem 0 var(--shadow-soft),
    0 0 calc(14px * var(--glow-strength)) var(--gold-glow);
  transform: translate(-50%, -50%) rotate(3deg);
}

.marketplace-opening-soon-sign::before {
  content: "✶ ";
}

.marketplace-closed-sign {
  border: 3px solid var(--coral);
  background: var(--tile-face);
  color: var(--coral);
  box-shadow: 0.18rem 0.22rem 0 var(--shadow-soft);
}

html[data-theme="dark"] .marketplace-opening-soon-sign {
  border-color: var(--cyan-neon);
}

html[data-theme="dark"] .marketplace-closed-sign {
  border-color: var(--pink-neon);
  color: var(--pink-neon);
}

/* Winner banner: neon marquee, keeps confetti + aria behavior */
.winner-banner {
  display: none;
  position: relative;
  width: 100%;
  min-height: 4.75rem;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: clamp(0.35rem, 1.8vw, 0.75rem);
  padding: calc(clamp(0.45rem, 1.8vw, 0.75rem) + 0.42rem) clamp(0.45rem, 1.8vw, 0.75rem) clamp(0.45rem, 1.8vw, 0.75rem);
  border: 2px solid var(--gold-deep);
  border-radius: 8px;
  background: var(--sign-face);
  box-shadow: 0.18rem 0.18rem 0 var(--shadow-soft);
  overflow: visible;
  text-align: left;
}

html[data-theme="dark"] .winner-banner {
  border-color: var(--pink-neon);
  box-shadow:
    0 0 calc(12px * var(--glow-strength)) var(--coral-glow),
    0 0 calc(20px * var(--glow-strength)) var(--gold-glow);
}

.winner-banner::before {
  content: "Final Result";
  position: absolute;
  top: -0.58rem;
  left: 0.7rem;
  z-index: 2;
  padding: 0.12rem 0.38rem;
  border: 2px solid var(--gold-deep);
  border-radius: 5px;
  background: var(--gold);
  color: var(--ink);
  font: 800 0.72rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

html[data-theme="dark"] .winner-banner::before {
  border-color: var(--pink-neon);
  background: var(--sign-face);
  color: var(--pink-neon);
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--coral-glow);
}

.winner-banner-confetti {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.winner-banner-confetti-piece {
  position: absolute;
  top: -0.8rem;
  left: var(--confetti-left);
  width: var(--confetti-width, 0.38rem);
  height: var(--confetti-height, 0.62rem);
  border-radius: 2px;
  background: var(--confetti-color);
  opacity: 0.7;
  transform: translateY(-0.8rem) rotate(var(--confetti-rotate, 0deg));
  animation: winner-banner-confetti-fall var(--confetti-duration, 4.6s) linear infinite;
  animation-delay: var(--confetti-delay, 0s);
}

.winner-banner-confetti-piece:nth-child(3n) {
  border-radius: 50%;
}

.winner-banner-confetti-piece:nth-child(4n) {
  height: var(--confetti-width, 0.38rem);
}

.winner-banner-confetti-piece:nth-child(1) {
  --confetti-left: 4%;
  --confetti-color: var(--coral);
  --confetti-delay: -0.6s;
  --confetti-duration: 4.8s;
  --confetti-rotate: 12deg;
}

.winner-banner-confetti-piece:nth-child(2) {
  --confetti-left: 13%;
  --confetti-color: var(--teal);
  --confetti-delay: -2.1s;
  --confetti-duration: 5.4s;
  --confetti-width: 0.3rem;
  --confetti-rotate: -24deg;
}

.winner-banner-confetti-piece:nth-child(3) {
  --confetti-left: 22%;
  --confetti-color: var(--gold);
  --confetti-delay: -1.4s;
  --confetti-duration: 4.4s;
  --confetti-height: 0.42rem;
  --confetti-rotate: 36deg;
}

.winner-banner-confetti-piece:nth-child(4) {
  --confetti-left: 31%;
  --confetti-color: var(--pink-neon);
  --confetti-delay: -3s;
  --confetti-duration: 5.8s;
  --confetti-rotate: 8deg;
}

.winner-banner-confetti-piece:nth-child(5) {
  --confetti-left: 41%;
  --confetti-color: var(--teal-deep);
  --confetti-delay: -1.9s;
  --confetti-duration: 4.9s;
  --confetti-width: 0.32rem;
  --confetti-rotate: -40deg;
}

.winner-banner-confetti-piece:nth-child(6) {
  --confetti-left: 52%;
  --confetti-color: var(--gold);
  --confetti-delay: -0.2s;
  --confetti-duration: 5.5s;
  --confetti-rotate: 20deg;
}

.winner-banner-confetti-piece:nth-child(7) {
  --confetti-left: 63%;
  --confetti-color: var(--coral);
  --confetti-delay: -2.7s;
  --confetti-duration: 4.7s;
  --confetti-width: 0.28rem;
  --confetti-rotate: -16deg;
}

.winner-banner-confetti-piece:nth-child(8) {
  --confetti-left: 73%;
  --confetti-color: var(--cyan-neon);
  --confetti-delay: -1.1s;
  --confetti-duration: 5.9s;
  --confetti-rotate: 44deg;
}

.winner-banner-confetti-piece:nth-child(9) {
  --confetti-left: 84%;
  --confetti-color: var(--gold-deep);
  --confetti-delay: -3.5s;
  --confetti-duration: 5.2s;
  --confetti-height: 0.46rem;
  --confetti-rotate: -28deg;
}

.winner-banner-confetti-piece:nth-child(10) {
  --confetti-left: 94%;
  --confetti-color: var(--pink-neon);
  --confetti-delay: -1.7s;
  --confetti-duration: 4.6s;
  --confetti-rotate: 18deg;
}

@keyframes winner-banner-confetti-fall {
  0% {
    transform: translate3d(-0.18rem, -0.9rem, 0) rotate(var(--confetti-rotate, 0deg));
  }

  45% {
    transform: translate3d(0.22rem, 2.45rem, 0) rotate(calc(var(--confetti-rotate, 0deg) + 110deg));
  }

  100% {
    transform: translate3d(-0.08rem, 6.4rem, 0) rotate(calc(var(--confetti-rotate, 0deg) + 240deg));
  }
}

@media (prefers-reduced-motion: reduce) {
  .winner-banner-confetti-piece {
    animation: none;
    transform: translateY(1.25rem) rotate(var(--confetti-rotate, 0deg));
  }
}

.winner-banner-icon {
  grid-column: 1;
  grid-row: 1;
  place-self: center;
  z-index: 1;
  color: var(--gold);
  width: clamp(2rem, 8vw, 2.7rem);
  height: clamp(2rem, 8vw, 2.7rem);
  filter: drop-shadow(0 0 calc(10px * var(--glow-strength)) var(--gold-glow));
}

.winner-banner-spacer {
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  aspect-ratio: 1;
  visibility: hidden;
  pointer-events: none;
}

.winner-banner-copy {
  grid-column: 2 / -1;
  grid-row: 1;
  align-self: center;
  z-index: 1;
  display: grid;
  gap: 0.2rem;
  min-width: 0;
}

.winner-banner-label {
  color: var(--gold); /* sits on the dark banner face in both themes; coral fails AA there */
  font: 900 0.78rem/1.1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

html[data-theme="dark"] .winner-banner-label {
  color: var(--pink-neon);
}

.winner-banner-names {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--ink-on-dark);
  font: 900 clamp(1.1rem, 4.5vw, 1.55rem)/1.1 system-ui, sans-serif;
}

body.game-over .market-sign {
  display: none;
}

body.game-over .winner-banner {
  display: grid;
}

.rack::before {
  position: absolute;
  top: -0.58rem;
  left: 0.7rem;
  z-index: 2;
  content: "Your Tiles";
  color: var(--ink-muted);
  border: 2px solid var(--cell-border);
  border-radius: 5px;
  padding: 0.12rem 0.38rem;
  background: var(--surface-raised);
  font: 800 0.72rem/1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  pointer-events: none;
}

.tile {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: 22% 22% 9% 9%;
  background: var(--tile-face);
  color: var(--tile-ink);
  font: 800 clamp(1.35rem, 6vw, 2.25rem)/1 Georgia, "Times New Roman", serif;
  box-shadow:
    inset 0 2px 0 var(--tile-top-sheen),
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    0 2px 3px var(--shadow-soft);
  user-select: none;
}

.tile-movable {
  cursor: pointer;
}

.tile-wildcard {
  background: var(--tile-face);
  color: var(--tile-ink);
  box-shadow:
    inset 0 0 0 0.18rem var(--tile-wildcard-ring),
    inset 0 2px 0 var(--tile-top-sheen),
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    0 2px 3px var(--shadow-soft);
}

.tile-wildcard::before {
  content: "";
  position: absolute;
  /* em-based so it scales with the tile; extra bottom clearance keeps the
     dashes out of the 0.22em inset shade band */
  inset: 0.2em 0.2em 0.34em;
  border: 1px dashed var(--tile-wildcard-dash);
  border-radius: 5px;
  pointer-events: none;
}

.tile-wild-symbol {
  width: clamp(1.2rem, 5vw, 2rem);
  height: clamp(1.2rem, 5vw, 2rem);
  display: block;
  z-index: 1;
  color: var(--coral);
}

.tile-blank {
  background: var(--tile-face);
  color: var(--tile-ink);
  box-shadow:
    inset 0 0 0 2px var(--tile-bottom-shade),
    inset 0 2px 0 var(--tile-top-sheen),
    0 2px 3px var(--shadow-soft);
}

.tile-blank-symbol {
  position: relative;
  width: 42%;
  height: 28%;
  transform: translateY(12%);
}

.tile-blank-symbol::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 42%;
  border: solid currentColor;
  border-width: 0 0.16rem 0.16rem;
  box-shadow: 0 0.08rem 0 var(--tile-bottom-shade);
}

.tile-rainbow {
  background: linear-gradient(
    120deg,
    var(--rainbow-1),
    var(--rainbow-2),
    var(--rainbow-3),
    var(--rainbow-4),
    var(--rainbow-5),
    var(--rainbow-1)
  );
  background-clip: padding-box;
  background-origin: border-box;
  background-repeat: no-repeat;
  background-size: 400% 400%;
  animation: rainbow-tile-flow 7200ms ease-in-out infinite;
  animation-delay: var(--rainbow-animation-delay, 0ms);
  color: var(--on-accent-ink);
  text-shadow: 0 1px 2px var(--shadow-soft);
}

.tile-rainbow .tile-points {
  color: var(--on-accent-ink);
  text-shadow: 0 1px 2px var(--shadow-soft);
}

@media (prefers-reduced-motion: reduce) {
  .tile-rainbow {
    animation: none;
    background-position: 0% 50%;
  }
}

.marketplace-item {
  position: relative;
  z-index: 1;
  display: grid;
  align-content: start;
  min-width: 0;
}

.marketplace-cost-rail {
  position: absolute;
  left: clamp(0.45rem, 1.8vw, 0.75rem);
  right: clamp(0.45rem, 1.8vw, 0.75rem);
  bottom: 0.25rem;
  z-index: 3;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: clamp(0.35rem, 1.8vw, 0.75rem);
  pointer-events: none;
}

/* hanging price tag: triangle top (stem), rectangular body, punched hole */
.marketplace-tile-cost {
  justify-self: center;
  align-self: end;
  position: relative;
  display: grid;
  /* Digit seats toward the tag bottom, clear of the absolutely-positioned
     hanger diamond (which paints above the element's own text). */
  place-items: end center;
  padding-bottom: 0.14rem;
  width: 1.3rem;
  height: 1.12rem;
  border: 1px solid var(--gold-deep);
  border-radius: 3px;
  background: var(--tile-face);
  color: var(--ink);
  font: 800 0.72rem/1 system-ui, sans-serif;
  opacity: 0; /* hidden until its slot holds a tile — tags hang off letters, not the board */
  box-shadow: 0 0 calc(6px * var(--glow-strength)) var(--gold-glow);
}

html[data-theme="dark"] .marketplace-tile-cost {
  /* Gold tag with dark ink: gold-on-maroon digits were illegible this small. */
  border-color: var(--gold-deep);
  background: var(--gold);
  color: var(--tile-ink);
}

/* Diamond hanger: a rotated square whose two exposed edges carry the border,
   its background masks the body's top border so the outline runs all the way
   around the tag; the punched hole rides its center. */
.marketplace-tile-cost::before {
  content: "";
  position: absolute;
  top: -0.32rem;
  left: 50%;
  width: 0.56rem;
  height: 0.56rem;
  transform: translateX(-50%) rotate(45deg);
  border: 1px solid transparent;
  border-top-color: var(--gold-deep);
  border-left-color: var(--gold-deep);
  border-radius: 2px 0 0 0;
  background:
    radial-gradient(circle 0.09rem at center, var(--sign-face) 0.09rem, transparent 0.13rem),
    var(--tile-face);
}

html[data-theme="dark"] .marketplace-tile-cost::before {
  border-top-color: var(--gold-deep);
  border-left-color: var(--gold-deep);
  background:
    radial-gradient(circle 0.09rem at center, var(--sign-face) 0.09rem, transparent 0.13rem),
    var(--gold);
}

/* Digit rides above the hanger diamond (positioned pseudos paint over the
   element's raw text, so the value needs its own positioned layer). */
.marketplace-tile-cost-value {
  position: relative;
  z-index: 1;
}

/* A few pixels of string tying the tag to its letter above. */
.marketplace-tile-cost::after {
  content: "";
  position: absolute;
  top: -0.78rem;
  left: 50%;
  transform: translateX(-50%);
  width: 2px;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--gold-deep);
}

html[data-theme="dark"] .marketplace-tile-cost::after {
  background: var(--gold);
}

/* Show a tag only when its slot's letter has FINISHED arriving: game.js adds
   .tile-landed to a marketplace item when its enter animation completes (or
   immediately when the tile renders without animating). Cost rail is child 1,
   tile slots are children 2-8. Each tag drops in the moment its own letter
   lands, so timing tracks the real enter queue instead of guessed delays. */
@keyframes market-tag-drop {
  from {
    opacity: 0;
    translate: 0 -0.45rem;
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

#marketplace:has(> .marketplace-item:nth-child(2).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(1),
#marketplace:has(> .marketplace-item:nth-child(3).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(2),
#marketplace:has(> .marketplace-item:nth-child(4).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(3),
#marketplace:has(> .marketplace-item:nth-child(5).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(4),
#marketplace:has(> .marketplace-item:nth-child(6).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(5),
#marketplace:has(> .marketplace-item:nth-child(7).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(6),
#marketplace:has(> .marketplace-item:nth-child(8).tile-landed:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(7) {
  opacity: 1;
  animation: market-tag-drop 240ms ease-out both;
}

/* Tiles that were already in place (every re-render marks them
   tile-landed-instant) show their tags immediately with NO drop animation —
   otherwise unrelated re-renders (e.g. dropping a rack tile on the board)
   blink every tag. Only genuinely arriving tiles replay the drop. */
/* The :not() term matches the drop-animation selectors' specificity —
   without it those rules win and the drop replays on every re-render
   (e.g. error messages), blinking all the tags. */
#marketplace:has(> .marketplace-item:nth-child(2).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(1),
#marketplace:has(> .marketplace-item:nth-child(3).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(2),
#marketplace:has(> .marketplace-item:nth-child(4).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(3),
#marketplace:has(> .marketplace-item:nth-child(5).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(4),
#marketplace:has(> .marketplace-item:nth-child(6).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(5),
#marketplace:has(> .marketplace-item:nth-child(7).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(6),
#marketplace:has(> .marketplace-item:nth-child(8).tile-landed-instant:not(.marketplace-item-empty)) > .marketplace-cost-rail > .marketplace-tile-cost:nth-child(7) {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .marketplace-tile-cost {
    animation: none !important;
  }
}

.marketplace-item.tile-movable {
  cursor: pointer;
}

/* Lift market tiles slightly so a visible run of price-tag string meets the
   tile's bottom edge (measured: string top otherwise hides behind the tile). */
.marketplace-item > .tile {
  position: relative;
  top: -0.25rem;
}

.marketplace-item-empty {
  position: relative;
  min-height: 100%;
  border-radius: 7px;
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--tile-face) 28%, transparent);
}

html[data-theme="dark"] .marketplace-item-empty {
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink-on-dark) 28%, transparent);
}

.marketplace-item-empty::after {
  content: "SOLD";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 900 0.5rem/1 system-ui, sans-serif;
  letter-spacing: 0.1em;
  color: var(--gold);
  transform: rotate(-14deg);
}

html[data-theme="dark"] .marketplace-item-empty::after {
  color: var(--cyan-neon);
  text-shadow: 0 0 calc(6px * var(--glow-strength)) var(--teal-glow);
}

.marketplace-item-frame-placeholder {
  visibility: hidden;
  pointer-events: none;
}

.marketplace:has(> .tile.sortable-ghost) .marketplace-item-empty {
  border: 2px solid color-mix(in srgb, var(--ink) 20%, transparent);
  background: color-mix(in srgb, var(--surface-raised) 34%, transparent);
}

/* Hide the drag source's tile only while it sits IN the marketplace — the
   same element (or its clone) placed as a ghost in a board cell must stay
   visible so market drags get the same placement preview as rack drags.
   The cursor-following .sortable-fallback copy is also appended inside
   #marketplace and inherits the class (it clones after onChoose), so it is
   explicitly excluded — hiding it would hide the drag itself. */
.marketplace .marketplace-item-source-empty:not(.sortable-fallback) .tile {
  visibility: hidden;
}

.marketplace > .tile {
  width: 100%;
  max-width: 100%;
  align-self: stretch;
  justify-self: stretch;
}

.marketplace > .tile.sortable-ghost {
  display: none !important;
}

.marketplace > .tile.sortable-drag,
.marketplace > .tile.sortable-fallback {
  width: calc((var(--play-width) - 10px) / 9);
  max-width: calc((var(--play-width) - 10px) / 9);
  align-self: center;
  justify-self: center;
}

.board-cell .marketplace-item {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  gap: 0;
}

.board-cell .marketplace-tile-cost,
.marketplace-item.sortable-drag .marketplace-tile-cost,
.marketplace-item.sortable-ghost .marketplace-tile-cost {
  display: none;
}

.board-cell .marketplace-item .tile {
  width: calc(100% - 6px);
  max-width: 100%;
  font-size: clamp(0.95rem, 3vw, 1.55rem);
}

.board-cell .marketplace-item .tile-points {
  right: 0.18rem;
  bottom: 0.38rem;
  font-size: clamp(0.42rem, 1.05vw, 0.56rem);
}

.marketplace-item.sortable-drag,
.marketplace-item.sortable-ghost {
  width: calc((var(--play-width) - 10px) / 9);
  height: calc((var(--play-width) - 10px) / 9);
  display: grid;
  place-items: center;
  gap: 0;
  align-content: center;
}

.marketplace-item.sortable-drag .tile,
.marketplace-item.sortable-ghost .tile {
  width: calc(100% - 6px);
  max-width: 100%;
  font-size: clamp(0.95rem, 3vw, 1.55rem);
}

.marketplace-item.sortable-drag .tile-points,
.marketplace-item.sortable-ghost .tile-points {
  right: 0.14rem;
  bottom: 0.12rem;
  font-size: clamp(0.42rem, 1.05vw, 0.56rem);
}

.tile.sortable-drag,
.tile.sortable-chosen,
.tile.sortable-fallback,
.marketplace-item.sortable-drag,
.marketplace-item.sortable-chosen,
.marketplace-item.sortable-fallback,
.marketplace-item.sortable-drag .tile,
.marketplace-item.sortable-chosen .tile,
.marketplace-item.sortable-fallback .tile {
  opacity: 1 !important;
  filter: none !important;
}

.tile.sortable-ghost,
.marketplace-item.sortable-ghost .tile {
  outline: 0;
  background: var(--drag-ghost-veil);
  color: transparent;
  text-shadow: none;
  box-shadow: none;
  opacity: 1;
}

.board-cell > .tile.sortable-ghost,
.board-cell > .marketplace-item.sortable-ghost {
  position: absolute !important;
  inset: 3px !important;
  z-index: 30 !important;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  margin: 0 !important;
  pointer-events: none;
  transform: none !important;
}

.board-cell > .tile.sortable-ghost {
  width: auto;
  max-width: 100%;
  font-size: clamp(0.95rem, 3vw, 1.55rem);
}

.board-cell > .tile.sortable-ghost.tile-active-placement,
.board-cell > .tile.sortable-ghost.tile-covering-placement {
  outline: 0;
  box-shadow: none;
}

.board-cell > .marketplace-item.sortable-ghost {
  display: grid;
  place-items: center;
}

.tile.sortable-ghost *,
.marketplace-item.sortable-ghost .tile * {
  visibility: hidden;
}

.marketplace-enter-1,
.marketplace-enter-2,
.marketplace-enter-3,
.marketplace-enter-4 {
  will-change: transform, opacity;
  animation-delay: var(--marketplace-delay, 0ms);
}

.marketplace-enter-1 {
  animation: marketplace-slide-in-low 620ms cubic-bezier(0.18, 0.84, 0.34, 1) both;
}

.marketplace-enter-2 {
  animation: marketplace-slide-in-high 660ms cubic-bezier(0.2, 0.82, 0.32, 1) both;
}

.marketplace-enter-3 {
  animation: marketplace-slide-in-tilt-left 640ms cubic-bezier(0.18, 0.84, 0.34, 1) both;
}

.marketplace-enter-4 {
  animation: marketplace-slide-in-tilt-right 680ms cubic-bezier(0.2, 0.82, 0.32, 1) both;
}

.tile:active {
  cursor: pointer;
}

.tile-active-placement {
  box-shadow:
    0 0 0 2px var(--orange),
    0 0 9px var(--orange-glow),
    inset 0 2px 0 var(--tile-top-sheen);
}

.tile-placement-error {
  animation: tile-flash 420ms ease-in-out 2;
}

.tile-remote-play {
  animation: remote-play-flash 1400ms ease-out 1;
}

@media (prefers-reduced-motion: reduce) {
  .tile-placement-error,
  .tile-remote-play {
    animation: none;
  }
}

.tile-shuffle-1,
.tile-shuffle-2,
.tile-shuffle-3,
.tile-shuffle-4,
.tile-enter-1,
.tile-enter-2,
.tile-enter-3,
.tile-enter-4 {
  position: relative;
  z-index: 5;
  will-change: transform;
  animation-delay: var(--shuffle-delay, 0ms);
}

.tile-enter-pending {
  opacity: 0;
  transform: translate(var(--shuffle-x, 115%), var(--shuffle-y, 0)) rotate(var(--tile-enter-rotation, 0deg));
}

.tile-shuffle-1,
.tile-enter-1 {
  animation: tile-shuffle-swing-left 520ms cubic-bezier(0.22, 0.8, 0.28, 1) both;
}

.tile-shuffle-2,
.tile-enter-2 {
  animation: tile-shuffle-swing-right 560ms cubic-bezier(0.2, 0.78, 0.32, 1) both;
}

.tile-shuffle-3,
.tile-enter-3 {
  animation: tile-shuffle-hop 540ms cubic-bezier(0.2, 0.82, 0.34, 1) both;
}

.tile-shuffle-4,
.tile-enter-4 {
  animation: tile-shuffle-slide 500ms cubic-bezier(0.18, 0.86, 0.34, 1) both;
}

.tile-redraw-exit-1,
.tile-redraw-exit-2,
.tile-redraw-exit-3,
.tile-redraw-exit-4 {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  will-change: transform, opacity;
  animation-delay: var(--redraw-delay, 0ms);
}

.tile-redraw-exit-1 {
  animation: tile-redraw-fall-left 1040ms cubic-bezier(0.32, 0.02, 0.72, 0.32) both;
}

.tile-redraw-exit-2 {
  animation: tile-redraw-fall-right 1100ms cubic-bezier(0.3, 0.04, 0.72, 0.34) both;
}

.tile-redraw-exit-3 {
  animation: tile-redraw-tumble-left 1080ms cubic-bezier(0.32, 0.03, 0.74, 0.34) both;
}

.tile-redraw-exit-4 {
  animation: tile-redraw-tumble-right 1060ms cubic-bezier(0.32, 0.03, 0.74, 0.34) both;
}

.tile-redraw-enter-1,
.tile-redraw-enter-2,
.tile-redraw-enter-3,
.tile-redraw-enter-4 {
  will-change: transform, opacity;
  animation-delay: var(--redraw-delay, 0ms);
}

.tile-redraw-enter-1 {
  animation: tile-redraw-slide-in-low 620ms cubic-bezier(0.18, 0.84, 0.34, 1) both;
}

.tile-redraw-enter-2 {
  animation: tile-redraw-slide-in-high 660ms cubic-bezier(0.2, 0.82, 0.32, 1) both;
}

.tile-redraw-enter-3 {
  animation: tile-redraw-slide-in-tilt-left 640ms cubic-bezier(0.18, 0.84, 0.34, 1) both;
}

.tile-redraw-enter-4 {
  animation: tile-redraw-slide-in-tilt-right 680ms cubic-bezier(0.2, 0.82, 0.32, 1) both;
}

.board .tile-covered-underlay,
.rules-example .tile-covered-underlay,
.rules-board-example .tile-covered-underlay {
  position: absolute;
  top: calc(3px + 0.18rem);
  left: calc(3px - 0.18rem);
  width: calc(100% - 6px);
  z-index: 1;
  opacity: 0.58;
  filter: saturate(0.7);
}

.board .tile-covering-placement,
.rules-example .tile-covering-placement,
.rules-board-example .tile-covering-placement {
  position: absolute;
  top: calc(3px - 0.18rem);
  left: calc(3px + 0.18rem);
  width: calc(100% - 6px);
  z-index: 2;
  box-shadow:
    inset 0 -0.22em 0 var(--tile-bottom-shade),
    -0.2rem 0.2rem 0 var(--shadow-soft);
}

.tile-stack-badge {
  position: absolute;
  top: 0.12rem;
  left: 0.12rem;
  min-width: 1.05rem;
  padding: 0.08rem 0.12rem;
  border-radius: 4px;
  background: var(--teal);
  color: var(--on-accent-ink);
  font: 800 clamp(0.44rem, 1.15vw, 0.58rem)/1 system-ui, sans-serif;
  text-align: center;
}

@keyframes tile-flash {
  0%,
  100% {
    box-shadow:
      inset 0 2px 0 var(--tile-top-sheen),
      inset 0 -0.22em 0 var(--tile-bottom-shade),
      0 2px 3px var(--shadow-soft);
  }

  50% {
    box-shadow:
      0 0 0 3px var(--coral),
      0 0 10px var(--orange-glow),
      inset 0 2px 0 var(--tile-top-sheen);
  }
}

@keyframes remote-play-flash {
  0% {
    transform: scale(0.82);
    box-shadow:
      inset 0 2px 0 var(--tile-top-sheen),
      inset 0 -0.22em 0 var(--tile-bottom-shade),
      0 0 0 0.35rem var(--teal);
  }

  45% {
    transform: scale(1.06);
    box-shadow:
      inset 0 2px 0 var(--tile-top-sheen),
      inset 0 -0.22em 0 var(--tile-bottom-shade),
      0 0 0 0.2rem var(--teal-deep);
  }

  100% {
    transform: scale(1);
    box-shadow:
      inset 0 2px 0 var(--tile-top-sheen),
      inset 0 -0.22em 0 var(--tile-bottom-shade),
      0 2px 3px var(--shadow-soft);
  }
}

@keyframes tile-shuffle-swing-left {
  0% {
    transform: translate(var(--shuffle-x), var(--shuffle-y)) rotate(-10deg);
  }

  52% {
    transform: translate(calc(var(--shuffle-x) * -0.16), calc(var(--shuffle-y) * -0.08)) rotate(7deg);
  }

  100% {
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-shuffle-swing-right {
  0% {
    transform: translate(var(--shuffle-x), var(--shuffle-y)) rotate(11deg);
  }

  48% {
    transform: translate(calc(var(--shuffle-x) * -0.14), calc(var(--shuffle-y) * 0.1)) rotate(-8deg);
  }

  100% {
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-shuffle-hop {
  0% {
    transform: translate(var(--shuffle-x), var(--shuffle-y)) rotate(-6deg);
  }

  45% {
    transform: translate(calc(var(--shuffle-x) * 0.35), calc(var(--shuffle-y) - 0.55rem)) rotate(8deg);
  }

  100% {
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-shuffle-slide {
  0% {
    transform: translate(var(--shuffle-x), var(--shuffle-y)) rotate(5deg);
  }

  58% {
    transform: translate(calc(var(--shuffle-x) * -0.1), calc(var(--shuffle-y) * -0.12)) rotate(-5deg);
  }

  100% {
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-redraw-fall-left {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }

  36% {
    transform: translate(calc(var(--redraw-fall-x) * 0.35), 0.7rem) rotate(-12deg);
  }

  100% {
    opacity: 0;
    transform: translate(var(--redraw-fall-x), 120vh) rotate(-42deg);
  }
}

@keyframes tile-redraw-fall-right {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }

  34% {
    transform: translate(calc(var(--redraw-fall-x) * 0.32), 0.45rem) rotate(13deg);
  }

  100% {
    opacity: 0;
    transform: translate(var(--redraw-fall-x), 120vh) rotate(48deg);
  }
}

@keyframes tile-redraw-tumble-left {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }

  28% {
    transform: translate(calc(var(--redraw-fall-x) * 0.22), -0.25rem) rotate(10deg);
  }

  100% {
    opacity: 0;
    transform: translate(var(--redraw-fall-x), 122vh) rotate(-110deg);
  }
}

@keyframes tile-redraw-tumble-right {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }

  30% {
    transform: translate(calc(var(--redraw-fall-x) * 0.2), -0.18rem) rotate(-9deg);
  }

  100% {
    opacity: 0;
    transform: translate(var(--redraw-fall-x), 122vh) rotate(112deg);
  }
}

@keyframes tile-redraw-slide-in-low {
  0% {
    opacity: 0;
    transform: translate(var(--redraw-enter-x), 0.55rem) rotate(-8deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-redraw-slide-in-high {
  0% {
    opacity: 0;
    transform: translate(var(--redraw-enter-x), -0.45rem) rotate(9deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-redraw-slide-in-tilt-left {
  0% {
    opacity: 0;
    transform: translate(var(--redraw-enter-x), 0.1rem) rotate(-14deg);
  }

  58% {
    transform: translate(-0.18rem, 0) rotate(5deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes tile-redraw-slide-in-tilt-right {
  0% {
    opacity: 0;
    transform: translate(var(--redraw-enter-x), -0.1rem) rotate(14deg);
  }

  58% {
    transform: translate(0.18rem, 0) rotate(-5deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes marketplace-slide-in-low {
  0% {
    opacity: 0;
    transform: translate(var(--marketplace-enter-x), 0.45rem) rotate(-7deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes marketplace-slide-in-high {
  0% {
    opacity: 0;
    transform: translate(var(--marketplace-enter-x), -0.4rem) rotate(8deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes marketplace-slide-in-tilt-left {
  0% {
    opacity: 0;
    transform: translate(var(--marketplace-enter-x), 0) rotate(-13deg);
  }

  58% {
    transform: translate(-0.15rem, 0) rotate(4deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes marketplace-slide-in-tilt-right {
  0% {
    opacity: 0;
    transform: translate(var(--marketplace-enter-x), 0) rotate(13deg);
  }

  58% {
    transform: translate(0.15rem, 0) rotate(-4deg);
  }

  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
}

@keyframes rainbow-tile-flow {
  0% {
    background-position: 0% 50%;
  }

  50% {
    background-position: 100% 50%;
  }

  100% {
    background-position: 0% 50%;
  }
}

.tile-points {
  position: absolute;
  right: 0.35rem;
  bottom: 0.45rem; /* clear of the tile's bottom inset shade band */
  color: var(--tile-points);
  font: 700 clamp(0.58rem, 2.2vw, 0.78rem)/1 system-ui, sans-serif;
}

.board .tile,
.rules-example .tile,
.rules-board-example .tile {
  width: calc(100% - 6px);
  max-width: 100%;
  font-size: clamp(0.95rem, 3vw, 1.55rem);
  cursor: default;
}

.board .tile-blank,
.rules-example .tile-blank,
.rules-board-example .tile-blank {
  background: var(--tile-face);
  box-shadow:
    inset 0 0 0 2px var(--tile-bottom-shade),
    inset 0 2px 0 var(--tile-top-sheen),
    0 2px 3px var(--shadow-soft);
}

.board .tile-movable {
  cursor: pointer;
}

.board .tile-points,
.rules-example .tile-points,
.rules-board-example .tile-points {
  right: 0.14rem;
  bottom: 0.24rem; /* clear of the smaller tiles' inset shade */
  font-size: clamp(0.42rem, 1.05vw, 0.56rem);
}

html.has-stored-player body main,
body.has-player main {
  align-content: start;
  gap: 0.75rem;
  padding-top: clamp(0.85rem, 2vw, 1.35rem);
}

html.has-stored-player body .masthead,
body.has-player .masthead {
  width: var(--play-width);
  row-gap: 0;
  column-gap: 1rem;
}

html.has-stored-player body .brand,
body.has-player .brand {
  --brand-scale: 1.9rem;
  margin-bottom: 0;
}

body.screen-setup.has-player main {
  align-content: start;
  padding-top: clamp(0.85rem, 2vw, 1.35rem);
}

body.screen-setup.has-player .game-controls {
  display: contents;
}

body.screen-setup.has-player .identity-bar {
  justify-self: end;
}

body.screen-setup.has-player .player-setup {
  grid-column: 1 / -1;
  justify-self: center;
  justify-items: center;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}

.redraw-tiles-button,
.pass-turn-button,
.concede-game-button {
  display: none;
}

body.screen-play .redraw-tiles-button,
body.screen-play .pass-turn-button,
body.screen-play .concede-game-button {
  display: inline-block;
}

.concede-game-button[hidden] {
  display: none;
}

body.game-over .rack,
body.game-over .rack-shuffle-button,
body.game-over .rack-controls,
body.game-over .redraw-confirm,
body.game-over .pass-confirm,
body.game-over .concede-confirm {
  display: none;
}

body.game-over .redraw-tiles-button,
body.game-over .pass-turn-button,
body.game-over .concede-game-button {
  display: none;
}

.rack-shuffle-button {
  display: none;
  position: absolute;
  /* Vertically centered on the RACK's top border (mirroring the "Your Tiles"
     label), not the dock's. Anchor positioning tracks the rack even when the
     Last Turn notice pushes it down; the plain values are the fallback
     (rack top = wrap's 0.6rem padding, rack right edge = wrap's padding). */
  top: -0.3rem;
  top: calc(anchor(--rack top) - 0.9rem);
  right: calc(clamp(0.5rem, 3vw, 0.85rem) + 0.7rem);
  right: calc(anchor(--rack right) + 0.7rem);
  z-index: 4;
  width: 1.8rem;
  min-width: 1.8rem;
  height: 1.8rem;
  min-height: 1.8rem;
  padding: 0.08rem;
  place-items: center;
  border-width: 2px;
  border-radius: 50%;
  background: var(--teal);
  color: var(--on-accent-ink);
  box-shadow: 0.12rem 0.12rem 0 var(--teal-deep);
}

/* Visual disc stays small (28.8px) to match the rack chrome, but the tappable
   hit-area is expanded to the >=40px touch-target minimum via an invisible
   centered ::before box. */
.rack-shuffle-button::before {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 2.5rem;
  height: 2.5rem;
  transform: translate(-50%, -50%);
}

.rack-shuffle-button:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

html[data-theme="dark"] .rack-shuffle-button:focus-visible {
  outline-color: var(--gold);
}

html[data-theme="dark"] .rack-shuffle-button {
  background: var(--sign-face);
  color: var(--cyan-neon);
  border-color: var(--cyan-neon);
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--teal-glow);
}

body.last-turn .rack-shuffle-button {
  top: calc(2.2rem + 0.75rem - 0.88rem);
}

body.screen-play .rack-shuffle-button {
  display: grid;
}

body.screen-play.game-over .rack-shuffle-button {
  display: none;
}

.rack-shuffle-button .ww-icon {
  width: 1.08rem;
  height: 1.08rem;
}

.rack-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 0.5rem;
}

.rack-controls .game-button {
  min-height: 2.5rem;
  padding: 0.55rem 0.95rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

#finish-placement-button {
  margin-left: auto;
}

/* Confirm dialogs: tilted-sign cards */
.redraw-confirm,
.pass-confirm,
.concede-confirm {
  display: none;
  width: 100%;
  max-width: 24rem;
  justify-self: center;
  justify-items: center;
  gap: 0.55rem;
  padding: 0.75rem;
  border: 2px solid var(--gold-deep);
  border-radius: 8px;
  background: var(--surface-raised);
  color: var(--ink);
  font: 800 0.9rem/1.25 system-ui, sans-serif;
  text-align: center;
  transform: rotate(-1deg);
  box-shadow: 0.18rem 0.22rem 0 var(--shadow-soft);
}

html[data-theme="dark"] .redraw-confirm,
html[data-theme="dark"] .pass-confirm,
html[data-theme="dark"] .concede-confirm {
  background: var(--sign-face);
  border-color: var(--gold);
  color: var(--ink-on-dark);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
}

body.confirm-redraw .redraw-confirm {
  display: grid;
}

body.confirm-pass .pass-confirm {
  display: grid;
}

body.confirm-concede .concede-confirm {
  display: grid;
}

.redraw-confirm-actions,
.pass-confirm-actions,
.concede-confirm-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.55rem;
}

.concede-game-control {
  display: grid;
  width: 100%;
  justify-items: start;
  gap: 0.55rem;
}

.concede-game-control[hidden] {
  display: none;
}

body.game-over .concede-game-control {
  display: none;
}

body.confirm-redraw #redraw-tiles-button,
body.confirm-pass #redraw-tiles-button,
body.confirm-pass #pass-turn-button,
body.confirm-redraw #pass-turn-button,
body.confirm-concede #redraw-tiles-button,
body.confirm-concede #pass-turn-button,
body.confirm-redraw #concede-game-button,
body.confirm-pass #concede-game-button,
body.confirm-concede #concede-game-button {
  display: none;
}

body.has-active-placement #redraw-tiles-button,
body.has-active-placement #pass-turn-button,
body.has-active-placement .pass-confirm {
  display: none;
}

.placement-action {
  display: none;
}

body.has-active-placement .placement-action {
  display: inline-block;
}

.game-message {
  position: relative;
  /* The callout IS the entire board-to-rack gap: negative block margins
     swallow the 1rem grid gaps (plus the rack's 0.25rem top margin) so the
     visible arrow touches the board above and the rack below with zero air,
     and the reservation is identical when empty (opacity handles hiding) —
     no jumping either way. */
  min-height: 2.6rem;
  width: var(--play-width);
  justify-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  /* -1rem swallows the grid gap above (board) exactly; the bottom swallows
     the gap + the rack's 0.25rem margin, backed off 1px so the band's own
     bottom border stays visible above the dock edge. Calibrate in LAYOUT
     coordinates (offsetTop), not bounding boxes — transforms inflate rects. */
  margin: -1rem auto calc(-1.25rem + 1px);
  /* plain full-width box (no arrow point): under the sticky dock the band's
     bottom can be covered by the rack edge, which reads fine for a box but
     amputated an arrow tip */
  padding: 0.4rem 0.85rem;
  background: var(--gold);
  color: var(--ink);
  font: 800 0.85rem/1.3 system-ui, sans-serif;
  text-align: center;
  opacity: 0;
  transform: translateY(-0.45rem);
  transition:
    opacity 180ms ease,
    transform 180ms ease;
  pointer-events: none;
}

html[data-theme="dark"] .game-message {
  background: var(--sign-face);
  color: var(--gold);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
  border: 1px solid var(--gold);
}

.game-message.has-message {
  opacity: 1;
  transform: translateY(0);
}

.game-message.message-exiting {
  opacity: 0;
  transform: translateY(-0.45rem);
}

.game-message.is-error {
  background: var(--coral);
  color: var(--ink-on-dark);
}

html[data-theme="dark"] .game-message.is-error {
  background: var(--sign-face);
  color: var(--coral);
  border-color: var(--coral);
  box-shadow: 0 0 calc(10px * var(--glow-strength)) var(--coral-glow);
}

body.screen-play:not(.is-my-turn) .game-message {
  background: var(--surface-raised);
  color: var(--ink-muted);
}

body.screen-play:not(.is-my-turn) .board {
  opacity: 0.82;
}

body.screen-play.spectator-mode .board {
  opacity: 1;
}

body.screen-play.spectator-mode .market-sign,
body.screen-play.spectator-mode .invite-link-panel,
body.screen-play.spectator-mode .last-turn-notice,
body.screen-play.spectator-mode .rack,
body.screen-play.spectator-mode .rack-shuffle-button,
body.screen-play.spectator-mode .rack-controls,
body.screen-play.spectator-mode .redraw-confirm,
body.screen-play.spectator-mode .pass-confirm,
body.screen-play.spectator-mode .concede-game-control,
body.screen-play.spectator-mode .potential-points-summary,
body.screen-play.spectator-mode #view-pool-button {
  display: none;
}

/* Spectators never see View Pool, so the log needs no separator above it. */
body.screen-play.spectator-mode .game-log {
  border-top: none;
  margin-top: 0;
  padding-top: 0;
}

body.screen-play:not(.is-my-turn) .tile-movable {
  cursor: not-allowed;
}

body.screen-play:not(.is-my-turn) #rack .tile-movable {
  cursor: pointer;
}

.game-button:disabled {
  cursor: not-allowed;
  opacity: 0.58;
  box-shadow: none;
}

/* Score strip: horizontal pill chips, "NOW PLAYING" tag on the active player */
.score-strip {
  width: var(--play-width);
  justify-self: center;
}

/* Always visible: sits in flow below the dock on narrow screens, becomes the
   fixed side panel at >=1280px. */
.game-sheet {
  width: 100%;
  max-width: var(--play-width); /* match the rack/board column */
  justify-self: center;
  margin-inline: auto;
  display: grid;
  gap: 0.75rem;
  padding-top: 0.6rem;
}

/* In-flow (below-dock) sheet wears the same counter treatment as the dock,
   full page width. The >=1280px fixed side panel keeps its own card chrome. */
@media (max-width: 1279.98px) {
  body.screen-play .game-sheet {
    padding: 0.6rem clamp(0.5rem, 3vw, 0.85rem) 0.9rem;
    border-top: 3px solid var(--teal);
    background: var(--surface);
    box-shadow: 0 -4px 12px var(--shadow-soft);
  }

  html[data-theme="dark"] body.screen-play .game-sheet {
    border-top-color: var(--cyan-neon);
    box-shadow: 0 0 calc(14px * var(--glow-strength)) var(--teal-glow);
  }
}

.game-state-panel {
  width: 100%;
  display: grid;
  gap: 0.75rem;
  padding: 0.85rem;
  border: 2px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface-raised);
  font: 700 0.95rem/1.2 system-ui, sans-serif;
  text-align: left;
}

/* Standalone stats bar: continues the sticky dock's cream counter flush below
   it (the -1rem cancels the .game-area grid gap), so only the rack + buttons
   pin and this row scrolls into view below the fold. */
.game-state-summary {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.35rem 0.9rem;
  width: 100%;
  max-width: var(--play-width);
  justify-self: center;
  margin-top: -1rem;
  padding: 0.55rem clamp(0.5rem, 3vw, 0.85rem) calc(0.7rem + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  font-size: 0.7rem;
}

.potential-points-kicker span {
  display: inline;
}

.game-state-kicker {
  color: var(--ink-muted);
  font: 800 0.66rem/1.2 system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.game-state-value {
  display: block;
  margin-top: 0.1rem;
  color: var(--ink);
  font-size: 0.85rem;
}

.game-state-value.negative {
  color: var(--coral);
}

.view-pool-button {
  justify-self: start;
  width: 6.25rem;
  min-height: 2.55rem;
  padding-inline: 0.85rem;
  font-size: 0.85rem;
  white-space: nowrap;
}

@media (max-width: 34rem) {
  .game-state-summary {
    gap: 0.3rem 0.6rem;
  }

  .potential-points-kicker span {
    display: block;
  }
}

.player-score-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem;
}

.player-score-row {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.32rem 0.7rem 0.32rem 0.4rem;
  border-radius: 999px;
  background: var(--surface-raised);
  box-shadow: 0 2px 4px var(--shadow-soft);
  font: 700 0.8rem/1.1 system-ui, sans-serif;
}

.player-score-row.current-turn {
  background: var(--sign-face);
  color: var(--gold);
  box-shadow:
    0 0 0 2px var(--gold),
    0 0 calc(10px * var(--glow-strength)) var(--gold-glow);
}

.player-score-row.conceded-player {
  background: var(--surface);
  color: var(--ink-muted);
  box-shadow: none;
  opacity: 0.75;
}

.player-score-name {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  overflow-wrap: anywhere;
}

.conceded-badge {
  display: inline-grid;
  place-items: center;
  padding: 0.14rem 0.42rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 12%, transparent);
  color: var(--ink-muted);
  font: 800 0.62rem/1 system-ui, sans-serif;
  text-transform: uppercase;
  vertical-align: middle;
}

.turn-badge {
  display: inline-grid;
  place-items: center;
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  /* day = dark MARKET board (calm inside the chip); night = electric red + glow */
  background: var(--hot-accent);
  color: var(--on-accent-ink);
  box-shadow: 0 0 calc(8px * var(--glow-strength)) var(--red-glow);
  font: 800 0.55rem/1.2 system-ui, sans-serif;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

.player-score-points {
  font: 800 0.85rem/1 system-ui, sans-serif;
}

.game-log-title {
  margin: 0;
  color: var(--ink-muted);
  font: 800 0.72rem/1.2 system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.game-log-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.word-score-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.word-score-item {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  max-width: 100%;
  padding: 0.18rem 0.42rem;
  border: 1px solid var(--teal);
  border-radius: 8px;
  background: color-mix(in srgb, var(--teal) 9%, transparent);
}

.word-score-word {
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 800;
}

.word-score-points {
  color: var(--teal-deep);
  font: 800 0.78rem/1 system-ui, sans-serif;
  white-space: nowrap;
}

.word-score-empty,
.game-log-empty {
  color: var(--ink-muted);
  font-size: 0.85rem;
}

.game-log {
  display: grid;
  gap: 0.55rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 2px solid var(--cell-border);
}

.game-log-result {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.5rem;
  align-items: baseline;
  color: var(--ink);
  font: 800 0.86rem/1.25 system-ui, sans-serif;
}

.game-log-result-label {
  color: var(--coral);
  font: 900 0.78rem/1.1 system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.game-log-result strong {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--ink);
  font: inherit;
}

.game-log-list {
  display: grid;
  gap: 0.45rem;
}

.game-log-entry {
  display: grid;
  gap: 0.4rem;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface-raised);
}

.game-log-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.55rem;
}

.game-log-turn {
  color: var(--ink-muted);
  font: 800 0.72rem/1.2 system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.game-log-player {
  overflow-wrap: anywhere;
}

/* Per-turn tally, pushed to the right edge of the heading row: points spent
   buying tiles (red, if any) then the words total (teal). */
.game-log-turn-tally {
  margin-left: auto;
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
}

.game-log-turn-spent {
  color: var(--hot-accent);
  font: 800 0.8rem/1.2 system-ui, sans-serif;
}

.game-log-turn-total {
  color: var(--teal-deep);
  font: 800 0.8rem/1.2 system-ui, sans-serif;
}

html[data-theme="dark"] .game-log-turn-total {
  color: var(--cyan-neon);
}

/* Net loss on the turn (spent more than scored) reads like the spend. */
.game-log-turn-total.negative {
  color: var(--hot-accent);
}

.pool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.4rem, 1fr));
  gap: 0.4rem;
}

.pool-letter {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 0.35rem;
  min-height: 2.25rem;
  padding: 0.42rem 0.55rem;
  border: 1px solid var(--cell-border);
  border-radius: 8px;
  background: var(--surface-raised);
}

.pool-letter-name {
  color: var(--ink);
  font: 900 1rem/1 system-ui, sans-serif;
}

.pool-blank-icon {
  display: inline-block;
  width: 1.08rem;
  height: 0.62rem;
  border-right: 0.14rem solid currentColor;
  border-bottom: 0.14rem solid currentColor;
  border-left: 0.14rem solid currentColor;
  transform: translateY(0.12rem);
}

.pool-letter-count {
  justify-self: end;
  color: var(--teal-deep);
  font: 800 0.9rem/1 system-ui, sans-serif;
}

@media (max-width: 640px) {
  :root {
    --play-width: min(72vh, calc(100vw - 0.5rem), 560px);
  }

  main {
    width: 100%;
    padding-inline: 0.1875rem;
  }

  html.has-stored-player body .masthead,
  body.has-player .masthead {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.45rem;
  }

  html.has-stored-player body .brand,
  body.has-player .brand {
    justify-self: start;
    --brand-scale: clamp(1.15rem, 6.5vw, 1.35rem);
  }

  html.has-stored-player body .game-controls,
  body.has-player .game-controls {
    justify-self: end;
    gap: 0.35rem;
  }

  html.has-stored-player body .identity-current,
  body.has-player .identity-current {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "icon name"
      "icon provider";
    align-items: center;
    gap: 0 0.35rem;
    text-align: left;
  }

  html.has-stored-player body .identity-current .ww-icon,
  body.has-player .identity-current .ww-icon {
    grid-area: icon;
  }

  html.has-stored-player body .identity-name,
  body.has-player .identity-name {
    grid-area: name;
    min-width: 0;
    line-height: 1.05;
  }

  html.has-stored-player body .identity-provider,
  body.has-player .identity-provider {
    grid-area: provider;
    min-width: 0;
    line-height: 1.05;
  }
}

@media (max-width: 520px) {

  .masthead {
    grid-template-columns: 1fr;
    justify-items: center;
  }

  .brand,
  .game-controls {
    justify-self: center;
  }

  .brand {
    --brand-scale: clamp(1.1rem, 9.5vw, 1.6rem);
  }

  html.has-stored-player body .masthead,
  body.has-player .masthead {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.45rem;
  }

  html.has-stored-player body .brand,
  body.has-player .brand {
    justify-self: start;
    --brand-scale: clamp(1.15rem, 6.5vw, 1.35rem);
  }

  html.has-stored-player body .game-controls,
  body.has-player .game-controls {
    justify-self: end;
    gap: 0.35rem;
  }

  body.screen-setup.has-player .identity-bar {
    justify-self: end;
  }

  .board {
    width: var(--play-width);
  }

  .rack {
    min-height: 3.8rem;
  }

}

@media (max-width: 400px) {
  html.has-stored-player body .brand,
  body.has-player .brand {
    --brand-scale: clamp(1.05rem, 6.5vw, 1.15rem);
  }

  html.has-stored-player body .masthead,
  body.has-player .masthead {
    column-gap: 0.3rem;
  }
}
