/* ===== Fonts ===== */
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700;800&family=Inter:wght@400;500;600;700;800&display=swap');

/* ===== Design tokens ===== */
:root {
  /* Backgrounds */
  --bg-deep: #08070a;                       /* warm near-black */
  --bg-panel: rgba(18, 14, 10, 0.62);       /* warm glass */
  --bg-panel-strong: rgba(18, 14, 10, 0.82);

  /* Gold palette (metallic gradient stops) */
  --gold-highlight: #f5e6c0;                /* champagne — top of gradient */
  --gold: #d4a574;                          /* mid metallic gold */
  --gold-deep: #8b6914;                     /* dark bronze — bottom of gradient */
  --gold-glow: rgba(212, 165, 116, 0.35);

  /* Text */
  --text-primary: #f0ebe0;                  /* warm off-white */
  --text-muted: rgba(240, 235, 224, 0.62);
  --text-subtle: rgba(240, 235, 224, 0.38);

  /* Borders */
  --border-soft: rgba(212, 165, 116, 0.16);
  --border-strong: rgba(212, 165, 116, 0.34);

  /* Danger (used by the in-game Exit X — coral red, reads as destructive
     without screaming, plays well with the warm gold-on-dark palette). */
  --danger: #e74c3c;
  --danger-glow: rgba(231, 76, 60, 0.35);

  /* Display gradient — used for title h1, final-total, etc. */
  --metallic-gradient: linear-gradient(180deg,
    var(--gold-highlight) 0%,
    var(--gold) 45%,
    var(--gold-deep) 100%);

  /* Type stacks */
  /* CJK fallbacks (ja/ko/zh) appended so localized UI never renders tofu.
     OS-native fonts only — zero webfont bytes shipped. */
  --font-display: 'Cinzel', Georgia, 'Times New Roman', "Hiragino Sans", "Yu Gothic UI", Meiryo, "Microsoft YaHei", "Malgun Gothic", "PingFang SC", "Noto Sans CJK JP", serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Hiragino Sans", "Yu Gothic UI", Meiryo, "Microsoft YaHei", "Malgun Gothic", "PingFang SC", "Noto Sans CJK JP", sans-serif;

  /* Era palette — sourced from the Field Report performance-chart swatches
     so era stripes on the final screen and any future surfaces (era pills,
     leaderboard tabs) stay in lockstep with the chart. Lighter end of the
     gradient; reads cleanly as a 4px stripe on dark rows. */
  --era-ancient:     #c8c0b3; /* warm slate */
  --era-medieval:    #d99e95; /* muted brick */
  --era-renaissance: #b9cba1; /* sage olive */
  --era-modern:      #a3b8cc; /* dusty steel blue */
}

/* ===== Reset / base ===== */
* {
  box-sizing: border-box;
  /* Disable double-tap-to-zoom on iOS WebKit (which deprecated honoring user-scalable=no).
     `manipulation` keeps panning + pinch (which we want for the map) but kills double-tap zoom. */
  touch-action: manipulation;
}
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  background: var(--bg-deep);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-feature-settings: 'cv02', 'cv03', 'cv11';
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
body {
  overflow: hidden;
}
/* Leaflet needs touch-action: none on its container to handle pinch correctly */
.leaflet-container {
  touch-action: none;
}
/* A-Frame's look-controls reads touchmove deltas to drive yaw + pitch on the
   panorama. iOS Safari, with the universal `touch-action: manipulation` rule
   above, claims vertical drags as candidate page-pans BEFORE delivering
   touchmove deltas to the scene listener — yaw still works (horizontal pans
   are recognized as cross-axis), but pitch is silently locked. Setting
   `touch-action: none` on the scene + canvas tells iOS to deliver every
   touchmove unmodified. (Walk-F06, 2026-05-02 mobile audit.) */
a-scene, a-scene canvas, .a-canvas {
  touch-action: none;
}
input, textarea {
  -webkit-user-select: text;
  user-select: text;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: none;
  background: none;
  padding: 0;
}

a { color: var(--gold); }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(255, 255, 255, 0.06);
  color: var(--gold-highlight);
  padding: 1px 6px;
  border-radius: 4px;
}

/* ===== Screen routing ===== */
.screen {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.screen.active {
  display: block;
}

/* ===== TITLE screen ===== */
#screen-title {
  background: var(--bg-deep);
  position: relative;
  overflow: hidden;
}
.title-bg-stack {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.title-bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 350ms ease-in-out;
  will-change: opacity, transform;
  pointer-events: none;
  background: var(--bg-deep);
}
.title-bg-video.active {
  opacity: 1;
  /* Subtle cinematic drift layered over the native video motion. 10s matches
     the video duration so the zoom is at peak (1.04) exactly at the cut. */
  animation: title-bg-drift 10s ease-in-out forwards;
}
@keyframes title-bg-drift {
  from { transform: scale(1.0); }
  to   { transform: scale(1.04); }
}
.title-bg-flash {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #ffffff;
  opacity: 0;
  pointer-events: none;
  transition: opacity 350ms ease-in-out;
}
.title-bg-flash.active {
  opacity: 1;
}
.title-vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse at center,
      transparent 0%,
      rgba(8, 7, 10, 0.55) 70%,
      rgba(8, 7, 10, 0.95) 100%),
    linear-gradient(180deg,
      rgba(8, 7, 10, 0.30) 0%,
      rgba(8, 7, 10, 0.00) 30%,
      rgba(8, 7, 10, 0.00) 55%,
      rgba(8, 7, 10, 0.85) 100%);
}
.title-content {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  /* Bottom-anchored stack — wordmark + stat + CTA row + About read as
     a "footer chrome" leaving the cinematic background to dominate the
     upper portion of the page. */
  justify-content: flex-end;
  align-items: center;
  text-align: center;
  padding: 24px 24px calc(56px + env(safe-area-inset-bottom, 0px));
}
/* Wordmark zone — wraps the H1 + high-score so we can paint a soft dark
   radial vignette directly behind the title. Keeps the gradient gold legible
   against bright backgrounds (sunset/explosion bgs) without darkening the
   whole page. */
.title-wordmark-zone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 18px 28px 6px;
}
.wordmark-vignette {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 130%;
  height: 220%;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(ellipse at center,
    rgba(8, 7, 10, 0.55) 0%,
    rgba(8, 7, 10, 0.40) 35%,
    rgba(8, 7, 10, 0.18) 60%,
    rgba(8, 7, 10, 0.00) 80%);
  filter: blur(8px);
}
.title-content h1 {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  /* Bumped from clamp(38px, 9vw, 84px) for more "epic" presence. */
  font-size: clamp(44px, 10vw, 104px);
  margin: 0 0 6px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 0.95;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 2px 24px rgba(212, 165, 116, 0.15);
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.5));
}
/* Tier A2: highscore medallion — small horizontal pill, two states.
   Returning user (.is-best) gets bright gold; first-time user
   (.is-firstrun) gets a slightly more muted invitation tone so the
   "Travel to N scenes" copy reads as encouragement, not stat. */
.title-highscore {
  position: relative;
  z-index: 1;
  /* Centers the flair in the gap between the Private-Beta pill (above)
     and the CTA row (below). Top is 18px because the wordmark-zone
     contributes 6px bottom padding above the flair (visual gap = 24px),
     and bottom is a clean 24px to match. Hidden by default; only
     renders when the player has a personal best or first-run nudge. */
  margin: 18px 0 24px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 8px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.16), rgba(212, 165, 116, 0.04));
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.10),
    0 4px 14px rgba(0, 0, 0, 0.45);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.7);
  white-space: nowrap;
}
.title-highscore[hidden] { display: none; }
.title-highscore-icon {
  width: 14px; height: 14px; flex: 0 0 14px;
  color: var(--gold);
  filter: drop-shadow(0 0 6px var(--gold-glow));
}
.title-highscore-label { color: var(--text-muted); font-weight: 500; }
.title-highscore-sep {
  color: var(--text-subtle);
  margin: 0 -2px;
}
.title-highscore-value {
  color: var(--gold-highlight);
  font-weight: 700;
  letter-spacing: 0.14em;
}
/* Personal-best variant reads as an opaque metallic medal: warm gold
   ribbon gradient (no background-blur transparency), dark text for
   contrast on the gold, subtle bevel via top/bottom inset shadows so
   the pill feels physical instead of glassy. The .is-firstrun and
   default .title-highscore states stay glass-translucent. */
.title-highscore.is-best {
  background: linear-gradient(180deg, #e8c285 0%, #b58450 50%, #8a5d2d 100%);
  border-color: #f5e6c0;
  color: #2a1a0c;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 200, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.35),
    0 4px 18px rgba(0, 0, 0, 0.5),
    0 0 14px color-mix(in srgb, var(--gold) 50%, transparent);
  text-shadow: 0 1px 0 rgba(255, 240, 200, 0.45);
}
.title-highscore.is-best .title-highscore-icon {
  color: #2a1a0c;
  filter: drop-shadow(0 1px 0 rgba(255, 240, 200, 0.5));
}
.title-highscore.is-best .title-highscore-label {
  color: rgba(42, 26, 12, 0.72);
  font-weight: 600;
}
.title-highscore.is-best .title-highscore-sep {
  color: rgba(42, 26, 12, 0.45);
}
.title-highscore.is-best .title-highscore-value {
  background: none;
  -webkit-background-clip: unset;
  background-clip: unset;
  color: #1a0e04;
  filter: none;
  font-weight: 800;
}
.title-highscore.is-firstrun {
  opacity: 0.85;
}
@media (max-width: 480px) {
  .title-highscore { font-size: 10px; padding: 4px 10px 4px 7px; letter-spacing: 0.16em; }
  .title-highscore-icon { width: 12px; height: 12px; flex-basis: 12px; }
}
.tagline {
  font-family: var(--font-display);
  font-size: clamp(13px, 2vw, 18px);
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  text-align: center;
  /* Stronger contrast against the rotating cinematic backgrounds — the
     old --text-muted (62% opacity) was washing out on bright frames.
     Light champagne with a deeper text-shadow halo. */
  color: rgba(245, 230, 200, 0.92);
  /* Symmetric vertical margin so the tagline sits visually centered
     between the personal-best pill (above) and the Daily Challenge
     button (below). Combined with .btn-daily margin-top: 14px this
     gives ~24px above, ~24px below. */
  margin: 18px 0 10px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85), 0 2px 14px rgba(0, 0, 0, 0.7);
}
.title-beta-pill {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: rgba(245, 230, 200, 0.7);
  /* Tight to the wordmark above (the user's "much closer to WHERE IN
     TIME"), zero bottom margin — the wordmark-zone owns the gap below. */
  margin: 4px 0 0;
  padding: 4px 14px;
  display: inline-block;
  border: 1px solid rgba(212, 165, 116, 0.34);
  border-radius: 999px;
  background: rgba(18, 12, 7, 0.5);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
}
.hint {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--text-subtle);
  margin: 22px 0 0;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.7);
}
.headphones-hint {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 8px;
  letter-spacing: 0.30em;
  margin-top: 12px;
}
.headphones-hint svg {
  width: 14px;
  height: 14px;
  color: var(--gold);
  opacity: 0.85;
}
@media (pointer: fine) {
  .headphones-hint { display: inline-flex; }
}

/* ===== Title-screen era selector (below Start button) =====
   Layout: a bold "ERA" section header on top (gold metallic, flanked by
   thin gold rules for a cinematic act-break feel), then a row of pills
   underneath. Each pill stacks an era name on top of a smaller, lower-
   opacity year range. */
.era-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
}
.era-block-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-family: var(--font-display);
  font-size: clamp(14px, 1.6vw, 17px);
  font-weight: 700;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  /* Gold metallic gradient — visually rhymes with the wordmark + Start
     button so the section header reads as part of the same lockup. */
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 2px 14px rgba(212, 165, 116, 0.18);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55));
  /* Trim the trailing letter-spacing on the right so the rules sit
     symmetrically around the label. */
  padding-left: 0.42em;
}
.era-block-label::before,
.era-block-label::after {
  content: "";
  display: block;
  width: clamp(28px, 6vw, 56px);
  height: 1px;
  background: linear-gradient(90deg,
    rgba(212, 165, 116, 0) 0%,
    var(--gold) 50%,
    rgba(212, 165, 116, 0) 100%);
}
@media (max-width: 380px) {
  .era-block-label { gap: 10px; letter-spacing: 0.36em; }
  .era-block-label::before,
  .era-block-label::after { width: 22px; }
}
.era-segments {
  display: inline-flex;
  align-items: stretch;
  padding: 4px;
  background: rgba(18, 14, 10, 0.62);
  border: 1px solid var(--border-soft);
  /* Match Start button's border-radius family but stay pill-like —
     12px on the container, 10px on the active pill. */
  border-radius: 14px;
  gap: 2px;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
}
.era-seg {
  font-family: var(--font-display);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 8px 14px;
  min-width: 92px;
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}
.era-seg .era-name {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
  line-height: 1.05;
}
/* Tier B1: era pills sell scope. Three lines now —
   name (top, bold) → count (mid, gold) → landmarks (bottom, muted).
   Old `.era-range` rule kept for back-compat in case anything else
   references it; the new pills don't render that span. */
.era-seg .era-range {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-subtle);
  opacity: 0.78;
  line-height: 1;
  white-space: nowrap;
}
.era-seg .era-count {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.9;
  line-height: 1;
  white-space: nowrap;
  margin-top: 1px;
}
.era-seg .era-landmarks {
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-subtle);
  opacity: 0.72;
  line-height: 1.05;
  white-space: nowrap;
  margin-top: 2px;
  /* Allow narrow widths to cap the visual width so "Magna Carta · Hattin"
     doesn't push the active pill wider than its neighbours. */
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (hover: hover) {
  .era-seg:hover { background: rgba(245, 230, 192, 0.04); }
  .era-seg:hover .era-name { color: var(--gold-highlight); }
  .era-seg:hover .era-range,
  .era-seg:hover .era-landmarks { color: var(--text-muted); opacity: 0.9; }
  .era-seg:hover .era-count { color: var(--gold-highlight); }
}
.era-seg.active {
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.22), rgba(212, 165, 116, 0.10));
  border-color: var(--border-strong);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.14),
    0 0 14px var(--gold-glow);
}
.era-seg.active .era-name { color: var(--gold-highlight); }
.era-seg.active .era-range,
.era-seg.active .era-landmarks { color: var(--text-muted); opacity: 0.95; }
.era-seg.active .era-count { color: var(--gold-highlight); opacity: 1; }
@media (max-width: 640px) {
  .era-segments {
    flex-wrap: wrap;
    justify-content: center;
    max-width: min(96vw, 380px);
  }
  .era-seg { min-width: 0; flex: 1 1 calc(50% - 4px); padding: 7px 10px; }
  .era-seg .era-name { font-size: 10px; letter-spacing: 0.16em; }
  .era-seg .era-range,
  .era-seg .era-count { font-size: 8.5px; letter-spacing: 0.08em; }
  .era-seg .era-landmarks { font-size: 8px; letter-spacing: 0.04em; }
}
@media (max-width: 380px) {
  .era-seg { flex-basis: 100%; }
  .era-seg .era-landmarks { max-width: none; }
}

/* ===== Title-screen share section (bottom-right) — ERA-style header
   stacked above the icon pill so the label gets the same cinematic
   "act-break" treatment as the era picker. ===== */
.title-share-block {
  position: absolute;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 20px);
  right: max(env(safe-area-inset-right, 0px), 20px);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.title-share-block-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-family: var(--font-display);
  font-size: clamp(12px, 1.3vw, 14px);
  font-weight: 700;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 2px 14px rgba(212, 165, 116, 0.18);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55));
  padding-left: 0.42em;
}
.title-share-block-label::before,
.title-share-block-label::after {
  content: "";
  display: block;
  width: clamp(22px, 4vw, 40px);
  height: 1px;
  background: linear-gradient(90deg,
    rgba(212, 165, 116, 0) 0%,
    var(--gold) 50%,
    rgba(212, 165, 116, 0) 100%);
}
.title-share {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: rgba(18, 14, 10, 0.55);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
}
.share-btn {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease, transform 180ms ease;
}
@media (hover: hover) {
  .share-btn:hover {
    color: var(--gold-highlight);
    background: rgba(245, 230, 192, 0.08);
  }
}
.share-btn:active { transform: scale(0.92); }
.share-btn svg { width: 18px; height: 18px; }
/* Copy icon (chain link) is harder to recognize than the others — bump it
   slightly so it reads as an action rather than decoration. */
.share-btn-copy svg { width: 20px; height: 20px; }
@media (max-width: 600px) {
  .title-share-block-label { font-size: 11px; letter-spacing: 0.36em; gap: 8px; }
  .title-share-block-label::before,
  .title-share-block-label::after { width: 18px; }
  .title-share { padding: 6px; gap: 6px; }
}
@media (max-width: 480px) {
  .title-share-block { bottom: calc(env(safe-area-inset-bottom, 0px) + 12px); right: max(env(safe-area-inset-right, 0px), 12px); gap: 8px; }
  .share-btn { width: 32px; height: 32px; }
  .share-btn svg { width: 16px; height: 16px; }
  .share-btn-copy svg { width: 17px; height: 17px; }
}
.desktop-hint {
  display: none;
  margin-top: 10px;
  font-size: 10px;
  letter-spacing: 0.28em;
  color: var(--text-subtle);
  opacity: 0.85;
}
.desktop-hint kbd {
  display: inline-block;
  padding: 1px 6px;
  margin: 0 2px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9px;
  font-weight: 600;
  background: rgba(245, 230, 192, 0.06);
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  color: var(--gold-highlight);
  letter-spacing: 0.04em;
}
@media (pointer: fine) {
  .desktop-hint { display: inline-block; }
}

/* ===== Settings popovers (title screen + in-game share styling) ===== */
.settings-popover {
  width: 280px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-soft);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
}
.settings-popover[hidden] { display: none; }
.settings-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.settings-section + .settings-section {
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.settings-heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}

/* Music row (icon button + volume slider) */
.settings-music {
  display: flex;
  align-items: center;
  gap: 10px;
}
.music-toggle {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--border-soft);
  color: var(--gold-highlight);
  cursor: pointer;
  border-radius: 50%;
  transition: color 180ms ease, background 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  .music-toggle:hover { background: rgba(245, 230, 192, 0.08); color: var(--gold); border-color: var(--border-strong); }
}
.music-toggle svg { width: 16px; height: 16px; }
.music-toggle[data-muted="true"] .ico-speaker { display: none; }
.music-toggle[data-muted="false"] .ico-muted { display: none; }

/* HUD mute toggle (chip-shaped, sits next to the cog in #global-hud-bl
   and #hud-bl). Inherits the .glass-chip + .icon-only sizing — only the
   icon-swap rules and the muted-state visual emphasis live here. */
.hud-mute-toggle .ico-muted { display: none; }
.hud-mute-toggle[data-muted="true"] .ico-speaker { display: none; }
.hud-mute-toggle[data-muted="true"] .ico-muted { display: block; }
.hud-mute-toggle[data-muted="true"] {
  background: rgba(231, 76, 60, 0.10);
  border-color: rgba(231, 76, 60, 0.45);
  color: var(--danger, #e74c3c);
}
@media (hover: hover) {
  .hud-mute-toggle[data-muted="true"]:hover {
    background: rgba(231, 76, 60, 0.20);
    border-color: rgba(231, 76, 60, 0.70);
    color: #ff6f5f;
  }
}
.music-volume {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  background: linear-gradient(90deg,
    var(--gold) 0%,
    var(--gold) var(--vol, 40%),
    rgba(120, 100, 80, 0.3) var(--vol, 40%),
    rgba(120, 100, 80, 0.3) 100%);
  border-radius: 999px;
  outline: none;
  cursor: pointer;
  transition: opacity 180ms ease;
}
.music-toggle[data-muted="true"] + .music-volume { opacity: 0.4; }
.music-volume::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px;
  background: var(--gold-highlight);
  border: 2px solid var(--gold);
  border-radius: 50%;
  cursor: grab;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}
.music-volume::-moz-range-thumb {
  width: 14px; height: 14px;
  background: var(--gold-highlight);
  border: 2px solid var(--gold);
  border-radius: 50%;
  cursor: grab;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}

/* ===== HUD volume vertical slider (revealed on hover/tap of mute chip) =====
   Both .hud-mute-toggle chips live in bottom-corner HUDs (#hud-bl in-game,
   #global-hud-bl on title), so the slider rises ABOVE the chip rather than
   dropping below it. Implementation: a horizontal range input rotated -90deg
   so it reads vertically, with a margin-bottom that compensates for the
   width-vs-height swap caused by the rotation. */
.hud-mute-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
/* Fix #3 (R2): hover-bridge — invisible hit area extending upward from the
   chip into the slot the rotated slider occupies. Without this, the cursor
   travels through the 8px gap + 45px margin-bottom dead zone between the
   chip and slider, loses :hover, and the slider hides before the cursor
   reaches it. The bridge keeps :hover continuous on .hud-mute-wrap. */
.hud-mute-wrap::before {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 60px;
  height: 70px; /* gap (8px) + margin-bottom (45px) + slack */
  pointer-events: none;
}
@media (hover: hover) {
  .hud-mute-wrap:hover::before {
    pointer-events: auto;
  }
}
.hud-volume-vertical {
  position: absolute;
  /* Position above the chip, centered horizontally over it. */
  bottom: calc(100% + 8px);
  left: 50%;
  /* Rotated -90deg so the 90px-wide slider reads as a 90px-tall vertical bar.
     transform-origin is center so the rotated rect stays centered on its pre-
     rotation position. The translate(-50%) handles horizontal centering on the
     chip; translateY moves the rotated rect upward into its visual slot. */
  width: 90px;
  height: 6px;
  transform: translateX(-50%) translateY(4px) rotate(-90deg);
  transform-origin: center center;
  /* margin-bottom of 45px (half of 90px width) reserves vertical space so the
     rotated bar visually sits above the chip with some breathing room. */
  margin-bottom: 45px;
  -webkit-appearance: none;
  appearance: none;
  /* Transparent padding extends the touchable hit area without changing the
     visual track width. With width:90px / height:6px content + padding 15px 6px,
     the input's padding-box is 102px × 36px → rotated to 36px × 102px on screen,
     comfortably above iOS's 44pt minimum thumb-zone (the thumb itself sits in
     the center of the bar and is 24px). content-box keeps the visible track
     width at 90px. */
  padding: 15px 6px;
  box-sizing: content-box;
  background: linear-gradient(90deg,
    var(--gold) 0%,
    var(--gold) var(--vol, 40%),
    rgba(120, 100, 80, 0.4) var(--vol, 40%),
    rgba(120, 100, 80, 0.4) 100%);
  /* Constrain the background to the content (track) area only — without this,
     the gradient would also paint the 12px padding rows above/below the track. */
  background-clip: content-box;
  border-radius: 999px;
  outline: none;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 50;
  /* Subtle dark backdrop so the bar reads against any panorama. */
  box-shadow: 0 0 0 6px rgba(20, 14, 8, 0.55), 0 6px 20px rgba(0, 0, 0, 0.55);
}
.hud-volume-vertical::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 24px; height: 24px;
  background: var(--gold-highlight);
  border: 2px solid var(--gold);
  border-radius: 50%;
  cursor: grab;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6);
}
.hud-volume-vertical::-moz-range-thumb {
  width: 24px; height: 24px;
  background: var(--gold-highlight);
  border: 2px solid var(--gold);
  border-radius: 50%;
  cursor: grab;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6);
}
/* Reveal: desktop hover (any pointer over chip OR slider keeps it visible). */
@media (hover: hover) {
  .hud-mute-wrap:hover .hud-volume-vertical,
  .hud-volume-vertical:hover,
  .hud-volume-vertical:focus {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0) rotate(-90deg);
  }
}
/* Reveal: mobile tap (JS adds .is-revealed class for 3s after chip tap). */
.hud-mute-wrap.is-revealed .hud-volume-vertical {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0) rotate(-90deg);
}
/* Muted state: slider stays grabbable when the wrap is hovered (desktop) or
   revealed (touch) so the user can drag the thumb back up to unmute. Slightly
   dimmed so the visual still reads "muted" while remaining a usable control. */
@media (hover: hover) {
  .hud-mute-wrap:hover .hud-mute-toggle[data-muted="true"] ~ .hud-volume-vertical,
  .hud-mute-toggle[data-muted="true"] ~ .hud-volume-vertical:hover,
  .hud-mute-toggle[data-muted="true"] ~ .hud-volume-vertical:focus {
    opacity: 0.7;
  }
}
.hud-mute-wrap.is-revealed .hud-mute-toggle[data-muted="true"] ~ .hud-volume-vertical {
  opacity: 0.7;
}

/* Settings toggle row — label + iOS-style switch */
.settings-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  cursor: pointer;
  padding: 4px 2px;
}
.toggle-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.toggle-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
.toggle-track {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  background: rgba(120, 100, 80, 0.32);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  transition: background 180ms ease, border-color 180ms ease;
}
.toggle-thumb {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 16px;
  height: 16px;
  background: var(--text-primary);
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  transition: transform 180ms cubic-bezier(0.32, 0.72, 0, 1), background 180ms ease;
}
.toggle-input:checked + .toggle-track {
  background: linear-gradient(180deg, var(--gold), var(--gold-deep));
  border-color: var(--gold);
}
.toggle-input:checked + .toggle-track .toggle-thumb {
  transform: translateX(16px);
  background: var(--gold-highlight);
}
.toggle-input:focus-visible + .toggle-track {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* Action buttons (Restart) */
.settings-action {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 14px;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease;
}
@media (hover: hover) {
  .settings-action:hover {
    background: rgba(245, 230, 192, 0.10);
    border-color: var(--border-strong);
    color: var(--gold);
  }
}

/* Language switcher — native <select> styled as a glass-chip. Stacked
   caption + full-width control so long endonyms fit the 280px popover.
   Native control = free keyboard + screen-reader support. */
.settings-lang-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
}
.settings-lang-caption {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-primary);
}
.settings-lang-control {
  position: relative;
  display: block;
}
.settings-lang-select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 100%;
  min-height: 44px;
  padding: 10px 36px 10px 12px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease;
}
.settings-lang-select::-ms-expand { display: none; }
.settings-lang-select option {
  color: #f3e7c8;
  background: #17120c;
}
@media (hover: hover) {
  .settings-lang-select:hover {
    background: rgba(245, 230, 192, 0.10);
    border-color: var(--border-strong);
  }
}
.settings-lang-select:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}
.settings-lang-chevron {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  color: var(--gold-highlight);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .settings-lang-select { transition: none; }
}

/* Title-screen settings popover positioning */
#title-hud-tr {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  right: max(env(safe-area-inset-right, 0px), 16px);
  z-index: 3;
  display: flex;
  flex-direction: row-reverse;     /* settings cog on right, sign-in pill to its left */
  align-items: center;
  gap: 10px;
}

/* Sign-in pill (next to settings cog on title screen).
   Designed to be visibly larger and more inviting than the settings cog so
   it reads as the primary OAuth surface — the cog stays at 44x44, this chip
   is taller and shows a row of provider logos below the label. */
.sign-in-chip {
  border-radius: 14px;
  padding: 10px 16px;
  min-height: 56px;
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.22), rgba(212, 165, 116, 0.08));
  border: 1px solid var(--border-strong);
  color: var(--gold-highlight);
  letter-spacing: 0.18em;
  white-space: normal;
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.10),
    0 8px 28px rgba(0, 0, 0, 0.45);
}
@media (hover: hover) {
  .sign-in-chip:hover {
    background: linear-gradient(180deg, rgba(212, 165, 116, 0.34), rgba(212, 165, 116, 0.14));
    border-color: var(--gold);
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.18),
      0 8px 24px rgba(0, 0, 0, 0.5),
      0 0 22px var(--gold-glow);
  }
}
.sign-in-stack {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  line-height: 1;
}
.sign-in-label {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.sign-in-providers {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.provider-mini {
  width: 14px;
  height: 14px;
  display: inline-block;
  opacity: 0.92;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
@media (max-width: 480px) {
  .sign-in-chip {
    padding: 0;
    width: 48px;
    height: 48px;
    min-height: 48px;
    justify-content: center;
  }
  .sign-in-label { display: none; }
  .sign-in-providers { display: none; }
  /* On tiny screens, fall back to the legacy person icon for visual hint. */
  .sign-in-stack::before {
    content: '';
    width: 18px;
    height: 18px;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/><circle cx='12' cy='7' r='4'/></svg>") center/contain no-repeat;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/><circle cx='12' cy='7' r='4'/></svg>") center/contain no-repeat;
    color: var(--gold-highlight);
  }
}

/* Clerk UserButton mount — sits where the Sign-in pill was when signed in */
.user-button-mount {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.user-button-mount[hidden] { display: none; }
/* Author CSS sets `display: inline-flex` on .glass-chip (the SIGN IN
   pill) and .info-tooltip-trigger (the "?" help button). Class
   selectors out-specify the UA's `[hidden] { display: none }` rule, so
   without these explicit overrides setAttribute('hidden', '') from
   syncUI() leaves both buttons visible after sign-in — the bug Eric
   hit on prod after Tier 5 shipped. Same pattern as
   .user-button-mount[hidden] above. */
.glass-chip[hidden] { display: none; }
.info-tooltip-trigger[hidden] { display: none; }
/* Global bottom-left HUD (settings cog + exit-fullscreen X). Mirrors the
   game-screen #hud-bl position for visual consistency across all screens.
   Hidden when body.in-game (game has its own #hud-bl with extras). */
#global-hud-bl {
  position: fixed;
  /* Override .hud-corner's `top: 16px` — without this, top + bottom both
     apply and the container stretches the full viewport height, parking
     the chips at vertical center instead of bottom-left. */
  top: auto;
  bottom: max(env(safe-area-inset-bottom, 0px), 16px);
  left: max(env(safe-area-inset-left, 0px), 16px);
  flex-direction: row;
  align-items: center;
  gap: 10px;
  z-index: 35;
}
body.in-game #global-hud-bl { display: none; }

/* Fullscreen toggle: shows the "enter" icon by default, swaps to "exit"
   icon (red) when document is actually in fullscreen. */
/* Fullscreen toggle (any button with .fs-toggle): shows the "enter" icon
   by default, swaps to "exit" icon (red) when document is in fullscreen. */
.fs-toggle .ico-exit-fs { display: none; }
body.is-fullscreen .fs-toggle .ico-enter-fs { display: none; }
body.is-fullscreen .fs-toggle .ico-exit-fs { display: block; }
body.is-fullscreen .fs-toggle {
  background: rgba(231, 76, 60, 0.15);
  border-color: rgba(231, 76, 60, 0.6);
  color: var(--danger, #e74c3c);
}
@media (hover: hover) {
  body.is-fullscreen .fs-toggle:hover {
    background: rgba(231, 76, 60, 0.28);
    border-color: rgba(231, 76, 60, 0.85);
    color: #ff6f5f;
  }
}

/* Prominent in-game Exit button: filled coral red with text label so it
   reads as "leave the game" and is visibly different from the title's
   utility-chip-shaped fullscreen toggle that occupies the same corner. */
.btn-exit-game {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px 10px 12px;
  min-height: 44px;
  background: linear-gradient(180deg, rgba(231, 76, 60, 0.95), rgba(192, 57, 43, 0.95));
  border: 1px solid rgba(255, 110, 95, 0.85);
  border-radius: 10px;
  color: #fff;
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 700;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 4px 16px rgba(231, 76, 60, 0.40),
    0 0 0 1px rgba(0, 0, 0, 0.20);
  transition: background 160ms ease, transform 120ms ease, box-shadow 160ms ease;
}
.btn-exit-game svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
@media (hover: hover) {
  .btn-exit-game:hover {
    background: linear-gradient(180deg, rgba(241, 96, 80, 1), rgba(212, 77, 63, 1));
    transform: translateY(-1px);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.22),
      0 6px 20px rgba(231, 76, 60, 0.55),
      0 0 0 1px rgba(0, 0, 0, 0.20);
  }
}
.btn-exit-game:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Title settings popover — anchored to the bottom-left cog, opens UP */
#title-settings-panel {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 0;
  transform-origin: bottom left;
  animation: settings-pop 220ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* ===== Buttons ===== */
.btn-primary {
  display: inline-block;
  min-width: 220px;
  min-height: 56px;
  padding: 16px 56px;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  background: linear-gradient(180deg, rgba(30, 22, 14, 0.92), rgba(14, 10, 6, 0.94));
  color: var(--gold-highlight);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.08),
    0 8px 28px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(0, 0, 0, 0.4);
  transition:
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 220ms ease,
    box-shadow 220ms ease,
    opacity 0.2s;
  user-select: none;
}
@media (hover: hover) {
  .btn-primary:hover {
    transform: translateY(-1px);
    border-color: var(--gold);
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.16),
      0 0 24px var(--gold-glow),
      0 8px 28px rgba(0, 0, 0, 0.6);
  }
}
.btn-primary:active { transform: translateY(1px); }
.btn-primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  background: linear-gradient(180deg, rgba(30, 22, 14, 0.6), rgba(14, 10, 6, 0.6));
  border-color: var(--border-soft);
  color: var(--text-subtle);
}

/* Compact gold-gradient pill — same metallic body as .btn-primary, narrowed
   for use as an inline chip next to full-size CTAs. Used on the title-page
   era selector (sits beside Daily/Casual columns, top-aligned).
   Width is FIXED (not min-width) so longer era names like "RENAISSANCE"
   don't expand the pill and shift the surrounding layout sideways. */
.btn-primary.btn-primary-compact {
  width: 85px;
  min-width: 0;          /* override .btn-primary's min-width: 220px */
  max-width: 85px;
  min-height: 60px;
  height: 60px;          /* lock height — `align-items: stretch` on the row
                            otherwise grows it to the column's min-height */
  padding: 0 10px;
  font-size: 11px;
  letter-spacing: 0.16em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  flex: 0 0 85px;        /* keep the basis at 85px so wrap math is stable */
  align-self: flex-start;
  /* Truncate long era names (RENAISSANCE) with ellipsis instead of letting
     them stretch the chip — the popover shows the full set of names. */
  overflow: hidden;
  /* More transparent than the standard .btn-primary so the pill reads as
     quieter/secondary next to the full-weight Daily / Casual primary
     buttons. The dark glass becomes a hint over the page background. */
  background: linear-gradient(180deg,
    rgba(30, 22, 14, 0.40),
    rgba(14, 10, 6, 0.55));
  border-color: rgba(245, 230, 192, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 4px 14px rgba(0, 0, 0, 0.35);
}
.btn-primary.btn-primary-compact:hover {
  background: linear-gradient(180deg,
    rgba(30, 22, 14, 0.55),
    rgba(14, 10, 6, 0.70));
  border-color: rgba(245, 230, 192, 0.65);
}
/* Override the row's `.btn-primary { width: 100%; padding; min-height }` so
   the compact pill keeps its fixed 85x60 even when wrapping onto its own
   row on narrow viewports. */
.title-cta-row .btn-primary.btn-primary-compact {
  width: 85px;
  min-width: 0;
  max-width: 85px;
  min-height: 60px;
  height: 60px;
  padding: 0 10px;
}
/* Era chip label/name: truncate with ellipsis so RENAISSANCE / MEDIEVAL
   don't push the chip wider. Caret stays visible at the right edge. */
.btn-primary-compact .era-chip-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.btn-primary-compact .era-chip-caret {
  flex: 0 0 auto;
}

/* (Removed: .locked-by-daily competitive toggle styling — the competitive
   toggle itself was removed; the 60s round timer is now always on.) */

/* Today + Past 7 + Past 30 + Hall of Fame tabs — daily-derived competitive
   surfaces, each with a distinct accent dot so they read as
   related-but-distinct in the tab strip. */
.lb-tab-today,
.lb-tab-rolling7,
.lb-tab-rolling30,
.lb-tab-hof {
  position: relative;
}
.lb-tab-today.active {
  background: linear-gradient(180deg, rgba(60, 44, 22, 0.95), rgba(28, 20, 10, 0.95));
}
.lb-tab-rolling7.active {
  background: linear-gradient(180deg, rgba(30, 70, 60, 0.95), rgba(12, 30, 26, 0.95));
}
.lb-tab-rolling30.active {
  background: linear-gradient(180deg, rgba(40, 60, 90, 0.95), rgba(15, 25, 40, 0.95));
}
.lb-tab-hof.active {
  background: linear-gradient(180deg, rgba(80, 60, 30, 0.95), rgba(35, 25, 12, 0.95));
}
/* Color-coded indicator dot. Anchored to the .era-name text span instead
   of the button so it sits inline with the label (6px gap), not pinned
   to the button's left edge. Each tab gets its own dot color via the
   per-tab rules below. */
.lb-tab-today .era-name::before,
.lb-tab-rolling7 .era-name::before,
.lb-tab-rolling30 .era-name::before,
.lb-tab-hof .era-name::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
  position: relative;
  top: -1px;
  opacity: 0.9;
}
.lb-tab-today .era-name::before {
  background: var(--gold);
  box-shadow: 0 0 8px var(--gold-glow, rgba(200, 160, 90, 0.6));
}
.lb-tab-rolling7 .era-name::before {
  background: #5cd6c4;
  box-shadow: 0 0 8px rgba(92, 214, 196, 0.55);
}
.lb-tab-rolling30 .era-name::before {
  background: #84c1e8;
  box-shadow: 0 0 8px rgba(132, 193, 232, 0.55);
}
.lb-tab-hof .era-name::before {
  background: var(--gold-highlight);
  box-shadow: 0 0 10px rgba(245, 230, 192, 0.6);
}

/* Hall of Fame season header — rendered into #leaderboard-status with
   a row of season chips above the standings list. Selected chip glows
   champagne-gold so the active season is unmistakable. */
.hof-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 6px 0 2px;
}
.hof-title {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
.hof-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}
.hof-chip {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 5px 10px;
  background: rgba(30, 22, 14, 0.6);
  color: var(--gold);
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease;
}
@media (hover: hover) {
  .hof-chip:hover {
    background: rgba(60, 44, 22, 0.7);
    border-color: var(--gold);
    color: var(--gold-highlight);
  }
}
.hof-chip.active {
  background: linear-gradient(180deg, rgba(80, 60, 30, 0.95), rgba(35, 25, 12, 0.95));
  border-color: var(--gold);
  color: var(--gold-highlight);
}
.leaderboard-row-empty {
  text-align: center;
  font-style: italic;
  opacity: 0.6;
  padding: 24px 0;
}

/* Hall of Fame — daily-refresh "Awards" cards. One card per superlative
   category (Champion, Iron Will, Most Dedicated, Speed Demon, Era
   Specialist, Wooden Spoon). Grid on desktop, single column on phones. */
.hof-awards[hidden] { display: none; }
.hof-awards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  grid-auto-rows: 1fr;
  gap: 10px;
  padding: 8px 4px 4px;
}
.hof-award-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: linear-gradient(180deg, rgba(40, 28, 14, 0.85), rgba(22, 15, 8, 0.85));
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  /* Pinned height keeps every card uniform regardless of how many leader
     names or whether the extras row has content. The extras row is always
     rendered (CSS reserves its space) so all 6 cards share the same
     label / leaders / extras / blurb stack — even when extras is empty. */
  min-height: 110px;
}
.hof-award-card[data-award="champion"] { border-color: rgba(245, 230, 192, 0.55); }
.hof-award-card[data-award="woodenSpoon"] { opacity: 0.86; }
.hof-award-icon {
  font-size: 28px;
  line-height: 1;
}
.hof-award-body {
  min-width: 0;
}
.hof-award-label {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  margin-bottom: 2px;
}
.hof-award-leaders {
  font-size: 14px;
  color: var(--text-primary, #f5e6c0);
  line-height: 1.35;
  word-break: break-word;
}
.hof-award-name {
  white-space: nowrap;
}
.hof-award-extra {
  /* Always rendered (even empty) so cards keep uniform height; min-height
     reserves the row whether or not there's tied-set spillover. */
  min-height: 1.1em;
  font-size: 12px;
  font-style: italic;
  opacity: 0.65;
  line-height: 1.1;
  margin-top: 1px;
}
.hof-award-empty {
  opacity: 0.5;
  font-style: italic;
}
.hof-award-blurb {
  margin-top: 4px;
  font-size: 11px;
  opacity: 0.65;
  letter-spacing: 0.02em;
}
.hof-award-value {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--gold-highlight);
  text-align: right;
  white-space: nowrap;
}
@media (max-width: 480px) {
  .hof-awards { grid-template-columns: 1fr; }
  .hof-award-icon { font-size: 24px; }
  .hof-award-leaders { font-size: 13px; }
  .hof-award-value { font-size: 13px; }
}

/* =====================================================================
   Daily Challenge button — sits below Start. Cyan/blue accent palette so
   it visually pops against the gold-and-dark site palette without
   clashing. Different "language" than Start (which is the casual primary)
   makes the modes feel distinct at a glance. Whole button uses the
   display font (Cinzel) including the meta line, so the typographic
   hierarchy stays consistent inside the button.

   States:
     default    → glowing blue, eye-catching, reads "Daily Challenge"
     hover      → brighter glow + lift
     .played    → near-transparent, grayscale-leaning, shows the
                  "Resets in Xh Ym" countdown text injected by JS into
                  .btn-daily-meta. No-cursor pointer.
   ===================================================================== */
.btn-daily {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin-top: 14px;
  min-width: 240px;
  min-height: 60px;
  padding: 12px 36px;
  font-family: var(--font-display);
  /* Solid glassy navy with a cyan highlight at the top. Was way too
     transparent — alpha values bumped from .16/.32/.92 to .55/.78/.97
     so the button reads as substantial against the cinematic
     backgrounds. */
  background:
    linear-gradient(180deg,
      rgba(80, 165, 220, 0.55) 0%,
      rgba(28, 75, 130, 0.78) 50%,
      rgba(8, 22, 45, 0.97) 100%);
  color: #d8eeff;
  border: 1px solid rgba(170, 220, 255, 0.7);
  border-radius: 10px;
  cursor: pointer;
  /* Three-layer back-glow done with stacked box-shadows. Reads as a
     wide cyan halo bleeding out behind the button — no z-index
     gymnastics, no extra DOM. The animation pulses the outer halo
     gently so it draws the eye without feeling jittery. */
  box-shadow:
    inset 0 1px 0 rgba(220, 240, 255, 0.32),
    0 0 36px 10px rgba(120, 200, 240, 0.45),
    0 0 18px rgba(120, 200, 240, 0.32),
    0 6px 22px rgba(0, 0, 0, 0.55);
  animation: btn-daily-glow 3.6s ease-in-out infinite;
  transition:
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 220ms ease,
    opacity 220ms ease,
    background 220ms ease;
  user-select: none;
}
@keyframes btn-daily-glow {
  0%, 100% {
    box-shadow:
      inset 0 1px 0 rgba(220, 240, 255, 0.32),
      0 0 36px 10px rgba(120, 200, 240, 0.42),
      0 0 18px rgba(120, 200, 240, 0.30),
      0 6px 22px rgba(0, 0, 0, 0.55);
  }
  50% {
    box-shadow:
      inset 0 1px 0 rgba(220, 240, 255, 0.42),
      0 0 52px 16px rgba(120, 200, 240, 0.65),
      0 0 26px rgba(120, 200, 240, 0.50),
      0 6px 22px rgba(0, 0, 0, 0.55);
  }
}
@media (prefers-reduced-motion: reduce) {
  .btn-daily { animation: none; }
}
.btn-daily-label {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #f0f9ff;
  text-shadow: 0 0 10px rgba(150, 220, 255, 0.55), 0 1px 2px rgba(0, 0, 0, 0.7);
}
.btn-daily-meta {
  /* Same display font as label, but smaller + softer color, so the
     button typography reads as one consistent voice. */
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(190, 220, 250, 0.8);
}
/* Second meta line — used in the post-completion has-results state to
   stack the action affordance ("View your results →") above the reset
   countdown ("Resets in 14h 22m"). Slightly smaller + dimmer than the
   primary meta so the action line stays the visual lead. */
.btn-daily-meta-secondary {
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(190, 220, 250, 0.62);
}
.btn-daily-meta-secondary[hidden] { display: none; }
@media (hover: hover) {
  .btn-daily:hover {
    transform: translateY(-1px);
    border-color: rgba(180, 230, 255, 0.85);
    box-shadow:
      inset 0 1px 0 rgba(240, 250, 255, 0.28),
      0 0 24px rgba(140, 210, 255, 0.45),
      0 8px 22px rgba(0, 0, 0, 0.55);
  }
}
.btn-daily:active { transform: translateY(1px); }

/* Played state — drained color, dimmed but still substantial. Visual
   cue that the action is complete and unavailable until midnight UTC.
   The countdown in .btn-daily-meta is updated every minute by JS. */
.btn-daily.played {
  /* Bumped 0.65 → 0.85 so the countdown text inside stays readable —
     the muted background colors below (0.45/0.62/0.82) still communicate
     "dormant" without crushing the foreground text. */
  opacity: 0.85;
  cursor: default;
  /* Drop the pulsing glow once the daily is done — the button is
     dormant; the eye-grab is no longer needed. */
  animation: none;
  background:
    linear-gradient(180deg,
      rgba(70, 90, 110, 0.45) 0%,
      rgba(35, 45, 65, 0.62) 50%,
      rgba(12, 18, 28, 0.82) 100%);
  border-color: rgba(160, 180, 200, 0.45);
  box-shadow: inset 0 1px 0 rgba(220, 230, 240, 0.16);
}
.btn-daily.played .btn-daily-label {
  color: rgba(232, 240, 250, 0.95);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
.btn-daily.played .btn-daily-label::after {
  content: ' ✓';
  color: #84c98a;
}
.btn-daily.played .btn-daily-meta {
  /* Countdown text — Eric specifically wanted this readable so users
     know when the next daily drops. Bright, with a drop shadow for
     contrast against the gradient. */
  color: rgba(240, 248, 255, 0.95);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}
@media (hover: hover) {
  .btn-daily.played:hover {
    transform: none;
    border-color: rgba(160, 180, 200, 0.5);
    box-shadow: inset 0 1px 0 rgba(220, 230, 240, 0.10);
  }
}

/* Played state with a saved snapshot — button now acts as a "View your
   results" entry point. Restore the cursor + a subtle hover lift so the
   click affordance reads. The primary meta line ("View your results →")
   becomes the dominant text; the secondary line carries the countdown. */
.btn-daily.played.has-results {
  cursor: pointer;
  opacity: 0.95;
}
.btn-daily.played.has-results .btn-daily-meta {
  color: rgba(240, 250, 255, 1);
  font-size: 11px;
  letter-spacing: 0.14em;
  font-weight: 600;
}
.btn-daily.played.has-results .btn-daily-meta-secondary {
  color: rgba(220, 235, 250, 0.78);
  margin-top: 2px;
}
@media (hover: hover) {
  .btn-daily.played.has-results:hover {
    transform: translateY(-1px);
    border-color: rgba(180, 220, 255, 0.7);
    box-shadow:
      inset 0 1px 0 rgba(240, 250, 255, 0.18),
      0 0 18px rgba(140, 210, 255, 0.30),
      0 6px 18px rgba(0, 0, 0, 0.45);
  }
}

/* Side-by-side CTA row on the title screen — Daily Challenge on the left,
   Casual Play on the right, equal visual weight. Wraps to a stack on
   narrow viewports (Daily stays first by source order). Each column now
   holds a primary CTA + a row of small ghost actions (View Board, Era). */
/* Desktop: CSS grid with 1fr fillers on both sides so the gap between
   Daily and Casual is always at the PAGE horizontal center, regardless
   of the era pill on the right. The era pill lives in the right filler
   column (anchored to its left edge) so it doesn't pull the centering
   math sideways. Pattern: [1fr · Daily · Casual · 1fr-with-era-pill]. */
.title-cta-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 280px) minmax(0, 280px) minmax(0, 1fr);
  align-items: stretch;
  gap: 16px;
  width: 100%;
  margin: 0 auto;
}
.title-cta-row > .title-cta-col:nth-of-type(1) { grid-column: 2; }
.title-cta-row > .title-cta-col:nth-of-type(2) { grid-column: 3; }
.title-cta-row > #btn-era-toggle {
  grid-column: 4;
  justify-self: start;
  align-self: flex-start;
}
.title-cta-col {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-width: 0;
}
/* Narrow viewports: drop back to a wrapping flex so all three elements
   stack/wrap as needed instead of clipping inside the grid columns. */
@media (max-width: 720px) {
  .title-cta-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    max-width: 760px;
  }
  .title-cta-row > .title-cta-col:nth-of-type(1),
  .title-cta-row > .title-cta-col:nth-of-type(2),
  .title-cta-row > #btn-era-toggle {
    grid-column: auto;
    justify-self: auto;
  }
  .title-cta-col { flex: 1 1 280px; }
}
.title-cta-row .btn-daily,
.title-cta-row .btn-primary {
  width: 100%;
  margin: 0;
  /* Locked equal height across the row. Was `min-height: 72px` — but
     btn-daily's label + meta stack pushed it past 72 while btn-primary
     stayed exact, so casual looked visibly shorter on desktop. Fixed
     height clamps both to the same y-extent. */
  height: 84px;
  /* Override the standalone .btn-daily/.btn-primary padding so the buttons
     are short and wide inside the title CTA row (rather than tall pills
     sized for hero-button use elsewhere). */
  padding: 10px 18px;
}
.title-cta-row .btn-daily {
  min-width: 0;
}
/* Push sub-button row to the BOTTOM of its column so View Daily Board
   and View Casual Boards land at the same y across columns even when
   the primary CTAs above them differ in height. */
.title-cta-actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
}
/* Shade the View Daily Board / View Casual Boards pills so they stay
   readable over bright/cluttered cinematic backgrounds (default ghost
   button is transparent). Translucent dark glass + a slightly stronger
   border than the global ghost variant. Hover keeps the same direction. */
.title-cta-actions .btn-secondary-ghost {
  background: linear-gradient(180deg,
    rgba(20, 14, 8, 0.50),
    rgba(10, 6, 4, 0.65));
  border-color: rgba(245, 230, 192, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 2px 10px rgba(0, 0, 0, 0.35);
}
.title-cta-actions .btn-secondary-ghost:hover,
.title-cta-actions .btn-secondary-ghost:focus-visible {
  background: linear-gradient(180deg,
    rgba(30, 22, 14, 0.65),
    rgba(14, 10, 6, 0.80));
  border-color: rgba(245, 230, 192, 0.85);
}
/* Small ghost-pill secondary action — used for the per-CTA leaderboard
   links and the era chip toggle. Champagne outline on transparent, no
   fill until hover. Sits visually quiet beneath the gold primary CTAs. */
.btn-secondary-ghost {
  appearance: none;
  border: 1px solid rgba(245, 230, 192, 0.45);
  background: transparent;
  border-radius: 999px;
  padding: 6px 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease;
}
.btn-secondary-ghost:hover,
.btn-secondary-ghost:focus-visible {
  background: rgba(245, 230, 192, 0.14);
  border-color: rgba(245, 230, 192, 0.85);
  color: #fff8e6;
  outline: none;
}
.btn-secondary-ghost:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.era-chip-btn[aria-expanded="true"] .era-chip-caret {
  transform: rotate(180deg);
}
.era-chip-caret {
  display: inline-block;
  transition: transform 180ms ease;
}
.era-chip-label .era-current {
  color: var(--gold-highlight);
  font-weight: 700;
}
/* Casual Play (.btn-primary) re-laid-out to match Daily's stacked label+meta
   structure so the two buttons read as parallel CTAs. Scoped to the row
   so we don't disturb other .btn-primary uses (Next round, Travel again,
   Submit, etc). */
.title-cta-row #btn-start {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  padding: 12px 24px;
  letter-spacing: normal;
}
.btn-start-label {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
.btn-start-meta {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(245, 230, 200, 0.6);
}
@media (max-width: 480px) {
  /* Reposition the title CTAs into an explicit 4-row grid using display:
     contents to dissolve the .title-cta-col wrappers — the inner buttons
     and "view ___ boards" ghost rows become direct grid items so each can
     span the full row independently for true centering. Era pill pinned to
     row 3 col 2 so it visually pairs with the Casual button. All other
     widths are unaffected — the grid only kicks in here. */
  .title-cta-row {
    display: grid;
    grid-template-columns: 1fr 78px;
    grid-auto-rows: auto;
    gap: 12px 8px;
    max-width: 360px;
    margin: 0 auto;
  }
  .title-cta-row > .title-cta-col { display: contents; }
  .title-cta-row > .title-cta-col:nth-of-type(1) > #btn-daily {
    grid-column: 1 / -1;
    grid-row: 1;
  }
  .title-cta-row > .title-cta-col:nth-of-type(1) > .title-cta-actions {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .title-cta-row > .title-cta-col:nth-of-type(2) > #btn-start {
    grid-column: 1;
    grid-row: 3;
  }
  .title-cta-row > .title-cta-col:nth-of-type(2) > .title-cta-actions {
    grid-column: 1 / -1;
    grid-row: 4;
  }
  .title-cta-row > #btn-era-toggle {
    grid-column: 2;
    grid-row: 3;
    align-self: start;
    justify-self: stretch;
    width: 78px;
    max-width: 78px;
    min-height: 56px;
    height: 56px;
  }

  /* Daily card: shorter, dimmer halo, no breathing animation. Still primary
     by gradient + position. */
  .title-cta-row .btn-daily {
    min-height: 56px;
    padding: 10px 14px;
    box-shadow:
      inset 0 1px 0 rgba(220, 240, 255, 0.20),
      0 0 14px 2px rgba(120, 200, 240, 0.22),
      0 4px 12px rgba(0, 0, 0, 0.55);
    animation: none;
  }
  .btn-daily-label { font-size: 12px; letter-spacing: 0.20em; }
  .btn-daily-meta  { font-size: 9px;  letter-spacing: 0.14em; }
  .btn-start-label { font-size: 12px; letter-spacing: 0.22em; }
  .btn-start-meta  { font-size: 9px;  letter-spacing: 0.14em; }

  .title-cta-row .btn-daily,
  .title-cta-row #btn-start {
    min-height: 56px;
  }

  /* Tighter chrome — pull the wordmark, pills, and ghost-button row inward
     so the page reads less bottom-heavy. */
  .title-content { padding: 16px 16px calc(28px + env(safe-area-inset-bottom, 0px)); }
  .title-wordmark-zone { padding: 8px 16px 4px; }
  .title-content h1 { font-size: clamp(20px, 6vw, 30px); }
  .title-beta-pill  { font-size: 8.5px; padding: 2px 8px; }
  .title-cta-actions .btn-secondary-ghost {
    font-size: 9.5px;
    padding: 5px 10px;
    letter-spacing: 0.16em;
  }
}

/* ===== Background rotation pause + reduced motion =====
   Toggled from the title settings popover via classes on <body>. We freeze
   the cinematic drift animation and snap the active layer to scale(1) so it
   doesn't visibly creep when paused. */
body.bg-rotation-paused .title-bg-video.active {
  animation-play-state: paused;
}
body.reduced-motion .title-bg-video {
  transition-duration: 0ms !important;
  animation: none !important;
  transform: none !important;
}
body.reduced-motion .onboarding-step,
body.reduced-motion .onboarding-stage {
  animation: none !important;
  transition-duration: 0ms !important;
}

/* ===== First-time onboarding overlay =====
   Three-step explainer shown once on first Start click. Sits above the title
   screen until the user clicks "Got it" or the auto-advance finishes. */
.onboarding-overlay {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse at center,
    rgba(8, 7, 10, 0.78) 0%,
    rgba(8, 7, 10, 0.94) 100%);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  animation: ob-fade-in 240ms ease-out both;
}
.onboarding-overlay[hidden] { display: none; }
@keyframes ob-fade-in { from { opacity: 0; } to { opacity: 1; } }

.onboarding-card {
  width: min(92vw, 460px);
  padding: 28px 28px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 18px;
  background: linear-gradient(180deg, rgba(28, 22, 16, 0.96), rgba(14, 10, 8, 0.98));
  border: 1px solid var(--border-strong);
  border-radius: 18px;
}
.onboarding-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.onboarding-stage {
  position: relative;
  width: 100%;
  min-height: 220px;
  overflow: hidden;
}
.onboarding-step {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  opacity: 0;
  transition: opacity 320ms ease;
  pointer-events: none;
}
.onboarding-stage[data-step="1"] .onboarding-step[data-step="1"],
.onboarding-stage[data-step="2"] .onboarding-step[data-step="2"],
.onboarding-stage[data-step="3"] .onboarding-step[data-step="3"] {
  opacity: 1;
  pointer-events: auto;
}
.onboarding-anim {
  width: 100%;
  height: 130px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  position: relative;
  overflow: hidden;
}
.onboarding-step-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.onboarding-step-text {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
  max-width: 36ch;
}
.onboarding-step-text kbd {
  display: inline-block;
  padding: 0 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  background: rgba(245, 230, 192, 0.08);
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  color: var(--gold-highlight);
}

/* Step 1: Look around — pano thumb + animated hand swipe */
.ob-pano-thumb {
  position: absolute;
  inset: 8px;
  background:
    radial-gradient(ellipse at 30% 60%, rgba(212, 165, 116, 0.32), transparent 60%),
    linear-gradient(135deg, #2a1d12 0%, #4a3220 30%, #1c1410 60%, #6b4a2e 100%);
  border-radius: 8px;
  filter: brightness(0.85) contrast(1.05);
}
.ob-hand {
  position: absolute;
  top: 50%;
  left: 25%;
  width: 36px;
  height: 36px;
  color: var(--gold-highlight);
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.7));
  animation: ob-hand-swipe 2000ms ease-in-out infinite;
}
.ob-hand svg { width: 100%; height: 100%; }
@keyframes ob-hand-swipe {
  0%, 100% { left: 25%; opacity: 0.7; }
  20%      { opacity: 1; }
  80%      { opacity: 1; }
  50%      { left: 75%; opacity: 1; }
}

/* Step 2: Drop a pin — fake map grid + animated pin drop */
.ob-map {
  position: absolute;
  inset: 8px;
  background:
    linear-gradient(135deg, #1f1812 0%, #2a1f15 50%, #1a130d 100%);
  border-radius: 8px;
  overflow: hidden;
}
.ob-map-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(0deg, rgba(212, 165, 116, 0.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(212, 165, 116, 0.12) 1px, transparent 1px);
  background-size: 24px 24px;
  opacity: 0.5;
}
.ob-pin {
  position: absolute;
  top: 30%;
  left: 50%;
  width: 28px;
  height: 28px;
  color: var(--gold);
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.7));
  transform: translate(-50%, -100%);
  animation: ob-pin-drop 2000ms ease-in-out infinite;
}
@keyframes ob-pin-drop {
  0%   { top: 0%; opacity: 0; transform: translate(-50%, -100%) scale(0.6); }
  35%  { top: 60%; opacity: 1; transform: translate(-50%, -100%) scale(1); }
  60%  { top: 60%; opacity: 1; transform: translate(-50%, -100%) scale(1); }
  100% { top: 60%; opacity: 0; transform: translate(-50%, -100%) scale(1); }
}

/* Step 3: Pick a year — animated slider + ticking year label */
.onboarding-anim-year {
  flex-direction: column;
  gap: 14px;
}
.ob-slider-track {
  position: relative;
  width: 70%;
  height: 6px;
  background: rgba(120, 100, 80, 0.32);
  border-radius: 999px;
}
.ob-slider-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0%;
  background: linear-gradient(90deg, var(--gold), var(--gold-highlight));
  border-radius: 999px;
  animation: ob-slider-fill 2000ms ease-in-out infinite;
}
.ob-slider-thumb {
  position: absolute;
  top: 50%;
  left: 0%;
  width: 14px;
  height: 14px;
  background: var(--gold-highlight);
  border: 2px solid var(--gold);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
  animation: ob-slider-thumb 2000ms ease-in-out infinite;
}
@keyframes ob-slider-fill {
  0%   { width: 5%; }
  100% { width: 95%; }
}
@keyframes ob-slider-thumb {
  0%   { left: 5%; }
  100% { left: 95%; }
}
.ob-year {
  font-family: var(--font-display);
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  color: var(--gold-highlight);
}
.ob-year-value {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
  animation: ob-year-tick 2000ms steps(1, end) infinite;
}
.ob-year-suf {
  font-size: 12px;
  letter-spacing: 0.18em;
  opacity: 0.8;
}
@keyframes ob-year-tick {
  0%   { content: '−1500'; }
  20%  {}
  40%  {}
  60%  {}
  80%  {}
  100% {}
}

.onboarding-dots {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
}
.onboarding-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(212, 165, 116, 0.28);
  transition: background 220ms ease, transform 220ms ease;
}
.onboarding-dot.active {
  background: var(--gold);
  transform: scale(1.3);
}
.onboarding-skip {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.22), rgba(212, 165, 116, 0.08));
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 10px 22px;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
@media (hover: hover) {
  .onboarding-skip:hover {
    background: linear-gradient(180deg, rgba(212, 165, 116, 0.34), rgba(212, 165, 116, 0.14));
    border-color: var(--gold);
    box-shadow: 0 0 22px var(--gold-glow);
  }
}
.onboarding-skip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
@media (hover: hover) {
  .onboarding-skip:disabled:hover {
    background: linear-gradient(180deg, rgba(212, 165, 116, 0.22), rgba(212, 165, 116, 0.08));
    border-color: var(--border-strong);
    box-shadow: none;
  }
}

/* Step 4: Content disclaimer — checkbox-gated */
.onboarding-stage[data-step="4"] .onboarding-step[data-step="4"] {
  opacity: 1;
  pointer-events: auto;
}
.onboarding-stage[data-step="4"] {
  min-height: 260px;
}
.onboarding-anim-disclaimer {
  background: transparent;
  border: none;
  height: 72px;
}
.ob-disclaimer-icon {
  width: 56px;
  height: 56px;
  color: var(--gold);
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.55));
}
.onboarding-agree-label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  margin-top: 2px;
  width: 100%;
  max-width: 380px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
  transition: border-color 180ms ease, background 180ms ease;
}
@media (hover: hover) {
  .onboarding-agree-label:hover {
    background: rgba(245, 230, 192, 0.07);
    border-color: var(--border-strong);
  }
}
.onboarding-agree-checkbox {
  flex-shrink: 0;
  margin: 1px 0 0 0;
  width: 16px;
  height: 16px;
  accent-color: var(--gold);
  cursor: pointer;
}
.onboarding-agree-text {
  flex: 1;
}
/* Disclaimer-only mode (returning user who never saw the disclaimer): hide
   the multi-step dots since there's only one card to show. */
.onboarding-overlay.disclaimer-only .onboarding-dots {
  display: none;
}

/* ===== GAME screen ===== */
#screen-game {
  background: #000;
}

/* ===== Scene loading placeholder (between rounds, pre-pano-paint) =====
   Covers the inside of the <a-sky> sphere — which would otherwise render
   as solid white (MeshBasicMaterial default color: #fff) until the
   panorama texture loads. Fades out 400ms after the validation Image
   in loadPano() fires onload. */
.scene-loader {
  position: absolute;
  inset: 0;
  z-index: 5; /* above a-scene canvas (z:1), below HUD chips (z:22+) */
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #0a0a14 0%, #1a1208 100%);
  pointer-events: none;
  opacity: 1;
  transition: opacity 400ms ease-out;
}
.scene-loader[hidden] { display: none; }
.scene-loader.is-fading { opacity: 0; }
.scene-loader-text {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  opacity: 0.4;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.7);
  animation: scene-loader-pulse 2200ms ease-in-out infinite;
}
@keyframes scene-loader-pulse {
  0%, 100% { opacity: 0.30; }
  50%      { opacity: 0.55; }
}
@media (prefers-reduced-motion: reduce) {
  .scene-loader-text { animation: none; opacity: 0.4; }
}
a-scene, #scene {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  z-index: 1;
}
/* A-Frame default canvas should fill */
.a-canvas {
  width: 100% !important;
  height: 100% !important;
}
/* Desktop affordance: grab cursor over the pano. Touch devices ignore. */
#screen-game.active a-scene .a-canvas { cursor: grab; }
#screen-game.active a-scene .a-canvas:active { cursor: grabbing; }
body.in-vr a-scene .a-canvas { cursor: none; }

/* ===== Cinematic vignette over panorama ===== */
#screen-game.active::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.45) 100%);
  z-index: 2;
}
/* User can disable the cinematic vignette via the in-game settings popover.
   Default is OFF (see SETTINGS_TOGGLES in main.js) so the cinematic title
   backgrounds + wordmark + final-screen stills stay color-saturated. The
   toggle covers every screen's vignette overlay so the on/off state is
   consistent across title, in-game, final/done, about, and the wordmark
   hero. */
body.no-vignette #screen-game.active::after { display: none; }
body.no-vignette .title-vignette,
body.no-vignette .wordmark-vignette,
body.no-vignette .final-vignette,
body.no-vignette .about-vignette { display: none; }
/* User-toggled "reduce motion" — disables decorative pulse/score-bump.
   Distinct from prefers-reduced-motion which is OS-driven. */
body.reduce-motion #map-dock.no-pin,
body.reduce-motion .lock-in-cta,
body.reduce-motion .score-chip.bumping #score-value,
body.reduce-motion .title-bg-video.active { animation: none !important; }

/* ===== Liquid Glass primitives ===== */
.glass-chip, .glass-panel {
  background: var(--bg-panel);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid var(--border-soft);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
  border-radius: 14px;
  color: var(--text-primary);
}
.glass-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-radius: 999px;
  min-height: 44px;
  white-space: nowrap;
}
.glass-chip .muted { color: var(--text-muted); font-weight: 400; }
.glass-chip.btn {
  cursor: pointer;
  transition:
    transform 180ms cubic-bezier(0.32, 0.72, 0, 1),
    background 180ms ease,
    border-color 180ms ease,
    box-shadow 180ms ease;
}
.glass-chip.btn.icon-only {
  padding: 0;
  width: 44px;
  height: 44px;
  justify-content: center;
}
@media (hover: hover) {
  .glass-chip.btn:hover {
    background: var(--bg-panel-strong);
    border-color: var(--border-strong);
    box-shadow:
      0 8px 32px rgba(0, 0, 0, 0.55),
      0 0 18px var(--gold-glow),
      inset 0 1px 0 rgba(245, 230, 192, 0.08);
  }
}
.glass-chip.btn:active { transform: scale(0.96); }
.glass-chip:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}
.chip-icon { width: 18px; height: 18px; flex: 0 0 18px; color: var(--gold-highlight); }
.chip-icon.gold {
  color: var(--gold);
  filter: drop-shadow(0 0 8px var(--gold-glow));
}

/* Danger chip variant — used by the in-game Exit X. Coral red glass
   that reads as destructive without screaming. Focus-visible keeps the
   gold ring (defined on .glass-chip:focus-visible above) for a11y
   consistency with the rest of the HUD. */
.glass-chip.btn-danger {
  background: rgba(231, 76, 60, 0.15);
  border-color: rgba(231, 76, 60, 0.6);
}
.glass-chip.btn-danger .chip-icon { color: var(--danger); }
@media (hover: hover) {
  .glass-chip.btn-danger:hover {
    background: rgba(231, 76, 60, 0.28);
    border-color: rgba(231, 76, 60, 0.85);
    box-shadow:
      0 8px 32px rgba(0, 0, 0, 0.55),
      0 0 18px var(--danger-glow),
      inset 0 1px 0 rgba(255, 200, 195, 0.12);
  }
  .glass-chip.btn-danger:hover .chip-icon { color: #ff6f5f; }
}

/* ===== Corner stacks ===== */
.hud-corner {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 32;
}
#hud-tl { left: max(env(safe-area-inset-left, 0px), 16px); align-items: flex-start; }

/* Bottom-left cluster (in-game settings + exit). Lives away from the
   map-dock's hover-zone so the cursor path from year-dock doesn't trigger
   the map's hover-expand. Overrides .hud-corner's `top` with `bottom`. */
#hud-bl {
  top: auto;
  bottom: max(env(safe-area-inset-bottom, 0px), 16px);
  left: max(env(safe-area-inset-left, 0px), 16px);
  align-items: flex-start;
}

/* Hide A-Frame's default VR button + any of its modal flavors (we have our
   own VR flow, and the device-orientation permission modal is broken on
   insecure contexts — show nothing instead of a dead-end "Cancel" dialog). */
.a-enter-vr-button, .a-orientation-modal, .a-modal, .a-dialog {
  display: none !important;
}

/* ===== VR exit hint ===== */
#vr-hint {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.78);
  border: 1px solid var(--border-soft);
  padding: 14px 22px;
  border-radius: 10px;
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  z-index: 999;
  pointer-events: none;
  transition: opacity 0.4s;
}
#vr-hint.hidden { opacity: 0; }

/* ===== Tier 1: offscreen Leaflet container =====
   The vr-pin-map A-Frame component spins up a hidden Leaflet instance to
   render tiles into a canvas, then binds the canvas as a CanvasTexture on
   the in-VR map plane. Off-viewport positioning (-9999px) keeps it out of
   sight while still letting Leaflet measure dimensions and lay out tiles.
   Fixed 1024x1024 to match the canvas size used by the component. */
#vr-map {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1024px;
  height: 1024px;
  pointer-events: none;
}

/* Placeholder hook for future Quest-specific styling (Tier 0 set the class;
   no specific rules yet, but the selector exists so additions don't churn
   the rule order). */
body.is-quest { /* reserved */ }

/* VR button: opt the chip OUT of the in-game HUD dim rule so the affordance
   stays visible against busy panoramas. Meta blue logo at full opacity (or
   close to) makes it discoverable without hover. */
@media (pointer: fine) {
  #screen-game.active #hud-tl > .vr-btn-meta { opacity: 1; }
  #screen-game.active #hud-tl > .vr-btn-meta:hover,
  #screen-game.active #hud-tl > .vr-btn-meta:focus-visible {
    opacity: 1;
  }
}

/* Tier 3 VR onboarding tip — pops on first round-1 entry on a VR-capable
   device (initVRButtonTip in main.js). While body.vr-tip-active is set,
   the VR button gets full opacity, an amber glow, and a gentle scale pulse
   so first-time users (Eric's friend on Quest tonight) can find it. */
body.vr-tip-active #vr-btn.vr-btn-meta {
  opacity: 1 !important;
  animation: vr-btn-attract 1.6s ease-in-out infinite alternate;
  box-shadow:
    0 0 0 2px rgba(255, 210, 122, 0.55),
    0 0 18px 6px rgba(255, 210, 122, 0.35),
    0 0 28px 12px rgba(24, 119, 242, 0.25);
  border-color: rgba(255, 210, 122, 0.7);
}
@keyframes vr-btn-attract {
  from { transform: scale(1); }
  to   { transform: scale(1.06); }
}
body.reduce-motion #vr-btn.vr-btn-meta { animation: none; }

.vr-onboarding-tip {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  left: calc(env(safe-area-inset-left, 0px) + 240px);
  z-index: 30;
  max-width: 280px;
  padding: 14px 36px 14px 16px;
  background: linear-gradient(180deg, rgba(20, 18, 24, 0.96), rgba(8, 7, 10, 0.96));
  border: 1px solid rgba(255, 210, 122, 0.55);
  border-radius: 12px;
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(255, 210, 122, 0.18);
  color: var(--gold-light, #f5e6c0);
  font-family: var(--font-body, 'Inter', system-ui, sans-serif);
  pointer-events: auto;
  animation: vr-tip-rise 0.34s ease-out both;
}
@keyframes vr-tip-rise {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.vr-onboarding-tip-arrow {
  position: absolute;
  top: 22px;
  left: -8px;
  width: 14px;
  height: 14px;
  background: linear-gradient(135deg, rgba(20, 18, 24, 0.96), rgba(20, 18, 24, 0.96));
  border-bottom: 1px solid rgba(255, 210, 122, 0.55);
  border-left: 1px solid rgba(255, 210, 122, 0.55);
  transform: rotate(45deg);
}
.vr-onboarding-tip-eyebrow {
  font-family: var(--font-display, 'Cinzel', serif);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-mid, #d4a574);
  margin-bottom: 4px;
}
.vr-onboarding-tip-title {
  font-family: var(--font-display, 'Cinzel', serif);
  font-size: 16px;
  letter-spacing: 0.04em;
  color: var(--gold-light, #f5e6c0);
  margin-bottom: 6px;
}
.vr-onboarding-tip-body {
  font-size: 13px;
  line-height: 1.4;
  color: rgba(245, 230, 192, 0.82);
}
.vr-onboarding-tip-close {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: rgba(245, 230, 192, 0.55);
  cursor: pointer;
  padding: 0;
  border-radius: 6px;
}
.vr-onboarding-tip-close:hover,
.vr-onboarding-tip-close:focus-visible {
  color: var(--gold-light, #f5e6c0);
  background: rgba(255, 210, 122, 0.12);
  outline: none;
}
.vr-onboarding-tip-close svg {
  width: 14px;
  height: 14px;
}

/* ===== Mini-map dock (top-right; expands on hover/focus) =====
   Settings + exit chips moved to bottom-left (#hud-bl) so the idle
   map-dock can sit at the very top edge again — no need to leave room
   for a chip row. */
#map-dock {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  right: max(env(safe-area-inset-right, 0px), 16px);
  width: 320px;
  height: 220px;
  padding: 6px;
  z-index: 22;
  overflow: hidden;
  cursor: pointer;
  opacity: 0.55;
  /* R2: layout/style/paint containment isolates the dock's expand/collapse
     animation from the rest of the page so Leaflet's tile rendering during
     the 420ms transition doesn't trigger reflow on the panorama or HUD. */
  contain: layout style paint;
  transition:
    width 420ms cubic-bezier(0.22, 1, 0.36, 1),
    height 420ms cubic-bezier(0.22, 1, 0.36, 1),
    top 420ms cubic-bezier(0.22, 1, 0.36, 1),
    right 420ms cubic-bezier(0.22, 1, 0.36, 1),
    border-radius 420ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 420ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 220ms ease;
}
#map-dock:focus-within, #map-dock.expanded, #map-dock.locked { opacity: 1; }
@media (hover: hover) {
  #map-dock:hover { opacity: 1; }
}
#map-dock #map {
  width: 100%;
  height: 100%;
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-deep);
}
.leaflet-container {
  background: var(--bg-deep);
  /* Julia's feedback: pan/zoom felt jumpy. GPU compositing hint helps the
     browser promote the tile pane to its own layer so transforms during
     zoom/pan don't repaint the whole map dock. */
  will-change: transform;
}
/* R2: per-pane GPU compositing layers. translateZ(0) forces each Leaflet
   pane to its own layer so tile transforms, marker repositions, and overlay
   redraws don't trigger composite work on neighboring panes. Builds on the
   container-level will-change above. */
.leaflet-tile-pane,
.leaflet-overlay-pane,
.leaflet-marker-pane,
.leaflet-shadow-pane,
.leaflet-popup-pane {
  transform: translateZ(0);
  will-change: transform;
}
/* Cross-PR (B): Eric called the +/- zoom controls redundant in every state.
   Disabled at the L.map() level (zoomControl: false in main.js); this rule
   is the belt-and-suspenders fallback in case any code path re-adds them. */
.leaflet-control-zoom { display: none !important; }

/* Subtle warm tint on the map tiles only — keeps the markers/labels at
   their intended saturation. Eric: "the map just doesnt go with the games
   vibe" — sepia/saturate aligns it with the gold-on-dark theme without
   hurting readability. Scoped to the tile pane so labels still show. */
.leaflet-tile-pane {
  filter: sepia(0.18) saturate(0.85) brightness(0.93) hue-rotate(-6deg);
}

/* Marker labels (YOU / ACTUAL) — small uppercase tracked-out chips
   anchored to each pin. permanent: true ensures they stay through pans. */
.marker-label.leaflet-tooltip {
  background: rgba(18, 14, 10, 0.92);
  border: 1px solid var(--border-strong);
  color: var(--gold-highlight);
  padding: 3px 8px;
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  border-radius: 999px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.55);
  white-space: nowrap;
}
.marker-label.leaflet-tooltip::before,
.marker-label.leaflet-tooltip::after { display: none !important; border: none !important; }
.marker-label-actual.leaflet-tooltip {
  color: #ffd9d3;
  border-color: rgba(231, 76, 60, 0.55);
}

/* Distance label centered on the dashed line — small gold pill so it
   reads against the warm map tint. interactive:false so clicks pass to
   tiles below (the map is locked anyway, but harmless either way). */
.distance-label {
  background: transparent !important;
  border: none !important;
}
.distance-label > span {
  display: inline-block;
  background: rgba(18, 14, 10, 0.92);
  border: 1px solid var(--gold);
  color: var(--gold-highlight);
  padding: 4px 10px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6);
  transform: translate(-50%, -50%);
  position: absolute;
}

#map-dock.expanded {
  width: min(72vw, 820px);
  height: min(70vh, 600px);
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  right: max(env(safe-area-inset-right, 0px), 16px);
  z-index: 30;
  border-color: var(--border-strong);
  box-shadow:
    0 24px 64px rgba(0, 0, 0, 0.7),
    inset 0 1px 0 rgba(245, 230, 192, 0.08);
}
/* Pulse ring on idle (no pin yet) — calls attention to the map */
#map-dock.no-pin {
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 0 0 0 rgba(212, 165, 116, 0.6);
  animation: pulse-ring 2.4s ease-out infinite;
}
@keyframes pulse-ring {
  0% {
    box-shadow:
      0 8px 32px rgba(0, 0, 0, 0.45),
      inset 0 1px 0 rgba(245, 230, 192, 0.06),
      0 0 0 0 rgba(212, 165, 116, 0.6);
  }
  100% {
    box-shadow:
      0 8px 32px rgba(0, 0, 0, 0.45),
      inset 0 1px 0 rgba(245, 230, 192, 0.06),
      0 0 0 18px rgba(212, 165, 116, 0);
  }
}

/* ===== Year picker dock (bottom-center) =====
   Universal numeric+era picker (alarm-clock pattern). The dock itself is a
   transparent flex container — no background, no border, no blur — that
   stacks the conditional CTAs (LOCK IN / DROP A PIN) above the picker pill.
   Picker + CTA visuals live further down (search ".year-input-mobile",
   ".lock-in-cta", ".drop-pin-prompt"). The slider, year-display, year-hint,
   tick rail, and scoring-help "?" all lived here in earlier iterations
   (pre-PR #46 / pre-this-PR) — gone now in favor of the picker. */
#year-dock {
  position: absolute;
  bottom: max(env(safe-area-inset-bottom, 0px), 16px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 8px 14px 10px;
  width: auto;
  max-width: calc(100vw - 32px);
  z-index: 20;
  background: transparent;
  border: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* ===== Inline round-result panel =====
   Replaces year-dock + submit pill after the user submits their guess.
   Shows the actual location, scoring, Wikipedia thumb + summary, Next button. */
#round-result {
  position: absolute;
  bottom: max(env(safe-area-inset-bottom, 0px), 16px);
  left: 50%;
  transform: translateX(-50%);
  width: min(720px, calc(100vw - 32px));
  padding: 18px 22px 18px;
  z-index: 33;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--bg-panel-strong);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  box-shadow:
    0 16px 48px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
  animation: rr-pop 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes rr-pop {
  from { opacity: 0; transform: translateX(-50%) translateY(12px) scale(0.97); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}
#round-result[hidden] { display: none; }
#year-dock[hidden] { display: none; }

.rr-header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
}
.rr-header-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}
.rr-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  /* With the View-Panorama pill moved out of the panel, the title can use
     the full row width. Wrap on word boundary if it ever spills. */
  line-height: 1.15;
  word-break: normal;
  overflow-wrap: break-word;
}
/* Coordinate row hidden globally — Eric: "coordinates mean nothing to anyone".
   Element kept in DOM so any cross-PR code that reads it doesn't error. */
.rr-actual-meta { display: none !important; }

/* Calibration badge — "Modern · Easy scene" type label under the title.
   Shows the era and difficulty so players understand why the scoring
   curve was tight or forgiving on this round. */
.rr-calibration {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-soft, #c8a05a);
  opacity: 0.85;
  margin-top: 2px;
}
.rr-calibration .rr-cal-dot {
  opacity: 0.5;
  margin: 0 6px;
}
.rr-calibration .rr-cal-diff-easy   { color: #84c98a; }
.rr-calibration .rr-cal-diff-medium { color: #d8c577; }
.rr-calibration .rr-cal-diff-hard   { color: #e08a6f; }

/* Ground-truth uncertainty band credit — shows when player guess fell
   within historical scholarly consensus (e.g. "circa 2530 BCE ±500 yrs"). */
.rr-band-credit {
  margin-top: 6px;
  padding: 6px 10px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--gold-soft, #c8a05a);
  background: rgba(132, 201, 138, 0.08);
  border: 1px solid rgba(132, 201, 138, 0.25);
  border-radius: 6px;
}
.rr-band-credit strong { color: #a4d9a8; }

/* Panorama-toggle pill — peeks at the 360° scene without losing the map.
   Eric pulled this OUT of the result-panel header so the scene title can
   take the full single-line width. The pill is now a floating chip
   anchored above the year-dock area, only visible during result mode. */
.rr-toggle-pano {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: rgba(18, 14, 10, 0.92);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  cursor: pointer;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease;
  flex: 0 0 auto;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
}
.rr-toggle-pano:focus-visible {
  background: rgba(28, 22, 14, 0.98);
  border-color: var(--gold);
  color: var(--gold-highlight);
  outline: none;
  transform: translateY(-1px);
}
@media (hover: hover) {
  .rr-toggle-pano:hover {
    background: rgba(28, 22, 14, 0.98);
    border-color: var(--gold);
    color: var(--gold-highlight);
    outline: none;
    transform: translateY(-1px);
  }
}
.rr-toggle-pano svg {
  width: 14px;
  height: 14px;
}
/* In-card placement: pill sits as its own row in #round-result's flex column,
   centered above the .rr-actions row (Wikipedia link + Next round). */
#round-result > .rr-toggle-pano {
  align-self: center;
}
#round-result > .rr-toggle-pano[hidden] { display: none; }

/* Peek mode: card collapses to a strip and hides .rr-summary / .rr-actions /
   .rr-body / .rr-year-callout. Float the button above the strip so it
   stays clickable (this is how the user exits peek) without bloating
   the strip's height. */
body.rr-pano-peek #round-result > .rr-toggle-pano {
  position: absolute;
  top: -52px;
  left: 50%;
  align-self: auto;
  transform: translateX(-50%);
  z-index: 35;
}
body.rr-pano-peek #round-result > .rr-toggle-pano:focus-visible,
body.rr-pano-peek #round-result > .rr-toggle-pano:hover {
  transform: translateX(-50%) translateY(-1px);
}

/* Year recall callout — replaces the old "Year delta" stat row */
.rr-year-callout {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 8px 10px;
  padding: 8px 14px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  font-family: var(--font-display);
  font-size: 13px;
}
.rr-year-callout[hidden] { display: none; }
.rr-yc-label {
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.rr-yc-value {
  font-weight: 700;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.rr-yc-arrow,
.rr-yc-sep {
  color: var(--text-muted);
  font-size: 12px;
}
.rr-yc-diff {
  font-size: 11px;
  letter-spacing: 0.10em;
  color: var(--text-muted);
}

.rr-body {
  display: flex;
  flex-direction: row;
  gap: 14px;
  align-items: stretch;
  min-height: 0;
}
.rr-thumb {
  width: 96px;
  height: 96px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--border-soft);
}
.rr-thumb.hidden { display: none; }

.rr-stats {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  align-content: center;
}
.rr-stat {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 12px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
}
/* Progress bar BEHIND each stat (0 → 5000, total 0 → 10000) */
.rr-stat-bar {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.rr-stat-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: linear-gradient(
    90deg,
    rgba(212, 165, 116, 0.04) 0%,
    rgba(245, 230, 192, 0.10) 100%);
  transition: width 240ms ease-out;
}
.rr-stat > *:not(.rr-stat-bar) { position: relative; z-index: 1; }
.rr-stat-label {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.rr-stat-value {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
}
.rr-stat-sub {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}
/* Dim "/ 5000 PTS" suffix — gives players a frame of reference for what
   each row's max is without competing visually with their score. */
.rr-of-max {
  color: var(--text-muted);
  font-weight: 500;
  opacity: 0.75;
  letter-spacing: 0.04em;
}
.rr-stat.rr-total {
  /* Match Distance/Year row padding so the bar/text sizes are consistent.
     Eric: "total bar and text shouldn't be different sizes" — emphasis
     stays via background gradient + metallic value, not size jump. */
  padding: 8px 12px;
  background: linear-gradient(135deg, rgba(212, 165, 116, 0.18), rgba(245, 230, 192, 0.06));
  border: 1px solid var(--border-strong);
}
.rr-stat.rr-total .rr-stat-value {
  /* Same size as the Distance/Year value (16px); metallic gradient still
     reads as "the important number" via color, not type scale. */
  font-size: 16px;
  font-weight: 700;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  letter-spacing: 0.04em;
}
.rr-stat.rr-total .rr-stat-bar-fill {
  background: linear-gradient(
    90deg,
    rgba(212, 165, 116, 0.18) 0%,
    rgba(245, 230, 192, 0.30) 100%);
}
@keyframes rr-total-flash {
  0%   { box-shadow: inset 0 0 0 1px var(--border-strong), 0 0 0 0 rgba(245, 230, 192, 0.0); }
  35%  { box-shadow: inset 0 0 0 1px var(--gold), 0 0 28px rgba(245, 230, 192, 0.55); }
  100% { box-shadow: inset 0 0 0 1px var(--border-strong), 0 0 0 0 rgba(245, 230, 192, 0); }
}
.rr-stat.rr-total.rr-flash {
  animation: rr-total-flash 700ms ease-out 1;
}

.rr-summary {
  /* Body typography — matches the rest of the panel body. Eric: "font is
     inconsistent. fix" — the body text and the inline Read-more button
     used to mix Inter (body) with Cinzel (display). Both are now Inter
     so the one-sentence summary reads as a coherent block. */
  margin: 0;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  font-weight: 400;
  color: var(--text-primary);
  letter-spacing: 0;
  text-align: justify;
  hyphens: auto;
}
.rr-summary[hidden] { display: none; }
.rr-summary-text {
  display: inline;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  font-weight: 400;
  color: var(--text-primary);
  letter-spacing: 0;
  text-align: justify;
  hyphens: auto;
}
.rr-summary-toggle {
  margin-left: 6px;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--gold);
  /* Match the surrounding body text — was Cinzel uppercase before, which
     looked like a stat label dropped into a paragraph. */
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: baseline;
  transition: color 180ms ease;
}
.rr-summary-toggle:focus-visible {
  color: var(--gold-highlight);
  outline: none;
}
@media (hover: hover) {
  .rr-summary-toggle:hover {
    color: var(--gold-highlight);
    outline: none;
  }
}
@media (max-width: 600px) {
  /* Default-state mobile clamp — even the first sentence trims with ellipsis
     if it spills beyond two lines. Expanded state removes the clamp. */
  .rr-summary:not(.expanded) .rr-summary-text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

.rr-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.rr-link {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  text-decoration: none;
  transition: color 180ms ease;
}
@media (hover: hover) {
  .rr-link:hover { color: var(--gold-highlight); text-decoration: underline; }
}
.rr-link:empty, .rr-link[style*="display: none"] { visibility: hidden; }
/* Next-round CTA — Eric: "in that color i still think its a bit tame".
   Idle: gold fill + dark text + a louder pulse. Hover: champagne fill +
   white-bright text. Background-color overrides .btn-primary's dark
   gradient via !important to keep the cascade simple. */
.rr-next {
  min-width: 0;
  min-height: 52px;
  padding: 14px 42px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.24em;
  background: linear-gradient(180deg, var(--gold), var(--gold-highlight)) !important;
  color: #1a1208 !important;
  border-color: var(--gold-highlight);
  text-shadow: 0 1px 0 rgba(255, 250, 230, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 250, 230, 0.45),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 6px 22px rgba(0, 0, 0, 0.55),
    0 0 28px var(--gold-glow);
  animation: rr-next-pulse 1.1s ease-in-out infinite;
}
@keyframes rr-next-pulse {
  0%, 100% { transform: scale(1.00); box-shadow:
    inset 0 1px 0 rgba(255, 250, 230, 0.45),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 6px 22px rgba(0, 0, 0, 0.55),
    0 0 22px var(--gold-glow); }
  50%      { transform: scale(1.045); box-shadow:
    inset 0 1px 0 rgba(255, 250, 230, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 8px 28px rgba(0, 0, 0, 0.6),
    0 0 36px rgba(245, 230, 192, 0.85); }
}
@media (hover: hover) {
  .rr-next:hover {
    animation-play-state: paused;
    background: linear-gradient(180deg, #fff7e0, #f5e6c0) !important;
    border-color: #fff7e0;
    color: #15110a !important;
    transform: translateY(-1px);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.55),
      0 10px 32px rgba(0, 0, 0, 0.65),
      0 0 40px rgba(255, 247, 224, 0.85);
  }
}
@media (prefers-reduced-motion: reduce) {
  .rr-next { animation: none; }
}
/* Last-round treatment — even louder. Champagne fill, near-white at peak. */
.rr-next-finale {
  background: linear-gradient(180deg, #fff5d0, var(--gold-highlight)) !important;
  border-color: #fff5d0;
  color: #15110a !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 8px 28px rgba(0, 0, 0, 0.6),
    0 0 44px rgba(255, 245, 208, 0.85);
}
@media (hover: hover) {
  .rr-next-finale:hover {
    background: linear-gradient(180deg, #ffffff, #fff5d0) !important;
  }
}

@media (max-width: 600px) {
  #round-result { padding: 14px 16px; }
  .rr-title { font-size: 18px; }
  .rr-thumb { width: 64px; height: 64px; }
  .rr-summary { -webkit-line-clamp: 2; }
  .rr-year-callout { font-size: 12px; gap: 4px 8px; padding: 6px 10px; }

  /* Stack stat rows vertically: label/value side-by-side, points sub underneath.
     Fixes baseline-misalignment caused by .rr-stat-sub wrapping to 2 lines at
     narrow widths (the "/ 5,000 pts" column collapses below ~80px). */
  .rr-stat {
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    gap: 2px 10px;
    padding: 8px 12px;
  }
  .rr-stat-label   { grid-column: 1; grid-row: 1; align-self: end; }
  .rr-stat-value   { grid-column: 2; grid-row: 1; text-align: right; align-self: end; }
  .rr-stat-sub     { grid-column: 1 / -1; grid-row: 2; text-align: right; font-size: 11px; opacity: 0.9; }
  /* Total row has no .rr-stat-sub element — single row layout */
  .rr-stat.rr-total { grid-template-rows: auto; }
  .rr-stat.rr-total .rr-stat-value { grid-column: 2; }
}

/* Panorama-peek mode: result panel collapses to a slim bottom strip AND
   the map dock fades out so the player gets the full 360° scene back.
   Eric: "view panorama should hide the map as well". Cross-PR (B): the
   #map-dock display rule technically lives in B's HUD scope; flagging
   here so the merge is clean. */
body.rr-pano-peek #round-result {
  bottom: max(env(safe-area-inset-bottom, 0px), 12px);
  width: min(540px, calc(100vw - 32px));
  padding: 8px 14px;
  transition: padding 240ms ease, width 240ms ease;
}
body.rr-pano-peek #round-result > .rr-body,
body.rr-pano-peek #round-result > .rr-summary,
body.rr-pano-peek #round-result > .rr-actions,
body.rr-pano-peek #round-result > .rr-year-callout {
  display: none;
}
body.rr-pano-peek #round-result > .rr-header {
  align-items: center;
  justify-content: center;
}
body.rr-pano-peek #round-result .rr-title { font-size: 14px; letter-spacing: 0.04em; }

/* Hide the map dock + its overlays during pano-peek. The dashed line and
   ACTUAL pin live inside the dock so opacity:0 + pointer-events:none
   takes everything down at once. Toggle-back restores all of it. */
body.rr-pano-peek #map-dock {
  opacity: 0;
  pointer-events: none;
  transition: opacity 240ms ease;
}

/* F18 #submit-cta and the scoring-help "?" + popover were removed when the
   slider was killed. LOCK IN (.lock-in-cta, search below) is the universal
   submit now and lives inside #year-dock. The scoring-help popover only
   really made sense as context for the slider — gone too. */

/* ===== Round-indicator progress dots ===== */
.round-dots {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 4px;
}
.round-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(245, 230, 192, 0.18);
  transition: background 320ms ease, box-shadow 320ms ease, transform 320ms ease;
}
.round-dot.filled {
  background: var(--gold-highlight);
  box-shadow: 0 0 6px var(--gold-glow);
}
.round-dot.current {
  background: var(--gold);
  transform: scale(1.25);
}
@media (max-width: 480px) {
  .round-dots { display: none; }   /* not enough room on tiny phones */
}

/* ===== Score-chip pop on update ===== */
.score-chip.bumping #score-value {
  display: inline-block;
  animation: score-bump 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes score-bump {
  0%   { transform: scale(1); color: var(--gold-highlight); }
  40%  { transform: scale(1.18); color: var(--gold-highlight); text-shadow: 0 0 12px var(--gold-glow); }
  100% { transform: scale(1); color: inherit; }
}

/* ===== Map drag-pin hint (shown briefly after first pin drop) ===== */
.map-drag-hint {
  position: absolute;
  left: 50%;
  bottom: -8px;
  transform: translate(-50%, 100%);
  padding: 6px 12px;
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 220ms ease, transform 220ms ease;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  z-index: 4;
}
.map-drag-hint.visible {
  opacity: 1;
  transform: translate(-50%, calc(100% + 4px));
}

/* ===== Hide Leaflet zoom controls in collapsed/idle map dock state =====
   The +/- chrome covers most of the 320×220 mini-map and adds visual noise.
   They reappear when the dock is .expanded or .locked (during result mode). */
#map-dock:not(.expanded):not(.locked) .leaflet-control-zoom {
  display: none;
}

/* ===== Settings toggle row (Visuals / Accessibility checkboxes) ===== */
.settings-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 4px 2px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
}
.settings-toggle input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 32px;
  height: 18px;
  border-radius: 999px;
  background: rgba(120, 100, 80, 0.3);
  border: 1px solid var(--border-soft);
  cursor: pointer;
  position: relative;
  transition: background 180ms ease, border-color 180ms ease;
  flex: 0 0 32px;
}
.settings-toggle input[type="checkbox"]::before {
  content: '';
  position: absolute;
  top: 1px;
  left: 1px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--gold-highlight);
  transition: transform 180ms cubic-bezier(0.32, 0.72, 0, 1);
}
.settings-toggle input[type="checkbox"]:checked {
  background: rgba(212, 165, 116, 0.45);
  border-color: var(--border-strong);
}
.settings-toggle input[type="checkbox"]:checked::before {
  transform: translateX(14px);
}
.settings-toggle-label {
  flex: 1;
  user-select: none;
}

/* Accessibility-driven tweaks (toggled by JS adding body classes). */
body.high-contrast-hud .glass-chip,
body.high-contrast-hud #map-dock {
  background: var(--bg-panel-strong);
  border-color: var(--border-strong);
}
body.large-text {
  font-size: 17px;
}
body.large-text .glass-chip {
  font-size: calc(1em + 1px);
}

/* ===== VR mode hides all glass UI ===== */
body.in-vr #hud-tl,
body.in-vr #hud-bl,
body.in-vr #map-dock,
body.in-vr #year-dock,
body.in-vr #toast,
body.in-vr #screen-game.active::after { display: none; }

/* ===== Shake — used when user hits Enter without a pin dropped ===== */
@keyframes year-dock-shake {
  0%, 100% { transform: translateX(-50%); }
  20%      { transform: translateX(calc(-50% - 8px)); }
  40%      { transform: translateX(calc(-50% + 8px)); }
  60%      { transform: translateX(calc(-50% - 5px)); }
  80%      { transform: translateX(calc(-50% + 5px)); }
}
#year-dock.shake { animation: year-dock-shake 360ms cubic-bezier(0.36, 0.07, 0.19, 0.97); }

/* ===== Bottom-left HUD (in-game: exit + settings cluster) =====
   Row layout, exit chip first, settings cog right of it. Sits bottom-left
   so the cursor path from year-dock (bottom-center) to these chips
   doesn't cross the map-dock (top-right) and trigger its hover-expand. */
#hud-bl {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  z-index: 33;
}

/* Settings popover — opens UP from the cog, anchored to cluster left */
#settings-panel {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 0;
  transform-origin: bottom left;
  animation: settings-pop 220ms cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes settings-pop {
  from { opacity: 0; transform: translateY(-8px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
#settings-panel[hidden] { display: none; }
.settings-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.settings-label {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.select-wrap {
  position: relative;
  display: block;
}
.select-wrap select {
  width: 100%;
  padding: 10px 36px 10px 14px;
  font: inherit;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  .select-wrap select:hover { background: rgba(245, 230, 192, 0.07); border-color: var(--border-strong); }
}
.select-wrap select:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.select-wrap select option { background: #1a1612; color: var(--text-primary); }
.select-caret {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--gold);
  pointer-events: none;
}

/* ===== Reduced motion ===== */
@media (prefers-reduced-motion: reduce) {
  #map-dock,
  .glass-chip.btn,
  .era-chip {
    transition: none !important;
  }
  #map-dock.no-pin { animation: none; }
  .title-bg-video.active { animation: none; }
  .title-bg-video { transition: none; }
}

/* ===== Narrow / mobile breakpoint =====
   Year-dock auto-sizes around the picker pill now (no slider chrome to
   stretch wide). Map-dock shrinks to the top-right corner. The in-game
   chip cluster stays bottom-left out of the dock's footprint. */
@media (max-width: 760px) {
  #map-dock {
    width: 200px;
    height: 140px;
    top: calc(env(safe-area-inset-top, 0px) + 12px);
    right: max(env(safe-area-inset-right, 0px), 12px);
  }
  #map-dock.expanded {
    width: calc(100vw - 24px);
    height: 55vh;
    top: calc(env(safe-area-inset-top, 0px) + 12px);
    right: max(env(safe-area-inset-right, 0px), 12px);
  }
  /* Lift settings/exit cluster above the picker dock so they don't sit on
     top of it. Picker is ~100-120px tall plus its 16px bottom margin →
     ~130px clearance covers it. */
  #hud-bl {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 130px);
    left: max(env(safe-area-inset-left, 0px), 12px);
  }
}
@media (max-width: 480px) {
  #map-dock {
    width: 160px;
    height: 110px;
    top: calc(env(safe-area-inset-top, 0px) + 12px);
  }
  #map-dock.expanded {
    top: calc(env(safe-area-inset-top, 0px) + 12px);
  }
  .glass-chip { padding: 8px 12px; font-size: 13px; min-height: 40px; }
  .glass-chip.btn.icon-only { width: 40px; height: 40px; }
  .chip-icon { width: 16px; height: 16px; flex: 0 0 16px; }
}

/* ===== Sign-in modal ===== */
.signin-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 7, 10, 0.78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  animation: signin-fade 220ms ease-out;
}
.signin-overlay[hidden] { display: none; }
@keyframes signin-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.signin-modal {
  position: relative;
  width: min(420px, calc(100vw - 32px));
  padding: 36px 32px 28px;
  background: linear-gradient(180deg, rgba(28, 22, 16, 0.96), rgba(14, 10, 8, 0.98));
  border: 1px solid var(--border-strong);
  border-radius: 16px;
  box-shadow:
    0 32px 80px rgba(0, 0, 0, 0.7),
    inset 0 1px 0 rgba(245, 230, 192, 0.08);
  animation: signin-pop 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes signin-pop {
  from { opacity: 0; transform: translateY(16px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.signin-close {
  position: absolute;
  top: 12px; right: 12px;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease;
}
@media (hover: hover) {
  .signin-close:hover { color: var(--gold-highlight); background: rgba(245, 230, 192, 0.08); }
}
.signin-close svg { width: 16px; height: 16px; }
.signin-heading {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.signin-sub {
  margin: 0 0 22px;
  font-family: var(--font-body);
  font-size: 13px;
  text-align: center;
  color: var(--text-muted);
}

/* Shared modal layout for the Casual 2-step demo wall (B3) — used by
   #casual-signin-prompt-modal (anon 3-play cap → signin) and
   #casual-trial-prompt-modal (signed-in 5-play cap → trial). Backdrop +
   panel chrome come from .signin-overlay / .signin-modal above. */
.casual-coming-sub2 {
  margin-top: -10px;
  margin-bottom: 24px;
}
.casual-coming-cta-row {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}
.casual-coming-cta-row .btn-primary,
.casual-coming-cta-row .btn-secondary-ghost {
  flex: 0 1 auto;
  min-width: 130px;
}

.signin-providers {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
}
.signin-provider {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 18px;
  background: rgba(245, 245, 245, 0.96);
  color: #1a1a1a;
  border: 1px solid rgba(245, 230, 192, 0.18);
  border-radius: 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  transition: transform 180ms ease, box-shadow 180ms ease, background 180ms ease;
}
@media (hover: hover) {
  .signin-provider:hover {
    background: rgba(255, 255, 255, 1);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  }
}
.signin-provider[data-provider="facebook"] { background: #1877F2; color: #fff; border-color: #1877F2; }
@media (hover: hover) {
  .signin-provider[data-provider="facebook"]:hover { background: #166fe0; }
}
.signin-provider[data-provider="facebook"] .signin-icon path { fill: #fff; }
.signin-provider[data-provider="apple"] { background: #000; color: #fff; border-color: #000; }
@media (hover: hover) {
  .signin-provider[data-provider="apple"]:hover { background: #1a1a1a; }
}
.signin-provider[data-provider="x"] { background: #000; color: #fff; border-color: #000; }
@media (hover: hover) {
  .signin-provider[data-provider="x"]:hover { background: #1a1a1a; }
}
.signin-icon { width: 18px; height: 18px; flex: 0 0 18px; }
.signin-disclaimer {
  margin: 0 0 14px;
  font-family: var(--font-body);
  font-size: 11px;
  text-align: center;
  color: var(--text-subtle);
  line-height: 1.5;
}
.signin-guest {
  display: block;
  width: 100%;
  padding: 10px;
  background: transparent;
  border: none;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 180ms ease;
}
@media (hover: hover) {
  .signin-guest:hover { color: var(--gold-highlight); }
}

/* ===== Toast (top-anchored to clear bottom UI) ===== */
#toast {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 76px);
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  background: var(--bg-panel-strong);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid var(--border-soft);
  color: var(--text-primary);
  padding: 12px 20px;
  border-radius: 10px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, transform 0.25s;
  z-index: 40;
  max-width: 80vw;
  text-align: center;
}
#toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ===== RESULT / FINAL / DONE screens ===== */
#screen-result, #screen-final, #screen-done {
  background: var(--bg-deep);
  overflow-y: auto;
  position: relative;
}

/* Cinematic blurred background behind the final-screen content, sourced
   from the player's best-scored scene. Matches the title-vignette pattern. */
.final-bg {
  position: fixed;
  inset: 0;
  background-position: center;
  background-size: cover;
  filter: blur(8px) brightness(0.45);
  opacity: 0;
  transform: scale(1.06); /* hide blur edges */
  transition: opacity 720ms ease;
  pointer-events: none;
  z-index: 0;
}
#screen-final.active .final-bg.has-bg,
#screen-done.active  .final-bg.has-bg { opacity: 1; }
.final-vignette {
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse at center, rgba(8, 7, 10, 0.0) 0%, rgba(8, 7, 10, 0.55) 70%, rgba(8, 7, 10, 0.85) 100%);
  pointer-events: none;
  z-index: 1;
}

.result-content, .final-content, .done-content {
  position: relative;
  z-index: 2;
  max-width: 720px;
  margin: 0 auto;
  padding: 32px 24px calc(32px + env(safe-area-inset-bottom, 0px));
  padding-top: calc(32px + env(safe-area-inset-top, 0px));
  display: flex;
  flex-direction: column;
  gap: 20px;
  text-align: center;
  align-items: center;
}
.result-content h2, .final-content h2, .done-content h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(32px, 7vw, 48px);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.5));
}
.result-stats {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}
.stat {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: baseline;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 14px 18px;
}
.stat .label {
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.stat .value {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--gold-highlight);
}
.stat .sub {
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--gold);
  font-weight: 600;
  letter-spacing: 0.06em;
  margin-left: 8px;
}
.stat.total {
  background: linear-gradient(135deg, rgba(212, 165, 116, 0.18), rgba(245, 230, 192, 0.06));
  border: 1px solid var(--border-strong);
}
.stat.total .value {
  font-size: 26px;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.actual-card {
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 14px 18px;
  width: 100%;
}
.actual-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  margin-bottom: 4px;
}
.actual-coords {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-muted);
}

.wiki-card {
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 16px;
  display: flex;
  flex-direction: row;
  gap: 14px;
  align-items: flex-start;
  overflow: hidden;
  width: 100%;
  text-align: left;
}
.wiki-card.hidden { display: none; }
.wiki-card img#result-wiki-thumb {
  width: 96px;
  height: 96px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 6px;
  background: var(--bg-deep);
  display: block;
}
.wiki-card img#result-wiki-thumb.hidden { display: none; }
.wiki-card .wiki-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.wiki-card p {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-primary);
}
.wiki-card a {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--gold);
}
@media (max-width: 480px) {
  .wiki-card { flex-direction: column; }
  .wiki-card img#result-wiki-thumb { width: 100%; height: 160px; }
}

/* ===== FINAL / DONE screens ===== */
.final-total {
  font-family: var(--font-display);
  font-size: clamp(56px, 10vw, 84px);
  font-weight: 700;
  text-align: center;
  letter-spacing: 0.02em;
  margin: 4px 0 0;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 2px 32px rgba(212, 165, 116, 0.22);
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.5));
  font-variant-numeric: tabular-nums;
}
.final-total-meta {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: -8px;
}
.final-best {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}
/* Author display: inline-block overrides the user-agent [hidden]
   display: none, so we have to re-assert it explicitly. Otherwise the
   banner stays visible after JS toggles hidden=true (e.g. on the daily
   re-view path where isNewBest=false on the second render). */
.final-banner[hidden] { display: none; }
.final-banner {
  display: inline-block;
  padding: 8px 18px;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.30em;
  text-transform: uppercase;
  color: var(--bg-deep);
  background: var(--metallic-gradient);
  border-radius: 999px;
  box-shadow: 0 0 24px rgba(245, 230, 192, 0.55);
}
.final-banner.flash {
  animation: final-banner-flash 1100ms ease-out 1;
}
@keyframes final-banner-flash {
  0%   { transform: scale(0.6); opacity: 0; }
  35%  { transform: scale(1.08); opacity: 1; box-shadow: 0 0 48px rgba(245, 230, 192, 0.8); }
  60%  { transform: scale(0.98); }
  100% { transform: scale(1); opacity: 1; box-shadow: 0 0 24px rgba(245, 230, 192, 0.55); }
}

/* ===== Sign-in conversion banner (Stream I) =====
   Glass panel on final screen for signed-out players who break the 25k
   total-score floor. Soft prompt — never blocks anything, persistent
   dismiss per gameId. */
.signin-banner {
  position: relative;
  width: 100%;
  max-width: 520px;
  margin: 14px auto 4px;
  padding: 12px 38px 12px 16px;
  background: var(--bg-panel);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid rgba(212, 165, 116, 0.28);
  border-radius: 14px;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.08);
}
.signin-banner[hidden] { display: none; }
.signin-banner-content {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
}
.signin-banner-icon {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--gold);
}
.signin-banner-icon svg {
  width: 22px;
  height: 22px;
  filter: drop-shadow(0 0 6px rgba(212, 165, 116, 0.45));
}
.signin-banner-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.signin-banner-title {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.signin-banner-copy {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
}
.signin-banner-cta {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 9px 18px;
  border-radius: 8px;
  border: 1px solid rgba(245, 230, 192, 0.34);
  color: var(--bg-deep);
  background: linear-gradient(180deg, var(--gold) 0%, var(--gold-deep) 100%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.22),
    0 4px 14px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  white-space: nowrap;
  transition: box-shadow 160ms ease, background 160ms ease;
}
.signin-banner-cta:hover {
  background: linear-gradient(180deg, var(--gold-highlight) 0%, var(--gold) 100%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.30),
    0 6px 18px var(--gold-glow);
}
.signin-banner-cta:focus-visible {
  outline: 2px solid var(--gold-highlight);
  outline-offset: 2px;
}
.signin-banner-dismiss {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 6px;
  color: var(--text-subtle);
  cursor: pointer;
  padding: 0;
  transition: color 140ms ease, background 140ms ease;
}
.signin-banner-dismiss svg {
  width: 14px;
  height: 14px;
}
.signin-banner-dismiss:hover {
  color: var(--gold-highlight);
  background: rgba(245, 230, 192, 0.06);
}
.signin-banner-dismiss:focus-visible {
  outline: 2px solid var(--gold-highlight);
  outline-offset: 2px;
}
@media (max-width: 480px) {
  .signin-banner {
    padding: 14px 36px 14px 14px;
  }
  .signin-banner-content {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    text-align: center;
  }
  .signin-banner-icon {
    align-self: center;
  }
  .signin-banner-cta {
    width: 100%;
  }
}

.final-section {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.final-section[hidden] { display: none; }
.final-section-title {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: left;
}
.final-allseen {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 14px 16px;
}

/* Per-era recap rows */
.final-era-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.final-era-row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 12px;
  align-items: baseline;
  padding: 10px 14px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
}
/* Era-tinted score bar behind .final-era-row content. Width is set by
   renderEraRecap() to (era_total / era_max) * 100, animated from 0%.
   Uses --era-glow which is bound below per data-era so the wash matches
   the field-report chart palette. Mirrors .rh-fill on round-history rows
   so the per-era recap reads the same visual language as the round list. */
.fe-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--era-glow, var(--gold-soft, #d4a574)) 8%, transparent) 0%,
    color-mix(in srgb, var(--era-glow, var(--gold-soft, #d4a574)) 22%, transparent) 100%);
  pointer-events: none;
  z-index: 0;
  transition: width 700ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .fe-fill { transition: none; }
}
.final-era-row > *:not(.fe-fill) {
  position: relative;
  z-index: 1;
}
.final-era-row[data-era="ancient"]     { --era-glow: var(--era-ancient); }
.final-era-row[data-era="medieval"]    { --era-glow: var(--era-medieval); }
.final-era-row[data-era="renaissance"] { --era-glow: var(--era-renaissance); }
.final-era-row[data-era="modern"]      { --era-glow: var(--era-modern); }
.fe-name {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  text-align: left;
}
.fe-score {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.fe-of {
  color: var(--text-muted);
  font-size: 11px;
  letter-spacing: 0.04em;
}
.fe-rounds {
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* "See how you stacked up" post-submit CTA. Sits above #round-history on
   #screen-final, hidden until showLeaderboardSubmitResult populates the
   rank text. Era-tinted gradient mirrors the active leaderboard pill so
   the CTA visually pre-announces the destination it routes to. */
.final-stacked-up-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 100%;
  margin: 4px 0 14px;
  padding: 12px 16px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--gold) 18%, transparent) 0%,
    color-mix(in srgb, var(--gold) 8%, transparent) 100%);
  border: 1px solid color-mix(in srgb, var(--gold) 50%, transparent);
  border-radius: 10px;
  font-family: var(--font-display);
  color: var(--gold-highlight);
  cursor: pointer;
  text-align: left;
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease, background 200ms ease;
  animation: fsu-pulse-in 480ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes fsu-pulse-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .final-stacked-up-cta { animation: none; }
}
@media (hover: hover) {
  .final-stacked-up-cta:hover {
    transform: translateY(-1px);
    border-color: var(--gold);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3), 0 0 14px var(--gold-glow);
  }
  .final-stacked-up-cta:hover .fsu-arrow {
    transform: translateX(3px);
  }
}
.final-stacked-up-cta:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.fsu-icon {
  flex: 0 0 auto;
  display: inline-flex;
  width: 28px;
  height: 28px;
  align-items: center;
  justify-content: center;
  color: var(--gold);
}
.fsu-icon svg { width: 100%; height: 100%; }
.fsu-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fsu-headline {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
}
.fsu-sub {
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  text-transform: none;
}
.fsu-arrow {
  flex: 0 0 auto;
  display: inline-flex;
  width: 22px;
  height: 22px;
  align-items: center;
  justify-content: center;
  color: var(--gold);
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
}
.fsu-arrow svg { width: 100%; height: 100%; }
@media (max-width: 600px) {
  .final-stacked-up-cta { padding: 10px 12px; gap: 10px; }
  .fsu-headline { font-size: 11px; letter-spacing: 0.12em; }
  .fsu-sub { font-size: 10px; }
  .fsu-icon { width: 22px; height: 22px; }
  .fsu-arrow { width: 18px; height: 18px; }
}

/* Round-by-round timeline rows */
.round-history {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
}
.round-history-row {
  position: relative;
  display: grid;
  grid-template-columns: 24px 22px 1fr auto auto;
  gap: 10px;
  align-items: center;
  padding: 8px 12px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  font-family: var(--font-display);
  overflow: hidden;
  cursor: pointer;
}
/* Bar-fill behind each row: animates from 0 → (round.total/10000)*100% on
   screen entry. Mirrors the in-game .rr-stat-bar-fill gradient so the
   final-screen recap reads as the same visual language as the per-round
   reveal. Width is set inline by renderRoundHistory(). */
.rh-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: linear-gradient(
    90deg,
    rgba(212, 165, 116, 0.04) 0%,
    rgba(245, 230, 192, 0.10) 100%);
  pointer-events: none;
  z-index: 0;
  transition: width 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.rh-fill.is-perfect {
  /* Mirror .rr-stat.rr-total .rr-stat-bar-fill gradient — high-scoring
     rounds (>= 8000) get the brighter fill the in-game total bar uses. */
  background: linear-gradient(
    90deg,
    rgba(212, 165, 116, 0.18) 0%,
    rgba(245, 230, 192, 0.30) 100%);
}
@media (prefers-reduced-motion: reduce) {
  .rh-fill { transition: none; }
}
.round-history-row > *:not(.rh-fill) {
  position: relative;
  z-index: 1;
}
@media (hover: hover) {
  .round-history-row:hover {
    background: rgba(245, 230, 192, 0.08);
    border-color: var(--border-strong);
  }
}
.round-history-row:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
/* Hover-only chevron affordance: the row already has cursor:pointer, but
   the original UI gave no other tap-me cue. The ›-glyph fades in on
   hover (and is keyboard-accessible via :focus-visible) so the click
   target is obviously discoverable without changing layout — pseudo-
   element overlays the row, so adding it doesn't shift real columns. */
.round-history-row::after {
  content: "›";
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%) translateX(-3px);
  font-size: 18px;
  font-weight: 600;
  color: var(--gold-highlight);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
  z-index: 2;
}
@media (hover: hover) {
  .round-history-row:hover::after {
    opacity: 0.8;
    transform: translateY(-50%) translateX(0);
  }
}
.round-history-row:focus-visible::after {
  opacity: 0.8;
  transform: translateY(-50%) translateX(0);
}
@media (prefers-reduced-motion: reduce) {
  .round-history-row::after { transition: none; }
}

/* One-time hint chip below #round-history. Visible until the user dismisses
   it (X) or clicks any round (since clicking IS the action being hinted).
   State persists in localStorage as wit-hint-final-tap-seen. */
.round-history-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 8px 12px;
  background: rgba(245, 230, 192, 0.06);
  border: 1px dashed color-mix(in srgb, var(--gold) 35%, transparent);
  border-radius: 8px;
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  animation: round-history-hint-in 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes round-history-hint-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .round-history-hint { animation: none; }
}
.round-history-hint-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
  color: var(--gold-highlight);
  flex: 0 0 auto;
}
.round-history-hint-icon svg { width: 100%; height: 100%; }
.round-history-hint-text {
  flex: 1 1 auto;
  text-transform: uppercase;
}
.round-history-hint-dismiss {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 4px;
  transition: color 160ms ease, background 160ms ease;
}
.round-history-hint-dismiss svg { width: 12px; height: 12px; }
.round-history-hint-dismiss:hover {
  color: var(--gold-highlight);
  background: rgba(245, 230, 192, 0.08);
}
.round-history-hint-dismiss:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.rh-num {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--text-muted);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.rh-name {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--gold-highlight);
  text-align: left;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
/* Stats: 4-column inner grid so dist# / unit / year# / direction line up
   across rows even with mixed digit widths (5.4k vs 1.3k vs 11.0k, etc.).
   Numbers right-align in their column; suffixes left-align next to them.
   tabular-nums on the wrapper so monospaced digits stack vertically. */
.rh-stats {
  display: inline-grid;
  grid-template-columns: 44px 22px 52px 46px;
  column-gap: 4px;
  align-items: baseline;
  font-size: 10px;
  letter-spacing: 0.10em;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.rh-dist-num,
.rh-year-num { text-align: right; color: var(--text-primary); opacity: 0.78; }
.rh-dist-unit,
.rh-year-dir { text-align: left; color: var(--text-muted); }
.rh-total {
  font-size: 20px;
  font-weight: 700;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  text-align: right;
  white-space: nowrap;
}
.rh-of {
  display: inline-block;
  font-size: 10px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.06em;
  margin-left: 2px;
}
/* Difficulty badge between rh-num and rh-name. Letter-only (E/M/H) so
   it stays compact on narrow rows. Background tint maps to the same
   semantic colors used by the in-game .rr-cal-diff-* labels: green for
   easy, amber for medium, coral for hard. The unknown variant collapses
   into an empty 22px gutter so existing rows that pre-date the
   difficulty field don't visually shift. */
.rh-diff {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 18px;
  border-radius: 5px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  border: 1px solid transparent;
  background: rgba(245, 230, 192, 0.08);
  color: var(--text-muted);
  text-align: center;
}
.rh-diff--easy {
  color: #9ec59b;
  border-color: color-mix(in srgb, #9ec59b 50%, transparent);
  background: color-mix(in srgb, #9ec59b 12%, transparent);
}
.rh-diff--medium {
  color: #e0b573;
  border-color: color-mix(in srgb, #e0b573 50%, transparent);
  background: color-mix(in srgb, #e0b573 12%, transparent);
}
.rh-diff--hard {
  color: #d68a7a;
  border-color: color-mix(in srgb, #d68a7a 50%, transparent);
  background: color-mix(in srgb, #d68a7a 14%, transparent);
}
.rh-diff--unknown {
  background: transparent;
  border-color: transparent;
}

/* =====================================================================
   Round-replay modal (#round-replay-modal): re-shows wiki summary +
   thumb + stats from a past round. Triggered by clicking a
   .round-history-row on the final/done screens. Visual language
   matches the in-game .glass-panel result reveal so the user gets
   the same affordance they had at round-end.
   ===================================================================== */
.round-replay-modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.round-replay-modal[hidden] { display: none; }
.rrm-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(8, 7, 10, 0.75);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.rrm-panel {
  position: relative;
  width: min(520px, 100%);
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  padding: 28px 24px;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: center;
  animation: rrm-pop-in 240ms cubic-bezier(0.22, 1, 0.36, 1) 1;
}
@keyframes rrm-pop-in {
  0%   { transform: scale(0.94) translateY(8px); opacity: 0; }
  100% { transform: scale(1) translateY(0);     opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .rrm-panel { animation: none; }
}
.rrm-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border-soft);
  border-radius: 50%;
  background: rgba(8, 7, 10, 0.45);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.rrm-close svg { width: 14px; height: 14px; }
.rrm-close:hover,
.rrm-close:focus-visible {
  color: var(--gold-highlight);
  border-color: var(--gold);
  background: rgba(245, 230, 192, 0.06);
  outline: none;
}
.rrm-title {
  margin: 0 36px 0 0;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--gold-highlight);
}
.rrm-yearline {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  flex-wrap: wrap;
}
.rrm-yc-label {
  font-size: 10px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.rrm-yc-value {
  font-size: 15px;
  font-weight: 600;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.rrm-yc-guess {
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.rrm-thumb {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  max-height: 240px;
  border-radius: 8px;
  border: 1px solid var(--border-soft);
  background: rgba(0, 0, 0, 0.35);
}
.rrm-stats {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
}
.rrm-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 8px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
.rrm-stat-label {
  font-family: var(--font-display);
  font-size: 9px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.rrm-stat-value {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.rrm-stat-total { border-color: var(--border-strong); background: linear-gradient(135deg, rgba(212, 165, 116, 0.18), rgba(245, 230, 192, 0.06)); }
.rrm-stat-total .rrm-stat-value {
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.rrm-summary {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-primary);
  text-align: justify;
  hyphens: auto;
  max-height: 200px;
  overflow-y: auto;
}
.rrm-link {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  text-decoration: none;
  align-self: center;
}
.rrm-link:hover { color: var(--gold-highlight); text-decoration: underline; }
body.rrm-open { overflow: hidden; }
@media (max-width: 480px) {
  .round-replay-modal { padding: 16px; }
  .rrm-panel { padding: 22px 16px; gap: 10px; }
  .rrm-title { font-size: 16px; }
  .rrm-stats { grid-template-columns: 1fr 1fr; }
  .rrm-stat-total { grid-column: 1 / -1; }
  .rrm-thumb { max-height: 180px; }
  .rrm-summary { font-size: 12px; max-height: 160px; }
}

/* Share row on final/done — reuse .share-btn from title screen */
.final-share {
  display: flex;
  gap: 6px;
  padding: 6px;
  background: var(--bg-panel);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
}

/* Generated-image Share button (above the platform-link pill row). Primary
   gold pill matching --metallic-gradient — the dominant share affordance.
   The platform row underneath is the secondary fallback for desktop users
   who don't have Web Share API for files. */
.share-image-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 14px 30px;
  margin: 0 auto 10px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #1a0e02;
  background: var(--metallic-gradient, linear-gradient(180deg, #f5e6c0 0%, #d4a574 45%, #8b6914 100%));
  border: 1px solid var(--gold);
  border-radius: 999px;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.30),
    0 4px 16px rgba(0, 0, 0, 0.55),
    0 0 24px var(--gold-glow, rgba(212, 165, 116, 0.40));
  transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 180ms ease, opacity 180ms ease;
}
.share-image-primary svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}
.share-image-primary:hover,
.share-image-primary:focus-visible {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.40),
    0 6px 22px rgba(0, 0, 0, 0.55),
    0 0 32px var(--gold-glow, rgba(212, 165, 116, 0.55));
  outline: none;
}
.share-image-primary:active { transform: translateY(0); }
.share-image-primary[disabled],
.share-image-primary.is-busy {
  opacity: 0.7;
  cursor: progress;
  pointer-events: none;
}
.share-image-primary.is-busy::before {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(26, 14, 2, 0.30);
  border-top-color: #1a0e02;
  border-radius: 50%;
  animation: share-card-spin 700ms linear infinite;
  margin-right: 4px;
}
.share-image-primary.is-busy svg { display: none; }
@keyframes share-card-spin {
  to { transform: rotate(360deg); }
}
@media (max-width: 480px) {
  .share-image-primary {
    width: 100%;
    max-width: 360px;
  }
}
/* On iPhone, hide the X/FB/Reddit/copy pill row — the native
   share sheet (opened by the primary Share button above) covers all of
   them and more. Keep them visible everywhere else as a desktop fallback. */
body.is-iphone #screen-final .final-share,
body.is-iphone #screen-done .final-share {
  display: none;
}
/* Inverse: on desktop (no Web Share API for files), hide the big primary
   "Share your score" button — desktop users get the platform-link pill +
   Copy. Mobile keeps the prominent button (navigator.share opens the
   native sheet there, which is materially better than 4 platform links). */
@media (hover: hover) and (pointer: fine) {
  #btn-share-image-final,
  #btn-share-image-done { display: none; }
}

.final-replay {
  margin-top: 0;
  min-height: 50px;
  padding: 14px 38px;
  font-size: 14px;
  letter-spacing: 0.22em;
  border-color: var(--gold);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.10),
    0 4px 16px rgba(0, 0, 0, 0.55),
    0 0 24px var(--gold-glow);
  animation: final-replay-pulse 2400ms ease-in-out infinite;
}
@keyframes final-replay-pulse {
  0%, 100% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.10),
      0 4px 16px rgba(0, 0, 0, 0.55),
      0 0 24px var(--gold-glow);
  }
  50% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.20),
      0 6px 22px rgba(0, 0, 0, 0.60),
      0 0 38px rgba(245, 230, 192, 0.55);
  }
}
@media (prefers-reduced-motion: reduce) {
  .final-replay { animation: none; }
}

/* Final-screen action cluster: primary CTA (Travel again) is its own
   row, then Main menu + Leaderboard sit centered as identical sibling
   ghost buttons below. Both secondary buttons share a forced minimum
   width so they read as a paired choice rather than fighting for
   visual weight. */
.final-actions {
  display: flex;
  flex-direction: row;
  gap: 12px;
  margin-top: 8px;
  flex-wrap: wrap;
  justify-content: center;
}
.final-menu,
.final-leaderboard {
  min-height: 50px;
  min-width: 180px;
  padding: 14px 30px;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-family: var(--font-display);
  background: transparent;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  color: var(--gold);
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
}
@media (hover: hover) {
  .final-menu:hover,
  .final-leaderboard:hover {
    background: rgba(245, 230, 192, 0.06);
    border-color: var(--gold);
    color: var(--gold-highlight);
  }
}
.final-menu:focus-visible,
.final-leaderboard:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
@media (max-width: 480px) {
  .final-actions { flex-direction: column; align-items: stretch; }
  .final-menu,
  .final-leaderboard { font-size: 12px; padding: 12px 24px; min-height: 44px; min-width: 0; }
}

.done-content p {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.5;
}

@media (max-width: 600px) {
  .final-total { font-size: clamp(44px, 12vw, 60px); }
  .round-history-row {
    grid-template-columns: 18px 20px 1fr auto auto;
    gap: 6px;
    padding: 8px 10px;
  }
  .rh-name { font-size: 11px; }
  .rh-stats {
    grid-template-columns: 38px 18px 44px 38px;
    column-gap: 3px;
    font-size: 9px;
  }
  .rh-total { font-size: 17px; }
  .rh-of { font-size: 9px; }
  .rh-diff { width: 20px; height: 16px; font-size: 9px; }
  .final-section-title { font-size: 10px; }
  .final-era-row { padding: 8px 12px; }
  .fe-name { font-size: 11px; }
  .fe-score { font-size: 19px; }
  .fe-rounds { font-size: 9px; }
  .final-replay { font-size: 12px; padding: 12px 28px; min-height: 44px; }
}

/* ===== Leaflet markers =====
   Two visually distinct dots so guess vs. actual is unambiguous on the
   warm-sepia CartoDB Voyager tiles:
   - Guess marker: champagne-gold (matches existing theme)
   - Actual marker: coral red (#e74c3c) with a white outer ring — pops on
     map tint AND against the white dashed distance line. */
.guess-marker {
  background: transparent;
  border: none;
}
.guess-marker-dot {
  width: 18px;
  height: 18px;
  border: 3px solid var(--gold-highlight);
  background: var(--gold);
  border-radius: 50%;
  box-sizing: border-box;
  box-shadow:
    0 0 0 2px rgba(0, 0, 0, 0.55),
    0 0 12px rgba(212, 165, 116, 0.55);
}
.true-marker {
  background: transparent;
  border: none;
}
.true-marker-dot {
  width: 22px;
  height: 22px;
  border: 3px solid #ffffff;
  background: #e74c3c;
  border-radius: 50%;
  box-sizing: border-box;
  box-shadow:
    0 0 0 2px rgba(0, 0, 0, 0.6),
    0 0 14px rgba(231, 76, 60, 0.65);
  animation: true-marker-pulse 1.6s ease-out infinite;
}
@keyframes true-marker-pulse {
  0%   { box-shadow: 0 0 0 2px rgba(0,0,0,0.6), 0 0 0 0 rgba(231, 76, 60, 0.55); }
  70%  { box-shadow: 0 0 0 2px rgba(0,0,0,0.6), 0 0 0 12px rgba(231, 76, 60, 0); }
  100% { box-shadow: 0 0 0 2px rgba(0,0,0,0.6), 0 0 0 0 rgba(231, 76, 60, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .true-marker-dot { animation: none; }
}

/* Leaflet attribution: keep it readable on dark theme */
.leaflet-control-attribution {
  background: rgba(0, 0, 0, 0.5) !important;
  color: var(--text-muted) !important;
  font-family: var(--font-body) !important;
}
.leaflet-control-attribution a {
  color: var(--gold) !important;
}

/* =====================================================================
   Phone (≤480px) — UI scale-down + translucent finish
   --------------------------------------------------------------------
   Keep this block last so it overrides the per-component rules above.
   - Aggressive size reduction so the UI doesn't feel desktop-sized on iPhone.
   - Lower glass-panel alpha so panorama bleeds through (still readable).
   - Top-HUD chips ghost to opacity:0.55 idle and pop to 1 on tap — same
     behavior as the in-game map dock (#map-dock line 663/673).
   ===================================================================== */
@media (max-width: 480px) {
  :root {
    --bg-panel: rgba(18, 14, 10, 0.42);
    --bg-panel-strong: rgba(18, 14, 10, 0.62);
  }

  /* --- Title screen --- */
  .title-content h1 { font-size: clamp(22px, 7vw, 38px); }
  .tagline { font-size: 11px; letter-spacing: 0.18em; }
  .hint { font-size: 9px; letter-spacing: 0.18em; }
  .title-content .btn-primary {
    min-width: 140px;
    min-height: 40px;
    padding: 10px 22px;
    font-size: 12px;
    letter-spacing: 0.22em;
    border-radius: 8px;
  }
  .era-block { gap: 8px; margin-top: 14px; }
  /* CSS-S02: cap tracking on Cinzel labels at small sizes — 0.34em on 13px
     turned this label into a sparse string of letters, killing scanning. */
  .era-block-label { font-size: 13px; letter-spacing: 0.22em; gap: 10px; }
  .era-block-label::before,
  .era-block-label::after { width: 22px; }
  .era-segments { gap: 3px; padding: 3px; border-radius: 12px; }
  .era-seg { padding: 6px 8px; }
  .era-seg .era-name { font-size: 10px; letter-spacing: 0.14em; }
  .era-seg .era-range { font-size: 9px; letter-spacing: 0.06em; }
  .title-share { gap: 4px; padding: 4px; }
  /* CSS-S02: title-share-block-label inherits 0.36em from the 600px bp;
     drop to 0.20em on phone — at 11px, anything >0.22em hurts scanning. */
  .title-share-block-label { letter-spacing: 0.20em; }

  /* --- Top HUD chips: shrink + ghost (mimics map dock idle look) --- */
  .glass-chip {
    padding: 5px 9px;
    font-size: 11px;
    min-height: 30px;
    gap: 5px;
    border-radius: 999px;
    opacity: 0.55;
    transition: opacity 220ms ease;
  }
  .glass-chip:focus, .glass-chip:focus-within, .glass-chip:active { opacity: 1; }
  @media (hover: hover) {
    .glass-chip:hover { opacity: 1; }
  }
  .glass-chip.btn.icon-only { width: 32px; height: 32px; min-height: 32px; }
  .chip-icon { width: 13px; height: 13px; flex: 0 0 13px; }
  /* Sign-in chip: keep visibly bigger than the settings cog so it reads
     as the primary OAuth surface even on phones. Stack-with-providers UI
     is hidden — falls back to the icon-only avatar via .sign-in-stack::before. */
  .sign-in-chip {
    padding: 0;
    width: 40px;
    height: 40px;
    min-height: 40px;
    border-radius: 12px;
  }
  .sign-in-chip .sign-in-label,
  .sign-in-chip .sign-in-providers { display: none; }

  /* --- Year dock (kept readable, panel alpha already lowered above) --- */
  /* --- Year picker dock: tighter padding at narrow / short viewports --- */
  #year-dock { padding: 6px 12px 8px; gap: 4px; }

  /* --- Round result panel --- */
  #round-result { padding: 10px 14px; gap: 8px; }
  .rr-header { gap: 4px; }
  .rr-title { font-size: 14px; letter-spacing: 0.04em; }
  /* Result-T01: 9px stat labels are below the practical lower bound for
     content text. Bump to 11px (label) / 10px (sub). Keep the BIG metallic
     stat values (.rr-stat-value, .rr-yc-value) at their existing sizes —
     those are the Tier D7 highlight numbers, scaled deliberately. */
  .rr-stat-label { font-size: 11px; letter-spacing: 0.16em; }
  .rr-stat-value { font-size: 13px; }
  .rr-stat.rr-total .rr-stat-value { font-size: 13px; }
  .rr-stat-sub { font-size: 10px; }
  /* Result-T01 / Walk-F19: the "Your guess → Actual" year callout label
     sits next to the metallic year value — bump to 11px so it's readable
     at a glance. */
  .rr-yc-label { font-size: 11px; letter-spacing: 0.16em; }
  .rr-summary { font-size: 12px; line-height: 1.5; }
  .rr-summary-text { font-size: 12px; line-height: 1.5; }
  .rr-summary-toggle { font-size: 11px; }
  .rr-link { font-size: 10px; letter-spacing: 0.18em; }
  .rr-next.btn-primary { min-width: 110px; min-height: 34px; padding: 8px 16px; font-size: 11px; letter-spacing: 0.18em; }

  /* --- Settings popover --- */
  .settings-popover { max-width: 260px; padding: 12px 14px; }
  .settings-heading { font-size: 10px; letter-spacing: 0.18em; }
  .settings-action { font-size: 11px; padding: 8px 10px; }

  /* --- Toast --- */
  #toast { font-size: 11px; padding: 8px 14px; }
}

/* User-specific: Leaflet idle mini-map on portrait phones eats too much
   screen real estate. Shrink only the closed/idle state — expanded view
   stays full-width × 55vh for accurate pin drops. */
@media (max-width: 480px) and (orientation: portrait) {
  #map-dock { width: 110px; height: 78px; }
  /* Same problem as in landscape: at this size the Leaflet zoom and
     attribution cover most of the mini-map. Hide on idle; reappear on
     expand/lock. */
  #map-dock:not(.expanded):not(.locked) .leaflet-control-zoom,
  #map-dock:not(.expanded):not(.locked) .leaflet-control-attribution {
    display: none;
  }
}

/* ===== Phone-landscape restructure =====
   On a phone in landscape (≤500px tall) we shrink the HUD/map proportionally
   so the year-dock + map don't crowd the panorama. Picker stack stays a
   compact column — the dock is tiny enough now (no slider chrome) that it
   fits horizontally without rearrangement. */
@media (orientation: landscape) and (max-height: 500px) {
  /* --- HUD chips: compact --- */
  .glass-chip {
    padding: 6px 12px;
    min-height: 32px;
    font-size: 11px;
    gap: 6px;
  }
  .glass-chip.btn.icon-only {
    width: 32px;
    height: 32px;
  }
  .chip-icon {
    width: 14px;
    height: 14px;
    flex: 0 0 14px;
  }
  .hud-corner { gap: 6px; }

  /* --- HUD-TL: keep round + score + VR vertical stacking (default flow). --- */

  /* --- Map-dock: smaller idle, capped expanded.
     Chips moved to #hud-bl (above the year-dock at narrow widths) so the
     map-dock returns to the top edge with no chip clearance needed. --- */
  #map-dock {
    width: 140px;
    height: 100px;
    top: calc(env(safe-area-inset-top, 0px) + 16px);
  }
  #map-dock.expanded {
    width: min(60vw, 540px);
    height: min(80vh, 320px);
  }
  /* Phone-landscape: year-dock is a single shorter row (~50-60px tall).
     Lift cluster just above it. */
  #hud-bl {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 80px);
  }
  /* At 140×100 the Leaflet zoom buttons + attribution cover the whole
     map. Hide them while idle; they reappear on expand/lock. */
  #map-dock:not(.expanded):not(.locked) .leaflet-control-zoom,
  #map-dock:not(.expanded):not(.locked) .leaflet-control-attribution {
    display: none;
  }

  /* --- Round-result panel --- */
  #round-result {
    padding: 12px 16px;
    gap: 8px;
    width: min(900px, calc(100vw - 24px));
  }
  .rr-title { font-size: 16px; }
  .rr-thumb {
    width: 60px;
    height: 60px;
  }
  .rr-summary {
    font-size: 12px;
    line-height: 1.5;
    max-height: 3.6em;
    overflow: hidden;
  }
  .rr-summary-text { font-size: 12px; line-height: 1.5; }
  .rr-summary-toggle { font-size: 11px; }
  .rr-stat-value { font-size: 14px; }
  .rr-stat.rr-total .rr-stat-value { font-size: 14px; }
  .rr-stat-label { font-size: 9px; }
  .rr-stat-sub { font-size: 9px; }
  .rr-next.btn-primary {
    padding: 8px 16px;
    min-height: 32px;
    font-size: 11px;
  }
}


/* =====================================================================
   ===== UI Pro Max overhaul (2026-05-02) =============================
   New rules introduced by the title-page overhaul + the About screen.
   Grouped at the bottom so existing structure stays diff-friendly.
   ===================================================================== */

/* ----- Tier A1: bg-context badge ---------------------------------- */
/* Sits high on the title screen, fades in/out around each crossfade.
   Reads like a film slate: SCENE NAME with thin gold rules either
   side. Picks up the same gold gradient used by the ERA / SHARE block
   labels for visual rhyme. */
.title-bg-context {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 22px);
  left: 50%;
  transform: translate(-50%, -6px);
  z-index: 2;
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 0 10px;
  font-family: var(--font-display);
  font-size: clamp(10px, 1.1vw, 12px);
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  text-align: center;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 2px 14px rgba(212, 165, 116, 0.18);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55));
  pointer-events: none;
  opacity: 0;
  transition: opacity 600ms ease, transform 800ms cubic-bezier(0.22, 1, 0.36, 1);
  white-space: nowrap;
}
.title-bg-context::before,
.title-bg-context::after {
  content: "";
  display: inline-block;
  width: clamp(28px, 6vw, 56px);
  height: 1px;
  background: linear-gradient(90deg,
    rgba(212, 165, 116, 0) 0%,
    var(--gold) 50%,
    rgba(212, 165, 116, 0) 100%);
  align-self: center;
}
.title-bg-context.visible {
  opacity: 0.78;
  transform: translate(-50%, 0);
}
.title-bg-context-sep {
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  color: var(--gold);
  opacity: 0.65;
  font-weight: 400;
}
.title-bg-context-year {
  letter-spacing: 0.22em;
}
body.in-about .title-bg-context,
body.in-game  .title-bg-context,
body.bg-rotation-paused .title-bg-context { opacity: 0; }
body.reduced-motion .title-bg-context { transition: opacity 0ms; }
@media (max-width: 480px) {
  .title-bg-context { gap: 6px; letter-spacing: 0.22em; padding: 0 8px; }
  .title-bg-context::before,
  .title-bg-context::after { width: 18px; }
}

/* Legacy footer-links block — removed from the markup but kept here for
   any third-party CSS that targeted it. Hide if it ever re-appears. */
.title-footer-links { display: none; }

/* About link sits as the LAST child of the centered title-content stack —
   flows naturally below the View Daily/Casual ghost buttons. No more
   absolute positioning (which used to overlap the View boards row on
   wider viewports). Tertiary by typography, not by absence of color. */
.title-about-link {
  margin: 28px 0 0;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--gold);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 2px 12px rgba(0, 0, 0, 0.6);
  pointer-events: auto;
}
@media (max-width: 480px) {
  .title-about-link { margin-top: 20px; font-size: 9px; letter-spacing: 0.24em; }
}

/* Era popover — anchored to the era-chip button below the Casual CTA.
   Glass panel with the same metallic-gold gradient borders the rest of
   the title chrome uses. Hidden by default; positioned via JS so the
   anchor math respects whichever column the chip ended up in after the
   flex row wrapped. */
.era-popover[hidden] { display: none; }
.era-popover {
  position: absolute;
  z-index: 5;
  background: linear-gradient(180deg,
    rgba(28, 22, 14, 0.96) 0%,
    rgba(18, 14, 10, 0.96) 100%);
  border: 1px solid rgba(245, 230, 192, 0.45);
  border-radius: 14px;
  padding: 10px;
  box-shadow:
    0 18px 48px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(245, 230, 192, 0.10) inset;
  min-width: 280px;
  max-width: min(480px, 92vw);
}
.era-segments-stacked {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.title-footer-link {
  color: var(--gold-highlight);
  /* Same translucent dark glass as the View boards pills, no border —
     keeps the link readable over bright cinematic backgrounds while
     staying clearly tertiary in weight (no outline, smaller font). */
  background: linear-gradient(180deg,
    rgba(20, 14, 8, 0.50),
    rgba(10, 6, 4, 0.65));
  border: none;
  padding: 6px 14px;
  cursor: pointer;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  border-radius: 999px;
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 2px 10px rgba(0, 0, 0, 0.35);
  transition: color 180ms ease, background 180ms ease, text-shadow 180ms ease;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 2px 12px rgba(0, 0, 0, 0.6);
}
@media (hover: hover) {
  .title-footer-link:hover {
    color: var(--gold-highlight);
    background: linear-gradient(180deg,
      rgba(30, 22, 14, 0.65),
      rgba(14, 10, 6, 0.80));
  }
}
.title-footer-link:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}
/* Each button centers within its grid cell, lining up under its
   matching CTA button above (Leaderboard ↔ Daily, About ↔ Casual). */
.title-footer-links > button { justify-self: center; }
/* Separator dot is no longer between adjacent labels — hide it. The
   element stays in the DOM as legacy markup; CSS removes it from view. */
.title-footer-sep { display: none; }
@media (max-width: 480px) {
  .title-footer-links { font-size: 9px; letter-spacing: 0.24em; gap: 7px; }
}

/* ----- Tier B3: wordmark gold-shimmer on load --------------------- */
@keyframes wordmark-shimmer {
  0%   { background-position: 200% 0%; }
  100% { background-position: 0% 0%; }
}
.title-content h1 {
  background-size: 200% 100%;
  background-position: 0% 0%;
  animation: wordmark-shimmer 1400ms cubic-bezier(0.22, 1, 0.36, 1) 200ms 1 backwards;
}
body.reduced-motion .title-content h1 {
  animation: none;
  background-size: 100% 100%;
}

/* ----- Tier B5: onboarding replay hint ---------------------------- */
.onboarding-replay-hint {
  margin: 0;
  padding-top: 6px;
  font-family: var(--font-body);
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-subtle);
  opacity: 0.78;
  text-align: center;
}
.onboarding-replay-link {
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* =====================================================================
   ===== ABOUT SCREEN ==================================================
   Single scrolling column, max-width ~720px. Fades up over the title
   backdrop (which is paused while About is active). Uses the same gold
   tokens + Cinzel display so the transition reads as the lobby
   lifting its veil rather than a page navigation.
   ===================================================================== */
#screen-about {
  background: var(--bg-deep);
}
.about-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(ellipse at center,
      rgba(8, 7, 10, 0.78) 0%,
      rgba(8, 7, 10, 0.92) 70%,
      rgba(8, 7, 10, 0.96) 100%);
}
.about-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 1;
  padding:
    calc(env(safe-area-inset-top, 0px) + 88px)
    24px
    calc(env(safe-area-inset-bottom, 0px) + 80px);
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
.about-scroll::-webkit-scrollbar { width: 8px; }
.about-scroll::-webkit-scrollbar-track { background: transparent; }
.about-scroll::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 999px;
}
.about-back {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 20px);
  left: max(env(safe-area-inset-left, 0px), 24px);
  z-index: 10;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px 10px 12px;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  cursor: pointer;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 8px 22px rgba(0, 0, 0, 0.45);
  transition: color 180ms ease, background 180ms ease, border-color 180ms ease,
              box-shadow 180ms ease, transform 180ms ease;
}
@media (hover: hover) {
  .about-back:hover {
    color: var(--gold);
    border-color: var(--border-strong);
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.12),
      0 8px 22px rgba(0, 0, 0, 0.55),
      0 0 18px var(--gold-glow);
    transform: translateX(-2px);
  }
}
.about-back:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.about-back svg { width: 16px; height: 16px; flex-shrink: 0; }

.about-content {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 56px;
  animation: about-enter 600ms cubic-bezier(0.22, 1, 0.36, 1) 100ms backwards;
}
@keyframes about-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
body.reduced-motion .about-content { animation: none; }

.about-hero {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.about-eyebrow {
  margin: 0;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.85;
}
.about-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(28px, 5vw, 48px);
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.05;
  text-transform: uppercase;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.5));
}
.about-lede {
  margin: 0;
  /* Fill the .about-content container width (720px) so the lede aligns
     with the .about-steps grid below — no narrower char-based cap. */
  font-family: var(--font-body);
  font-size: clamp(15px, 1.6vw, 17px);
  line-height: 1.6;
  color: var(--text-primary);
  text-align: justify;
  hyphens: auto;
}
.about-lede em {
  font-style: italic;
  color: var(--gold-highlight);
  font-weight: 500;
}
.about-beta-note {
  margin: 10px 0 0;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(245, 230, 200, 0.6);
  text-align: center;
}

/* Reusable info-popover trigger + bubble. Used next to Sign In to explain
   Clerk's safety story without burying the user in copy. Anchored relative
   to .info-tooltip-wrap, opens on click, dismisses on Escape / outside. */
.info-tooltip-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.info-tooltip-trigger {
  width: 26px;
  height: 26px;
  margin-left: 6px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border-soft);
  background: rgba(20, 14, 8, 0.6);
  color: var(--gold-highlight);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 180ms ease, border-color 180ms ease, transform 180ms ease;
}
.info-tooltip-trigger:hover {
  background: rgba(60, 42, 22, 0.78);
  border-color: var(--gold);
  transform: translateY(-1px);
}
.info-tooltip-trigger[aria-expanded="true"] {
  background: rgba(60, 42, 22, 0.85);
  border-color: var(--gold);
}
.info-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 260px;
  max-width: 320px;
  padding: 14px 16px;
  background: linear-gradient(180deg, rgba(28, 20, 12, 0.97), rgba(14, 10, 6, 0.99));
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  box-shadow:
    0 14px 40px rgba(0, 0, 0, 0.7),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  z-index: 50;
  text-align: left;
}
.info-popover[hidden] { display: none; }
.info-popover p { margin: 0 0 8px; }
.info-popover p:last-child { margin-bottom: 0; }
.info-popover strong { color: var(--gold-highlight); font-weight: 600; }
.info-popover-links {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.info-popover-links a {
  color: var(--gold);
  text-decoration: none;
}
.info-popover-links a:hover {
  color: var(--gold-highlight);
  text-decoration: underline;
}
@media (max-width: 480px) {
  .info-popover {
    min-width: 220px;
    max-width: calc(100vw - 32px);
    font-size: 12px;
  }
}

.about-section {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.about-section-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(13px, 1.5vw, 15px);
  font-weight: 600;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.92;
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border-soft);
}
.about-paragraph {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.65;
  color: var(--text-primary);
  /* No char-based max-width — prose fills the .about-content container
     so it matches the cell-grid width above. */
  text-align: justify;
  hyphens: auto;
}
.about-paragraph strong { color: var(--gold-highlight); font-weight: 600; }
.about-link {
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  text-decoration: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
  transition: color 180ms ease, background 180ms ease;
}
@media (hover: hover) {
  .about-link:hover {
    color: var(--gold-highlight);
    background: rgba(245, 230, 192, 0.06);
  }
}
.about-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.about-aside {
  margin: 4px 0 0;
  text-align: center;
}

.about-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}
.about-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  padding: 22px 18px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.06),
    0 6px 20px rgba(0, 0, 0, 0.4);
}
.about-step-icon {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.16), rgba(212, 165, 116, 0.04));
  border: 1px solid var(--border-strong);
  color: var(--gold-highlight);
}
.about-step-icon svg { width: 22px; height: 22px; }
.about-step-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.about-step-text {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-muted);
  text-align: justify;
  hyphens: auto;
}
/* Mobile fallback: justified text in narrow columns produces ugly "rivers"
   of whitespace. Drop back to left-aligned below 600px so the prose stays
   readable on phones. */
@media (max-width: 600px) {
  .rr-summary,
  .rr-summary-text,
  .about-lede,
  .about-paragraph,
  .about-step-text {
    text-align: left;
  }
}
.about-step-text kbd {
  display: inline-block;
  padding: 0 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  background: rgba(245, 230, 192, 0.08);
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  color: var(--gold-highlight);
}
@media (max-width: 640px) {
  .about-steps { grid-template-columns: 1fr; gap: 12px; }
  .about-step { padding: 18px 16px; }
}

.about-scoring-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.about-scoring-card {
  padding: 18px 20px 20px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}
.about-scoring-label {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
}
.about-scoring-formula {
  margin: 0 0 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--text-primary);
  opacity: 0.9;
}
.about-scoring-formula code {
  background: rgba(245, 230, 192, 0.05);
  border: 1px solid var(--border-soft);
  padding: 4px 10px;
  border-radius: 6px;
  display: inline-block;
}
.about-scoring-thresholds {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.about-scoring-thresholds li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-muted);
}
.about-scoring-thresholds .asc-mark {
  color: var(--gold);
  font-size: 9px;
  width: 12px;
  text-align: center;
}
.about-scoring-thresholds .asc-arrow {
  color: var(--text-subtle);
  margin: 0 2px;
}
@media (max-width: 640px) {
  .about-scoring-grid { grid-template-columns: 1fr; }
}

.about-eras {
  display: grid;
  /* Single full-width column. The 3-up grid created an awkward 3+1
     orphan row with the four eras (Ancient / Medieval / Renaissance /
     Modern); stacking gives each era its own full-width card and reads
     like a proper list. */
  grid-template-columns: 1fr;
  gap: 14px;
}
.about-era {
  /* Single-row layout: name + range sit inline on the left, sample
     list fills the right side. Three columns let the range hug the
     name with a small gap, and the sample column flexes to fill. */
  display: grid;
  grid-template-columns: auto auto 1fr;
  column-gap: 16px;
  align-items: center;
  padding: 18px 20px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
}
.about-era-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.about-era-range {
  margin: 0;
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.85;
}
.about-era-sample {
  margin: 0;
  text-align: right;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
}
/* On narrow viewports the inline layout gets cramped — fall back to
   the stacked layout so the long labels wrap cleanly. */
@media (max-width: 540px) {
  .about-era {
    grid-template-columns: 1fr;
    row-gap: 6px;
  }
  .about-era-sample { text-align: left; }
}
@media (max-width: 640px) {
  /* .about-eras already 1fr at all widths */
}

.about-stack {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.about-stack li {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  padding: 10px 14px;
  background: var(--bg-panel);
  border-left: 2px solid var(--border-strong);
  border-radius: 0 8px 8px 0;
}
.about-stack strong {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  display: inline-block;
  margin-right: 8px;
}

.about-maker {
  text-align: left;
}
.about-maker-links {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.about-footer {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--border-soft);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.about-footer-line {
  margin: 0;
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--text-subtle);
}
.about-footer-back .about-link { font-size: 11px; }

@media (max-width: 480px) {
  .about-scroll { padding: calc(env(safe-area-inset-top, 0px) + 80px) 16px 60px; }
  .about-content { gap: 44px; }
  .about-back { padding: 8px 14px 8px 10px; min-height: 40px; font-size: 10px; }
  .about-section-title { font-size: 11px; letter-spacing: 0.28em; }
  .about-paragraph, .about-step-text { font-size: 13px; }
  .about-stack li { font-size: 13px; }
}

/* When about is active, hide the title screen DOM entirely so the
   absolutely-positioned share/sign-in chips (z-index 3) don't peek
   through the about vignette on tablet widths. The bg rotation keeps
   running silently behind us; we just stop showing the title content
   and HUD layer. Restored when about closes (body.in-about removed). */
body.in-about #screen-title { display: none; }

/* =====================================================================
   ===== Tier C1: in-game HUD calmness pass ============================
   Both #hud-tl (Round / Score / VR) and #hud-bl (Exit / FS / Settings /
   Mute) idle at half opacity so the panorama breathes. Each chip
   independently brightens to full on hover/focus — like the map dock,
   the chrome recedes until the player reaches for it.

   Touch (pointer: coarse) opts out — there's no hover affordance there
   and dimming critical buttons would be hostile.
   ===================================================================== */
@media (pointer: fine) {
  #screen-game.active #hud-tl > .glass-chip,
  #screen-game.active #hud-bl > .glass-chip,
  #screen-game.active #hud-bl > .btn-exit-game,
  #screen-game.active #hud-bl > .exit-hud-wrap > .btn-exit-game,
  /* Fix #6 (R2): the music chip lives inside .hud-mute-wrap (not a direct
     child of #hud-bl), so the existing #hud-bl > .glass-chip dim rule
     skipped it and it sat at full opacity while siblings dimmed to 0.30.
     Pull it into the same dim/hover cycle. */
  #screen-game.active #hud-bl > .hud-mute-wrap > .glass-chip {
    opacity: 0.30;
    transition:
      opacity 220ms ease,
      transform 180ms cubic-bezier(0.32, 0.72, 0, 1),
      background 180ms ease,
      border-color 180ms ease,
      box-shadow 180ms ease;
  }
  #screen-game.active #hud-tl > .glass-chip:hover,
  #screen-game.active #hud-tl > .glass-chip:focus-visible,
  #screen-game.active #hud-tl > .glass-chip:focus-within,
  #screen-game.active #hud-bl > .glass-chip:hover,
  #screen-game.active #hud-bl > .glass-chip:focus-visible,
  #screen-game.active #hud-bl > .glass-chip:focus-within,
  #screen-game.active #hud-bl > .btn-exit-game:hover,
  #screen-game.active #hud-bl > .btn-exit-game:focus-visible,
  #screen-game.active #hud-bl > .exit-hud-wrap > .btn-exit-game:hover,
  #screen-game.active #hud-bl > .exit-hud-wrap > .btn-exit-game:focus-visible,
  /* Fix #6 (R2): hover/focus brightening for the music chip. Also brightens
     when the wrap is hovered (so cursor on the slider keeps the chip lit)
     and when the slider has focus. */
  #screen-game.active #hud-bl > .hud-mute-wrap > .glass-chip:hover,
  #screen-game.active #hud-bl > .hud-mute-wrap > .glass-chip:focus-visible,
  #screen-game.active #hud-bl > .hud-mute-wrap:hover > .glass-chip,
  #screen-game.active #hud-bl > .hud-mute-wrap:focus-within > .glass-chip {
    opacity: 1;
  }
  /* When the cog popover is open, the cog itself is the "active" chip —
     keep it bright while it owns the popover. */
  #screen-game.active #hud-bl > .glass-chip[aria-expanded="true"] {
    opacity: 1;
  }
  /* Bumping (score animation), drag-hint pulse, and other state changes
     should bring their host chips to full opacity automatically — those
     animations would be invisible at 0.30. */
  #screen-game.active .glass-chip.bumping,
  #screen-game.active .score-chip.bumping,
  #screen-game.active .glass-chip[aria-live]:not([aria-live=""]) {
    opacity: 1;
  }
}
/* Reduced-motion users: snap, don't fade. */
body.reduced-motion #hud-tl > .glass-chip,
body.reduced-motion #hud-bl > .glass-chip,
body.reduced-motion #hud-bl > .btn-exit-game,
body.reduced-motion #hud-bl > .exit-hud-wrap > .btn-exit-game,
body.reduced-motion #hud-bl > .hud-mute-wrap > .glass-chip {
  transition: none;
}

/* The C2 collapsed-pill state ("GUESS · 1500 AD" with hover/focus expansion)
   was removed when the slider was killed — there's nothing to "expand to"
   anymore. Picker is always visible inside the transparent dock now. */

body.reduced-motion #year-dock {
  transition: none;
}

/* =====================================================================
   ===== Tier E3: era pickers — give them life =========================
   Six layered enhancements on top of the existing .era-seg pills:
   - Per-pill era tint (bronze / mid-gold / champagne)
   - Era glyph icon next to era-name
   - Hover micro-bloom (translateY + scale + glow)
   - Active pill slow breath (box-shadow oscillation)
   - Count number roll on era-switch
   - Landmark text dot -> arrow on hover
   ===================================================================== */

/* Glyph slot — sits above the era-name, inherits gold color from parent. */
.era-seg .era-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-bottom: 2px;
  color: var(--gold);
  opacity: 0.55;
  transition: color 200ms ease, opacity 200ms ease, transform 220ms cubic-bezier(0.32, 0.72, 0, 1);
}
.era-seg .era-glyph svg { width: 100%; height: 100%; }
.era-seg.active .era-glyph {
  color: var(--gold-highlight);
  opacity: 1;
}
@media (hover: hover) {
  .era-seg:hover .era-glyph {
    color: var(--gold-highlight);
    opacity: 1;
  }
}
.era-seg.active .era-glyph {
  transform: scale(1.08);
}

/* Per-era tints — three brightness shades within the warm-gold palette. */
.era-seg[data-era="ancient"] .era-glyph     { color: var(--gold-deep); }
.era-seg[data-era="medieval"] .era-glyph    { color: var(--gold); }
.era-seg[data-era="renaissance"] .era-glyph { color: #e4c59a; }
.era-seg[data-era="modern"] .era-glyph      { color: var(--gold-highlight); }
.era-seg[data-era="all"] .era-glyph         { color: var(--gold); }
/* Active glyph: tint to the same era color the rest of the active pill
   uses (--era-glow) so the icon, ring, and breath all match. */
.era-seg.active[data-era="ancient"] .era-glyph,
.era-seg.active[data-era="medieval"] .era-glyph,
.era-seg.active[data-era="renaissance"] .era-glyph,
.era-seg.active[data-era="modern"] .era-glyph {
  color: var(--era-glow);
}
@media (hover: hover) {
  .era-seg:hover[data-era="ancient"] .era-glyph {
    color: #c89a5e;  /* deeper bronze, still in the warm family */
  }
}
/* Per-era selection glow color. Bound via data-era so both the active-pill
   ring AND the breath keyframe pick it up automatically. Mirrors the
   field-report chart palette (--era-* vars) so the era selector and the
   leaderboard chart speak the same color language. "all" stays gold. */
.era-seg[data-era="all"]         { --era-glow: var(--gold); }
.era-seg[data-era="ancient"]     { --era-glow: var(--era-ancient); }
.era-seg[data-era="medieval"]    { --era-glow: var(--era-medieval); }
.era-seg[data-era="renaissance"] { --era-glow: var(--era-renaissance); }
.era-seg[data-era="modern"]      { --era-glow: var(--era-modern); }

/* Active pill: era-tinted gradient + ring. color-mix lets us derive
   transparent variants from the era hex var without a parallel RGB
   tuple set. */
.era-seg.active[data-era="ancient"],
.era-seg.active[data-era="medieval"],
.era-seg.active[data-era="renaissance"],
.era-seg.active[data-era="modern"] {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--era-glow) 24%, transparent),
    color-mix(in srgb, var(--era-glow) 9%, transparent));
  border-color: var(--era-glow);
}
.era-seg.active[data-era="all"] {
  background: linear-gradient(180deg, rgba(245, 230, 192, 0.22), rgba(212, 165, 116, 0.10));
}
.era-seg.active[data-era="ancient"] .era-name,
.era-seg.active[data-era="medieval"] .era-name,
.era-seg.active[data-era="renaissance"] .era-name,
.era-seg.active[data-era="modern"] .era-name {
  color: var(--era-glow);
}

/* Hover micro-bloom — non-active pills lift and bloom on hover. */
@media (hover: hover) {
  .era-seg:not(.active):hover {
    transform: translateY(-1px) scale(1.02);
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.10),
      0 6px 18px rgba(0, 0, 0, 0.35),
      0 0 14px var(--gold-glow);
  }
}

/* Active pill slow breath — gentle 2.4s box-shadow oscillation so the
   "selected" pill feels alive without animating geometry. The glow is
   keyed off --era-glow (set per data-era above) so each era breathes in
   its own color rather than always gold. */
@keyframes era-active-breath {
  0%, 100% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.14),
      0 0 14px color-mix(in srgb, var(--era-glow, rgb(212, 165, 116)) 30%, transparent);
  }
  50% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.18),
      0 0 22px color-mix(in srgb, var(--era-glow, rgb(212, 165, 116)) 55%, transparent);
  }
}
.era-seg.active {
  animation: era-active-breath 2400ms ease-in-out infinite;
}
body.reduced-motion .era-seg.active { animation: none; }

/* Count-roll: when the era-count text changes, briefly slide it in from
   below. The .rolling class is added by main.js for ~280ms after switch. */
.era-seg .era-count {
  display: inline-block;
  transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1), opacity 280ms ease;
}
.era-seg.active.rolling .era-count {
  animation: era-count-roll 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes era-count-roll {
  0%   { transform: translateY(-8px); opacity: 0; }
  100% { transform: translateY(0);    opacity: 1; }
}
body.reduced-motion .era-seg.active.rolling .era-count { animation: none; }

/* Landmark text — dot -> arrow on hover. The dot is the default
   separator in the text; on hover we add a CSS ::after that prints the
   arrow with a tiny offset, replacing the visual feel. (We don't
   actually replace text — that would flicker. Instead, the arrow
   overlays via pseudo-element when the pill is hovered.) */
.era-seg .era-landmarks {
  position: relative;
  transition: letter-spacing 200ms ease, color 200ms ease;
}
@media (hover: hover) {
  .era-seg:hover .era-landmarks {
    /* Slight letter-spacing widening signals "look closer" */
    letter-spacing: 0.10em;
    color: var(--gold);
  }
}

/* =====================================================================
   ===== Tier E1: grand entrance =======================================
   On every cold page load, body.pristine is set. We hide every title-
   screen child except the bg layers + vignette. First user interaction
   removes .pristine; CSS transition-delays cascade the chrome in.

   Cursor signal (instant), pulse hint (visible at 1.5s), and JS-driven
   15s auto-reveal fallback are the three discoverability layers.
   ===================================================================== */

/* The cascade-eligible elements ALWAYS carry the transition rule, so
   removing body.pristine triggers a smooth fade. (Putting transition
   inside body.pristine selector would delete it on reveal and snap
   opacity instantly — exactly what we don't want.)

   Walk-F14: 3-second cinematic fade. Duration tuned so the last-staged
   element (#global-hud-bl, delay 900ms) finishes at ~3000ms total. */
#screen-title > .title-content,
#title-hud-tr,
.title-share-block,
#global-hud-bl {
  transition: opacity 2100ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* While pristine: hide every direct child of #screen-title except the
   bg stack + vignette (the visual anchor). The bg-context badge is
   handled by its own renderBgContext gating (it listens for the
   grand-entrance event and adds .visible). */
body.pristine #screen-title > .title-content,
body.pristine #title-hud-tr,
body.pristine .title-share-block,
body.pristine #global-hud-bl {
  opacity: 0;
  pointer-events: none;
}
/* Tap-hint visible during pristine — appears at full opacity on load (no
   auto fade-in; the cinematic 3s fade is for the title content cascade
   AFTER the user taps). Breathes gently to advertise the affordance.
   Sits at viewport center, anchored on safe-area. */
body.pristine #tap-hint {
  opacity: 0.78;
  /* Override the blanket pristine "opacity: 0; pointer-events: none" rule
     so the hint can be seen and ignored (still pointer-events: none —
     we don't want it intercepting the very click that reveals everything). */
  animation: tap-hint-pulse 2500ms ease-in-out infinite;
}
@keyframes tap-hint-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 0.78; }
}
/* The hint itself is hidden when not pristine.
   Walk-F14: centered vertically + horizontally, larger Cinzel display
   for cinematic title-card feel.
   Universal centering: position:fixed + top:50dvh handles iPhone Safari's
   URL-bar layout-viewport quirk, and works identically on iPad/desktop
   (dvh == 1% viewport height everywhere). */
#tap-hint {
  position: fixed;
  top: 50dvh;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(22px, 6vw, 32px);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.85);
  pointer-events: none;
  /* Force one line — iPhone narrow viewports were wrapping "TAP TO" / "BEGIN" */
  white-space: nowrap;
  /* Hidden by default — only visible during pristine. */
  opacity: 0;
}

/* Show mouse copy by default, swap to touch via media query. CSS media
   queries resolve before first paint, so desktop never flashes "Tap" first. */
#tap-hint .tap-hint-touch { display: none; }
@media (hover: none) {
  #tap-hint .tap-hint-mouse { display: none; }
  #tap-hint .tap-hint-touch { display: inline; }
}

/* Cursor signal during pristine — tells mouse users "there's something
   to click." Excludes the bg layers themselves so they aren't pointer-
   weirded. */
body.pristine { cursor: pointer; }
@media (pointer: coarse) {
  body.pristine { cursor: auto; }
}

/* Reveal cascade — when .pristine is removed, every hidden child fades
   in with a transition-delay so they cascade rather than all snap up
   together. Order roughly matches a movie title sequence:
     bg-context badge first, then wordmark, then chrome.
   Uses inherited 700ms transition from the pristine rule above. */
body:not(.pristine) #title-bg-context { transition-delay: 0ms; }
body:not(.pristine) #screen-title > .title-content { transition-delay: 200ms; }
body:not(.pristine) #title-hud-tr { transition-delay: 700ms; }
body:not(.pristine) .title-share-block { transition-delay: 800ms; }
body:not(.pristine) #global-hud-bl { transition-delay: 900ms; }
body:not(.pristine) #tap-hint {
  /* Hint fades back to 0 (becomes invisible — its job is done). */
  opacity: 0;
  transition-delay: 0ms;
  animation: none;
}

/* Reduced motion: snap, don't cascade. */
body.reduced-motion.pristine #screen-title > .title-content,
body.reduced-motion.pristine #title-hud-tr,
body.reduced-motion.pristine .title-share-block,
body.reduced-motion.pristine #title-bg-context,
body.reduced-motion.pristine #global-hud-bl {
  transition-duration: 0ms;
}
body.reduced-motion.pristine #tap-hint { animation: none; opacity: 0.55; }

/* =====================================================================
   ===== Tier E2: fullscreen nudge =====================================
   Small dark glass chip anchored above the bottom-left fullscreen button.
   Appears 5s after grand entrance (desktop only). Dismissible via × or
   by entering fullscreen. Auto-fades at 12s.
   ===================================================================== */
.fullscreen-nudge {
  position: fixed;
  z-index: 35;
  /* Anchored above the global bottom-left HUD cluster. The cluster sits
     at bottom: max(env(safe-area-inset-bottom, 0px), 16px) and ~44px
     tall. Park the chip ~64px above that. */
  bottom: calc(env(safe-area-inset-bottom, 0px) + 80px);
  left: max(env(safe-area-inset-left, 0px), 16px);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px 10px 16px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.08),
    0 8px 22px rgba(0, 0, 0, 0.55);
  white-space: nowrap;
  pointer-events: auto;
  /* Appear / dismiss animation. */
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 280ms ease, transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
.fullscreen-nudge[hidden] { display: none; }
.fullscreen-nudge.visible {
  opacity: 1;
  transform: translateY(0);
  /* Initial breathing pulse to draw attention, then settles. */
  animation: fsn-attention 1400ms ease-in-out 1;
}
@keyframes fsn-attention {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(245, 230, 192, 0.08), 0 8px 22px rgba(0, 0, 0, 0.55), 0 0 0 0 var(--gold-glow); }
  50%      { box-shadow: inset 0 1px 0 rgba(245, 230, 192, 0.14), 0 8px 22px rgba(0, 0, 0, 0.55), 0 0 22px var(--gold-glow); }
}
.fullscreen-nudge .fsn-text { color: var(--text-muted); }
.fullscreen-nudge .fsn-kbd {
  display: inline-block;
  padding: 1px 7px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  background: rgba(245, 230, 192, 0.08);
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  color: var(--gold-highlight);
}
.fullscreen-nudge .fsn-or { color: var(--text-subtle); margin: 0 -2px; }
.fullscreen-nudge .fsn-icon {
  width: 14px;
  height: 14px;
  color: var(--gold-highlight);
}
.fsn-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 4px;
  background: transparent;
  border: none;
  border-radius: 999px;
  color: var(--text-subtle);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease;
}
@media (hover: hover) {
  .fsn-close:hover { color: var(--gold-highlight); background: rgba(245, 230, 192, 0.06); }
}
.fsn-close:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.fsn-close svg { width: 12px; height: 12px; }

/* Hide on touch — fullscreen idiom isn't meaningful there. */
@media (pointer: coarse) {
  .fullscreen-nudge { display: none !important; }
}
/* Hide while pristine — must wait for grand entrance. */
body.pristine .fullscreen-nudge { display: none !important; }
/* Hide during in-game / about / final / done — only on title. */
body.in-game .fullscreen-nudge,
body.in-about .fullscreen-nudge { display: none !important; }
body.reduced-motion .fullscreen-nudge { transition: none; animation: none; }

/* =====================================================================
   ===== Tier D7 + C3: result-panel polish =============================
   D7: emphasize "Your guess" year value with metallic gradient + glow
        + slightly larger font. The actual year stays clean and bright.
   C3: score-bar gold-brighten on high scores (>= 4,000 / >= 4,500 pts).
   ===================================================================== */

/* D7: asymmetric emphasis on the guess year. Player's guess is the
   narrative subject, actual is the answer. */
.rr-yc-guess {
  font-size: 16px !important;
  letter-spacing: 0.06em;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent !important;
  text-shadow: 0 2px 14px rgba(212, 165, 116, 0.40);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.45));
  font-weight: 700;
}
@media (max-width: 480px) {
  .rr-yc-guess { font-size: 15px !important; }
}

/* The arrow gains weight too — visual lead-in to the actual answer. */
.rr-yc-arrow {
  color: var(--gold-highlight) !important;
  opacity: 0.85;
  font-weight: 600;
}

/* C3: score bar gold-brighten thresholds. Bar fills are colored by JS
   adding .bar-strong (>= 4,000) or .bar-perfect (>= 4,500). Default
   stays as the existing gold-toned bar. */
.rr-stat-bar-fill {
  transition: background 320ms ease, box-shadow 320ms ease;
}
.rr-stat-bar-fill.bar-strong {
  background: linear-gradient(90deg, rgba(212,165,116,0.45) 0%, rgba(245,230,192,0.55) 100%);
}
.rr-stat-bar-fill.bar-perfect {
  background: linear-gradient(90deg, rgba(245,230,192,0.55) 0%, rgba(255,234,203,0.70) 50%, rgba(245,230,192,0.55) 100%);
  box-shadow:
    0 0 12px var(--gold-glow),
    inset 0 0 6px rgba(255, 234, 203, 0.4);
  animation: bar-perfect-breath 2400ms ease-in-out infinite;
}
@keyframes bar-perfect-breath {
  0%, 100% { box-shadow: 0 0 10px rgba(212, 165, 116, 0.40), inset 0 0 6px rgba(255, 234, 203, 0.30); }
  50%      { box-shadow: 0 0 18px rgba(212, 165, 116, 0.65), inset 0 0 8px rgba(255, 234, 203, 0.50); }
}
body.reduced-motion .rr-stat-bar-fill.bar-perfect { animation: none; }

/* =====================================================================
   ===== Tier D8: era-themed final round bars ==========================
   Each .round-history-row gets data-era="ancient|medieval|modern" set
   in renderRoundHistory(). We add a 4px left-border accent in three
   gold shades — bronze (ancient), mid-gold (medieval), champagne
   (modern). Stays monochromatic warm-gold; just three brightness shades.
   ===================================================================== */
.round-history-row {
  border-left: 4px solid transparent;
  padding-left: 8px;  /* compensate so content doesn't shift sideways */
  transition: border-color 220ms ease, background 220ms ease;
}
.round-history-row[data-era="ancient"]     { border-left-color: var(--era-ancient); }
.round-history-row[data-era="medieval"]    { border-left-color: var(--era-medieval); }
.round-history-row[data-era="renaissance"] { border-left-color: var(--era-renaissance); }
.round-history-row[data-era="modern"]      { border-left-color: var(--era-modern); }
/* Per Eric's UX pass (2026-05): era is conveyed only via the left-edge
   border now — the round number stays a calm muted text color so the
   era stripe is the single source of era-recognition. */

/* =====================================================================
   Mobile-only fixes from real-iPhone walk (2026-05-02)
   See docs/mobile-audit-2026-05-02.md "Real-iPhone + iPad walk findings"
   --------------------------------------------------------------------
   These rules sit AFTER the existing mobile blocks so they win the
   cascade. All gated to (pointer: coarse) AND (max-width: 480px) (or
   landscape) or body.is-iphone, so desktop is pixel-identical
   before/after.
   ===================================================================== */

/* Walk-F07: HUD chips stay full opacity on phone-touch. The existing
   .glass-chip { opacity: 0.55 } idle inside the (max-width: 480px) block
   has a :hover/:focus/:focus-within/:active opt-out — none of which fire
   reliably on iPhone touch (no real hover, focus is sticky-then-lost on
   tap, :active only during the touch). Result on real iPhone: chips
   ghost dim forever, except .btn-exit-game which has its own rule.
   Fix: on touch phones, just keep them at full opacity. */
@media (max-width: 480px) and (pointer: coarse) {
  .glass-chip { opacity: 1; }
}

/* Walk-F03 was originally scoped here but DROPPED from this PR — the
   audit's 6px-gap measurement was on an older snapshot (00e3c92). On
   current main there's already a `#hud-bl { bottom: env(...) + 80px }`
   rule in the existing landscape block (~line 3820) that gives a 14px
   gap on real iPhone. If Eric still feels it's tight in landscape,
   raise the existing 80px → 100px+ in a follow-up PR. */

/* =====================================================================
   ===== Walk-F10 + Walk-F12: iPhone-only platform overrides ===========
   Apple disables the Fullscreen API on iPhone Safari (only <video>
   elements support fullscreen on iPhone — iPad supports element
   fullscreen). The .fs-toggle chip is dead UI on iPhone, so we hide
   it. Side benefit: removes one of the 32×32 chips from the bottom-left
   cluster on the title/final/done/in-game screens.

   For the share row, we collapse 4 buttons (X / FB / Reddit / Copy at
   32×32 each) to a single 44×44 Share trigger chip on
   iPhone. The chip calls navigator.share() to open the iOS native
   sheet (iMessage / Mail / etc.). iPad + desktop are pixel-identical
   to before — gating is purely on the .is-iphone body class.
   ===================================================================== */

/* Walk-F10: hide fullscreen chip on iPhone (iPad keeps it; desktop keeps it). */
body.is-iphone .fs-toggle { display: none !important; }

/* Walk-F12: hide existing 5-button share row + label on iPhone. */
body.is-iphone .title-share { display: none !important; }
body.is-iphone .title-share-block-label { display: none !important; }

/* Walk-F12: by default the Share trigger chip is hidden; only iPhone
   reveals it. The chip lives inside .title-share-block which is the
   bottom-right anchor on the title screen. Sized to 44×44 to meet the
   iOS touch-target minimum. */
.share-trigger-chip { display: none; }
body.is-iphone .share-trigger-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--gold);
  background: rgba(18, 14, 10, 0.55);
  border: 1px solid var(--border-soft);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease, transform 180ms ease;
}
body.is-iphone .share-trigger-chip:hover {
  color: var(--gold-highlight);
  background: rgba(245, 230, 192, 0.08);
}
body.is-iphone .share-trigger-chip:active { transform: scale(0.92); }
body.is-iphone .share-trigger-chip svg { width: 20px; height: 20px; }

/* =====================================================================
   Mobile/MR2 v3 — iPhone-only volume slider hide
   ---------------------------------------------------------------------
   iPhone Safari: audio.volume is read-only (slider does nothing) AND
   the in-HUD mute chip already auto-mutes/unmutes the player. The
   settings popover's Music section is fully redundant on iPhone — hide
   the entire section (heading + toggle + slider). Uses :has() which is
   iOS Safari 15.4+ (Eric's audience).
   iPad + desktop: unchanged.
   ===================================================================== */
body.is-iphone .settings-section:has(.settings-music) {
  display: none;
}

/* =====================================================================
   Universal numeric year picker (alarm-clock pattern: number + AD/BC pill)
   --------------------------------------------------------------------
   Single composite pill: <input inputmode="numeric"> + <button> era toggle.
   Was phone-only in PR #46 (max-width: 480px), promoted here to the
   universal year UI on iPhone, iPad, AND desktop. The slider is gone
   everywhere — no platform gates needed.

   Default sizing is iPad-baseline (20px font, 56px height) which reads
   well on desktop. Phones get a more compact size in the @media block
   below (16px stays >=16px to suppress iOS zoom-on-focus).
   ===================================================================== */
.year-input-mobile {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--gold-deep);
  background: var(--bg-panel);
  overflow: hidden;
  min-height: 56px;
  margin: 0 auto;
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(245, 230, 192, 0.06);
}
.year-input-mobile[hidden] { display: none !important; }

.year-num-input {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: var(--gold-highlight);
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-align: center;
  padding: 12px 16px;
  width: 7ch;
  outline: none;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}
.year-num-input:focus { color: var(--gold); }
/* Clear-on-focus shows previous value as faded placeholder. Per Eric:
   "have there be whatever place hold number is there and then when user
   clicks to edit the text box is cleared and ready for them to type". */
.year-num-input::placeholder { color: rgba(245, 230, 192, 0.35); }

.year-era-toggle {
  appearance: none;
  -webkit-appearance: none;
  /* AD default: deep bronze background — high contrast for champagne text */
  background: rgba(75, 50, 8, 0.92);
  border: 0;
  border-left: 1px solid var(--gold-deep);
  color: var(--gold-highlight);
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.18em;
  padding: 12px 22px;
  min-width: 68px;
  cursor: pointer;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  transition: background 160ms ease, color 160ms ease, transform 120ms ease;
}
.year-era-toggle[data-era="BC"] {
  /* BC: warm-deep, near-white text — clearly distinct from AD */
  background: rgba(40, 22, 6, 0.96);
  color: #fff8e7;
}
.year-era-toggle:active { transform: scale(0.96); }

/* Era-out-of-range shake — 200ms wobble on the pill */
@keyframes year-input-mobile-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}
.year-input-mobile.shake {
  animation: year-input-mobile-shake 200ms ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
  .year-input-mobile.shake { animation: none; }
}

/* =====================================================================
   LOCK IN + DROP A PIN: universal CTAs above the picker pill.
   --------------------------------------------------------------------
   Was phone-only in PR #46. Now the universal Submit + status indicator
   pair on iPhone, iPad, AND desktop. JS toggles [hidden] based on:
     - no pin set         → DROP A PIN visible, LOCK IN hidden
     - pin + valid year   → LOCK IN visible, DROP A PIN hidden
     - in result panel    → both hidden
   ===================================================================== */
.lock-in-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 14px 36px;
  min-height: 52px;
  min-width: 220px;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.22), rgba(139, 105, 20, 0.20));
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(245, 230, 192, 0.10),
    0 6px 22px rgba(0, 0, 0, 0.55),
    0 0 22px var(--gold-glow);
  animation: lock-in-cta-pulse 1.6s ease-in-out infinite;
  transition: transform 120ms ease, opacity 220ms ease, background 180ms ease;
}
.lock-in-cta:hover {
  transform: translateY(-1px);
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.28), rgba(139, 105, 20, 0.24));
}
.lock-in-cta:active { transform: scale(0.97); }
.lock-in-cta:disabled { cursor: default; opacity: 0.6; animation: none; }
.lock-in-cta[hidden] { display: none !important; }

@keyframes lock-in-cta-pulse {
  0%, 100% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.10),
      0 6px 22px rgba(0, 0, 0, 0.55),
      0 0 16px rgba(212, 165, 116, 0.30);
  }
  50% {
    box-shadow:
      inset 0 1px 0 rgba(245, 230, 192, 0.14),
      0 6px 22px rgba(0, 0, 0, 0.55),
      0 0 30px rgba(212, 165, 116, 0.60);
  }
}

.drop-pin-prompt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 11px 30px;
  min-height: 46px;
  min-width: 188px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
  background: transparent;
  border: 1px solid rgba(212, 165, 116, 0.55);
  border-radius: 999px;
  cursor: pointer;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.7);
  transition: transform 120ms ease, color 180ms ease, border-color 180ms ease, background 180ms ease;
}
.drop-pin-prompt:hover {
  background: rgba(212, 165, 116, 0.06);
  border-color: var(--gold-highlight);
  color: var(--gold-highlight);
}
.drop-pin-prompt:active {
  transform: scale(0.97);
  background: rgba(212, 165, 116, 0.06);
}
.drop-pin-prompt[hidden] { display: none !important; }

/* Brief pulse used when the user taps DROP A PIN to draw the eye to
   the (already-visible) map dock. JS adds .nudge for ~900ms. */
@keyframes drop-pin-prompt-nudge {
  0%, 100% { transform: scale(1); border-color: rgba(212, 165, 116, 0.55); }
  50% { transform: scale(1.04); border-color: var(--gold-highlight); box-shadow: 0 0 16px var(--gold-glow); }
}
.drop-pin-prompt.nudge { animation: drop-pin-prompt-nudge 900ms ease-out; }

/* Highlight the map-dock briefly when DROP A PIN is tapped. */
@keyframes map-dock-highlight {
  0%, 100% { box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35); }
  50% { box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35), 0 0 24px var(--gold-glow); border-color: var(--gold-highlight); }
}
#map-dock.nudge { animation: map-dock-highlight 900ms ease-out; }

@media (prefers-reduced-motion: reduce) {
  .lock-in-cta { animation: none; }
  .drop-pin-prompt.nudge,
  #map-dock.nudge { animation: none; }
}

/* =====================================================================
   Phone (≤480px): tighter sizing for picker + CTAs.
   --------------------------------------------------------------------
   Default rules above use iPad-baseline sizing. On phones we shrink the
   pill + CTAs to fit comfortably on a 375-wide viewport without crowding.
   ===================================================================== */
@media (max-width: 480px) {
  .year-input-mobile { min-height: 48px; }
  .year-num-input {
    font-size: 18px;          /* >= 16px to suppress iOS auto-zoom on focus */
    padding: 10px 12px;
    width: 6.5ch;             /* fits 4 digits + breathing room */
    letter-spacing: 0.14em;
  }
  .year-era-toggle {
    font-size: 14px;
    padding: 10px 16px;
    min-width: 56px;
  }
  .lock-in-cta {
    padding: 12px 28px;
    min-height: 44px;
    min-width: 168px;
    font-size: 14px;
    letter-spacing: 0.18em;
  }
  .drop-pin-prompt {
    padding: 8px 22px;
    min-height: 38px;
    min-width: 140px;
    font-size: 12px;
    letter-spacing: 0.22em;
  }
}

/* =====================================================================
   EXIT button: tap-without-hold hint tooltip (universal, all platforms)
   ---------------------------------------------------------------------
   When user taps EXIT quickly without completing the 1.5s hold, show a
   "Hold to exit" tooltip for 1.5s. Educational only — does NOT fire EXIT.
   See initExitHoldToConfirm() in main.js for the trigger logic.

   Wrapper hosts both the button and the absolute-positioned tooltip so
   the tooltip stays visually attached to the button across all
   layout variants (phone bottom-right, iPad bottom-right, desktop
   bottom-right, fallback bottom-left in #hud-bl). The phone/iPad/desktop
   media queries below override .exit-hud-wrap to position: fixed; this
   default `relative` only applies on small-desktop/tablet where the
   wrapper sits inside #hud-bl's flex column.

   IMPORTANT: keep this block BEFORE the phone/iPad/desktop media queries
   that override .exit-hud-wrap. Same-specificity rules cascade by source
   order — putting this AFTER would clobber `position: fixed`.
   ===================================================================== */
.exit-hud-wrap {
  position: relative;
  display: inline-flex;
}
.exit-tap-hint {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  left: auto;
  transform: translateY(4px);
  padding: 6px 10px;
  background: rgba(0, 0, 0, 0.85);
  border: 1px solid rgba(245, 230, 192, 0.20);
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  white-space: normal;
  width: max-content;
  max-width: 160px;
  text-align: center;
  line-height: 1.35;
  pointer-events: none;
  opacity: 0;
  transition: opacity 200ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 50;
}
.exit-tap-hint::after {
  content: '';
  position: absolute;
  top: 100%;
  right: 42px;
  left: auto;
  transform: none;
  border: 5px solid transparent;
  border-top-color: rgba(0, 0, 0, 0.85);
}
.exit-tap-hint[hidden] { display: none; }
.exit-tap-hint.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* =====================================================================
   Phone HUD relocations (PR #46): EXIT bottom-right + cog/mute bottom-left.
   --------------------------------------------------------------------
   Kept gated to phone widths — desktop/iPad keep their original HUD layout.
   ===================================================================== */
@media (max-width: 480px) {
  /* EXIT button: relocate bottom-right + scale to 75%. The visible EXIT
     is #btn-exit-hud (not the legacy #btn-exit-game in the settings popover).
     Fixed positioning lives on .exit-hud-wrap so the "Hold to exit" tooltip
     stays anchored to the button. */
  .exit-hud-wrap {
    position: fixed;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
    right: max(env(safe-area-inset-right, 0px), 12px);
    transform: scale(0.75);
    transform-origin: bottom right;
    z-index: 34;
  }
  #btn-exit-hud {
    opacity: 1 !important;
  }
  #btn-exit-hud:active { transform: scale(0.97); }

  /* Settings cog + mute stay bottom-left (where EXIT used to live). */
  #hud-bl {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 12px) !important;
    left: max(env(safe-area-inset-left, 0px), 12px);
  }
  #screen-game.active #hud-bl > .glass-chip {
    opacity: 1 !important;
  }
}

/* iPhone/iPad UA-detected fallback for the same HUD relocations — some
   DevTools mobile presets don't trip max-width: 480px (iPad widths) but
   we still want the EXIT-bottom-right behavior on iPad.
   Fixed positioning lives on .exit-hud-wrap so the "Hold to exit" tooltip
   stays anchored to the button. */
body.is-iphone .exit-hud-wrap,
body.is-ipad .exit-hud-wrap {
  position: fixed;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  right: max(env(safe-area-inset-right, 0px), 12px);
  transform: scale(0.75);
  transform-origin: bottom right;
  z-index: 34;
}
body.is-iphone #btn-exit-hud,
body.is-ipad #btn-exit-hud {
  opacity: 1 !important;
}
body.is-iphone #btn-exit-hud:active,
body.is-ipad #btn-exit-hud:active { transform: scale(0.97); }
body.is-iphone #hud-bl,
body.is-ipad #hud-bl {
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px) !important;
  left: max(env(safe-area-inset-left, 0px), 12px);
}
body.is-iphone #screen-game.active #hud-bl > .glass-chip,
body.is-ipad #screen-game.active #hud-bl > .glass-chip {
  opacity: 1 !important;
}


/* =====================================================================
   EXIT button: hold-to-confirm visual fill (universal, all platforms)
   ---------------------------------------------------------------------
   Click handler is replaced with hold-detection in main.js
   (initExitHoldToConfirm). User must press + hold for 1.5s to actually
   exit. This pseudo-element draws the left-to-right fill that animates
   during the hold to give visual feedback.
   ===================================================================== */
#btn-exit-hud {
  position: relative;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
#btn-exit-hud::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.40);
  border-radius: inherit;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0s ease;
  pointer-events: none;
  z-index: 0;
}
#btn-exit-hud.holding::before {
  transform: scaleX(1);
  transition: transform 1.5s linear;
}
#btn-exit-hud.confirmed::before {
  transform: scaleX(1);
  background: rgba(0, 0, 0, 0.60);
}
/* Keep the EXIT label/icon above the fill overlay */
#btn-exit-hud > * {
  position: relative;
  z-index: 1;
}

/* =====================================================================
   PR #46 v4: desktop EXIT relocation.
   --------------------------------------------------------------------
   Per Eric: move EXIT to bottom-right on desktop too. Full size (no 75%
   scale — the scale was a phone tightening trick). The fine-pointer dim
   rule above still applies via the .btn-exit-game class.

   Placed at the END of the file so it overrides the universal
   #btn-exit-hud { position: relative } rule above (same specificity,
   later wins). The iPhone/iPad gates already win on specificity via
   body.is-iphone/.is-ipad and stay correct above this rule.

   The fixed positioning now lives on .exit-hud-wrap (the wrapper added
   for the "Hold to exit" tap-hint tooltip) — the wrapper takes the
   button + tooltip out of #hud-bl together, so the tooltip can absolute-
   position above the button regardless of viewport.
   ===================================================================== */
@media (min-width: 1025px) and (pointer: fine) {
  #hud-bl > .exit-hud-wrap {
    position: fixed;
    bottom: max(env(safe-area-inset-bottom, 0px), 16px);
    right: max(env(safe-area-inset-right, 0px), 16px);
    z-index: 34;
  }
}

/* =====================================================================
   Competitive-mode round timer (top-center chip)
   Visible only when competitive mode is on AND a round is in flight.
   60s SVG ring drains via stroke-dashoffset (paintTimer in main.js).
   ===================================================================== */
.timer-chip {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 16px);
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px 8px 12px;
  z-index: 32;
  border-radius: 999px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  pointer-events: none; /* purely informational, no clicks */
}
.timer-chip .timer-ring {
  width: 28px;
  height: 28px;
  display: block;
  /* Rotate so stroke-dashoffset starts the drain at the 12 o'clock position. */
  transform: rotate(-90deg);
}
.timer-chip .timer-ring-bg {
  stroke: var(--border-soft);
  stroke-width: 3;
}
.timer-chip .timer-ring-fg {
  stroke: var(--gold);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 4px var(--gold-glow));
  transition: stroke 220ms ease;
}
.timer-chip .timer-readout {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.08em;
  color: var(--gold-highlight);
  min-width: 38px;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
.timer-chip.warning .timer-ring-fg { stroke: #e6b455; }
.timer-chip.warning .timer-readout { color: #f6d49a; }
.timer-chip.warning {
  border-color: rgba(230, 180, 85, 0.45);
  animation: timer-pulse 0.9s ease-in-out infinite alternate;
}
.timer-chip.critical .timer-ring-fg { stroke: var(--danger); }
.timer-chip.critical .timer-readout { color: #ff8d80; }
.timer-chip.critical {
  border-color: rgba(231, 76, 60, 0.6);
  animation: timer-shake 0.36s ease-in-out infinite alternate;
}
@keyframes timer-pulse {
  from { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35), 0 0 0 0 rgba(230, 180, 85, 0.0); }
  to   { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35), 0 0 0 6px rgba(230, 180, 85, 0.18); }
}
@keyframes timer-shake {
  from { transform: translateX(calc(-50% - 2px)); }
  to   { transform: translateX(calc(-50% + 2px)); }
}
/* Reduce-motion: drop the pulse + shake; ticks (audio) still play. */
body.reduce-motion .timer-chip.warning,
body.reduce-motion .timer-chip.critical {
  animation: none;
}

/* =====================================================================
   Title-screen footer-link separator — legacy, hidden in the current
   2-column grid layout (Leaderboard under Daily, About under Casual).
   Kept in the DOM in case we revert to the inline list later.
   ===================================================================== */
.title-footer-sep {
  display: none;
}

/* =====================================================================
   Final/Done screen "Leaderboard" button shares the .final-menu styling
   above (gold-on-transparent secondary button). Previously had its own
   block that only set border + color, which left it without padding,
   font, etc. — rendering as a plain white box. Merged into .final-menu.
   ===================================================================== */

/* =====================================================================
   Leaderboard alias-prompt modal (body-level overlay shown after the
   final-screen score reveal). Pseudonym is required; emails never shown.
   ===================================================================== */
.leaderboard-prompt-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 24px;
  background: linear-gradient(180deg, rgba(8, 7, 10, 0) 0%, rgba(8, 7, 10, 0.55) 60%, rgba(8, 7, 10, 0.78) 100%);
  z-index: 60;
  pointer-events: auto;
}

/* Hold-to-confirm overlay (Tier 7). Sits above the leaderboard prompt
   (z-index 70 vs 60) so it can intercept skip-with-prior-claim and
   rename-warning paths. Shared surface — showHoldConfirm() in main.js
   populates the title/message/handlers per call. */
.hold-confirm-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(8, 7, 10, 0.78);
  z-index: 70;
  pointer-events: auto;
}
.hold-confirm-overlay[hidden] { display: none; }
.hold-confirm-panel {
  width: min(420px, 100%);
  padding: 24px 24px 20px;
}
.hold-confirm-title {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  margin: 0 0 12px;
}
.hold-confirm-message {
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: 14px;
  color: var(--text-primary);
  margin: 0 0 22px;
  line-height: 1.5;
}
.hold-confirm-actions {
  display: flex;
  gap: 12px;
}
.hold-confirm-actions .btn-primary,
.hold-confirm-actions .btn {
  flex: 1;
  min-height: 48px;
}
.hold-confirm-confirm {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  /* Secondary destructive button — sits opposite the safe primary
     "Go back" so the visual weight tips toward the safe option.
     Coral border telegraphs that this is the irreversible side. */
  padding: 10px 18px;
  background: rgba(214, 138, 122, 0.10);
  border: 1px solid color-mix(in srgb, #d68a7a 60%, transparent);
  border-radius: 12px;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  .hold-confirm-confirm:hover {
    background: rgba(214, 138, 122, 0.18);
    border-color: #d68a7a;
  }
}
.hold-confirm-confirm:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.hold-confirm-confirm.is-holding {
  background: rgba(214, 138, 122, 0.06);
}
.hold-confirm-progress-bar {
  position: absolute;
  inset: 0 100% 0 0;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--gold) 28%, transparent) 0%,
    color-mix(in srgb, var(--gold) 48%, transparent) 100%);
  pointer-events: none;
  z-index: 0;
  /* Reset speed when hold is released — fast snap-back. */
  transition: right 200ms ease-out;
}
.hold-confirm-confirm.is-holding .hold-confirm-progress-bar {
  right: 0;
  /* Hold-fill speed — must match HOLD_DURATION_MS in showHoldConfirm. */
  transition: right 1500ms linear;
}
.hold-confirm-label {
  position: relative;
  z-index: 1;
}
@media (prefers-reduced-motion: reduce) {
  /* Reduced-motion: drop the bar animation. The button still works as a
     plain click → confirm path; showHoldConfirm relabels it
     "Tap to confirm" so the affordance reads correctly. */
  .hold-confirm-progress-bar {
    display: none;
  }
}
.leaderboard-prompt-overlay[hidden] { display: none; }
.leaderboard-prompt {
  width: min(360px, 100%);
  padding: 22px 24px 18px;
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-strong);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  border-radius: 14px;
  box-shadow: 0 32px 80px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(245, 230, 192, 0.08);
}
.leaderboard-prompt-title {
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  margin: 0 0 6px;
}
.leaderboard-prompt-meta {
  font-size: 13px;
  color: var(--text-muted);
  margin: 0 0 14px;
  line-height: 1.4;
}
.leaderboard-name-input {
  width: 100%;
  padding: 10px 12px;
  font: 500 16px/1.2 var(--font-body);
  color: var(--text-primary);
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  outline: none;
  transition: border-color 160ms ease, background 160ms ease;
  -webkit-user-select: text;
  user-select: text;
}
.leaderboard-name-input:focus {
  border-color: var(--gold);
  background: rgba(245, 230, 192, 0.07);
}
.leaderboard-name-input::placeholder {
  color: var(--text-subtle);
}
.leaderboard-prompt-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
}
.leaderboard-prompt-actions .btn-primary,
.leaderboard-prompt-actions .btn {
  flex: 1;
  padding: 10px 14px;
  font: 600 13px/1 var(--font-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: 8px;
  border: 1px solid var(--border-soft);
  background: rgba(245, 230, 192, 0.04);
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease, color 160ms ease;
}
.leaderboard-prompt-actions .btn-primary {
  background: linear-gradient(180deg, var(--gold-highlight), var(--gold) 60%, var(--gold-deep));
  border-color: var(--gold);
  color: #1a1208;
}
.leaderboard-prompt-actions .btn-primary:hover { filter: brightness(1.06); }
.leaderboard-prompt-actions .btn:hover { border-color: var(--gold); color: var(--gold-highlight); }
.leaderboard-prompt-actions .btn-primary:disabled,
.leaderboard-prompt-actions .btn:disabled { opacity: 0.5; cursor: wait; }
.leaderboard-prompt-error {
  margin: 10px 0 0;
  font-size: 13px;
  color: #ff8d80;
}
.leaderboard-prompt-result {
  text-align: left;
}
.leaderboard-rank-readout {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.06em;
  color: var(--gold-highlight);
  margin: 0 0 14px;
}
.leaderboard-rank-line { display: block; }

@media (min-width: 768px) {
  .leaderboard-prompt-overlay {
    align-items: center;
  }
}

/* =====================================================================
   Leaderboard view screen (#screen-leaderboard)
   ===================================================================== */
#screen-leaderboard.active {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  /* Long boards (Today / Past 30 / HoF can each have up to 100 rows
     plus the me-row + Field Report + tabs above) need to scroll. The
     base .screen rule has `overflow: visible` so without this the rows
     spill off the bottom of the viewport with no way to reach them. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: radial-gradient(circle at 30% 20%, rgba(212, 165, 116, 0.04), transparent 60%),
              radial-gradient(circle at 70% 80%, rgba(212, 165, 116, 0.04), transparent 60%),
              var(--bg-deep);
}
.leaderboard-view {
  width: min(720px, 100%);
  margin: 0 auto;
  padding: 24px 20px 80px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  position: relative;
  z-index: 2;
}
.leaderboard-header {
  /* 1fr · auto · 1fr puts the title in the middle column, dead-center
     over the leaderboard view, while the back button hugs the left
     edge in column 1 (justify-self: start). The empty 1fr in column 3
     mirrors column 1 so the title stays centered regardless of back-
     button width. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  padding: 4px 0 6px;
}
.leaderboard-back { justify-self: start; }
.leaderboard-title { grid-column: 2; text-align: center; }
.leaderboard-title {
  font-family: var(--font-display);
  font-size: clamp(28px, 5vw, 40px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--metallic-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin: 0;
}
.leaderboard-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: rgba(245, 230, 192, 0.04);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  color: var(--text-primary);
  font: 500 13px/1 var(--font-display);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease;
}
.leaderboard-back svg { width: 16px; height: 16px; }
.leaderboard-back:hover { border-color: var(--gold); color: var(--gold-highlight); }

/* Ranked / Casual top-level toggle. Sits above the subtab strip and
   swaps which subtabs are visible. Pill-shaped segmented control,
   centered above the subtab grid. */
.lb-section-toggle {
  display: flex;
  width: fit-content;
  margin: 0 auto 10px;
  padding: 4px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  gap: 4px;
}
.lb-section-btn {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 8px 22px;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  .lb-section-btn:hover { color: var(--gold-highlight); }
}
.lb-section-btn.active {
  background: rgba(212, 165, 116, 0.12);
  color: var(--gold-highlight);
  border-color: var(--border-strong);
  box-shadow: inset 0 0 0 1px var(--border-soft);
}
/* Ranked is the headline section (daily / past-30 / hall-of-fame) and
   shares the navy/cyan treatment of the Daily Challenge button on the
   title screen so the visual hierarchy reads "this is the important
   one." Casual keeps the gold treatment from the base .active rule. */
#lb-section-ranked.active {
  background: linear-gradient(180deg,
    rgba(80, 165, 220, 0.55) 0%,
    rgba(28, 75, 130, 0.78) 50%,
    rgba(8, 22, 45, 0.97) 100%);
  color: #d8eeff;
  border-color: rgba(170, 220, 255, 0.7);
  box-shadow:
    inset 0 1px 0 rgba(170, 220, 255, 0.3),
    0 0 14px rgba(80, 165, 220, 0.28);
}
@media (hover: hover) {
  #lb-section-ranked:hover { color: #d8eeff; }
}

.leaderboard-tabs {
  /* Was a fixed 5-column grid (designed for the old 5 era tabs).
     Now the visible tabs are 3 (Ranked) or 5 (Casual) depending on
     section. Flex with flex:1 children + hidden-aware [hidden] auto-
     distributes the width. */
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 12px;
}
.leaderboard-tabs .era-seg[hidden] { display: none !important; }
.leaderboard-tabs .era-seg {
  flex: 1 1 0;
  min-width: 0;
  padding: 10px 8px;
  text-align: center;
  border-radius: 8px;
  background: transparent;
  border: 1px solid transparent;
}
.leaderboard-tabs .era-seg .era-name {
  font: 600 12px/1 var(--font-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.leaderboard-tabs .era-seg.active {
  background: rgba(212, 165, 116, 0.08);
  border-color: var(--border-strong);
  box-shadow: inset 0 0 0 1px var(--border-soft);
}
.leaderboard-tabs .era-seg.active .era-name { color: var(--gold-highlight); }
.leaderboard-tabs .era-seg:hover .era-name { color: var(--gold-highlight); }

/* Mobile: 5 casual era tabs (All / Ancient / Medieval / Renaissance / Modern)
   shrink below their text width with the default flex:1 1 0; min-width:0,
   so labels overlap. Switch to a horizontal scroll row on narrow viewports
   so each pill keeps its intrinsic width. */
@media (max-width: 480px) {
  .leaderboard-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
  }
  .leaderboard-tabs::-webkit-scrollbar { display: none; }
  .leaderboard-tabs .era-seg {
    flex: 0 0 auto;
    min-width: 88px;
    padding: 10px 14px;
    scroll-snap-align: start;
  }
  .leaderboard-tabs .era-seg .era-name { white-space: nowrap; }
}

.leaderboard-status {
  font-size: 14px;
  color: var(--text-muted);
  text-align: center;
  padding: 24px 0;
}

/* "How you stack up" — collapsible chart panel that lives above the
   leaderboard rows on the Today tab. Hidden by default; main.js drops
   the [hidden] attr when the spoiler-gate is satisfied (player has
   proven they've played today). Native <details>/<summary> drives the
   collapse so we get keyboard + a11y for free. */
.lb-perf-panel {
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  overflow: hidden;
  /* Subtle gold inner glow so it reads as a featured surface, not just
     another row. Kept low-alpha to match the rest of the leaderboard. */
  box-shadow: inset 0 1px 0 rgba(245, 230, 192, 0.06);
}
.lb-perf-summary {
  /* Reset the default ▶ disclosure marker — we draw our own chevron
     so it can be styled and animated consistently with the brand. */
  list-style: none;
  cursor: pointer;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-highlight);
  user-select: none;
}
.lb-perf-summary::-webkit-details-marker { display: none; }
.lb-perf-title { line-height: 1; }
/* Mid-summary "Tap to view breakdown" hint — pushes the chevron to the
   far right and turns the whole row into an obvious CTA. The pulse + a
   slight hover lift signal "this opens." */
.lb-perf-cta {
  margin-left: auto;
  padding: 4px 10px;
  border: 1px solid rgba(245, 230, 192, 0.45);
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: none;
  color: var(--gold-highlight);
  background: rgba(245, 230, 192, 0.08);
  box-shadow: 0 0 0 0 rgba(245, 230, 192, 0.0);
  animation: lb-perf-cta-pulse 2200ms ease-in-out infinite;
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease;
}
.lb-perf-summary:hover .lb-perf-cta,
.lb-perf-summary:focus-visible .lb-perf-cta {
  background: rgba(245, 230, 192, 0.18);
  border-color: rgba(245, 230, 192, 0.75);
  color: #fff8e6;
}
@keyframes lb-perf-cta-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 230, 192, 0.00); }
  50%      { box-shadow: 0 0 14px 0 rgba(245, 230, 192, 0.35); }
}
/* Brighten the whole summary row on hover so the panel feels live. */
.lb-perf-summary { transition: background 180ms ease; }
.lb-perf-summary:hover { background: rgba(245, 230, 192, 0.04); }
/* "How scoring works ↗" chip — sibling of the breakdown CTA. Clicking it
   navigates to the About page scrolled to the Scoring section. Stops the
   click from also toggling the parent <details> via stopPropagation in JS. */
.lb-about-scoring-chip {
  appearance: none;
  background: transparent;
  border: 1px solid rgba(245, 230, 192, 0.30);
  border-radius: 999px;
  padding: 4px 10px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--gold);
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease;
}
.lb-about-scoring-chip:hover,
.lb-about-scoring-chip:focus-visible {
  background: rgba(245, 230, 192, 0.12);
  border-color: rgba(245, 230, 192, 0.55);
  color: var(--gold-highlight);
}
.lb-about-scoring-chip svg { width: 10px; height: 10px; }
/* Quiet modifier — used when the chip lives in the leaderboard header as
   metadata under the title (rather than as a CTA-adjacent action in the
   Field Report summary). Reduces opacity and drops the background fill so
   it reads as quiet supporting copy. */
.lb-about-scoring-chip--quiet {
  border: 1px solid rgba(245, 230, 192, 0.20);
  background: transparent;
  opacity: 0.55;
  font-size: 10px;
}
.lb-about-scoring-chip--quiet:hover,
.lb-about-scoring-chip--quiet:focus-visible {
  opacity: 0.85;
  background: transparent;
  border-color: rgba(245, 230, 192, 0.45);
}
/* When the quiet chip sits inside the leaderboard header (3-col grid),
   place it on row 2 spanning all columns, centered — reads as a subtitle
   immediately under the "Leaderboard" h2 rather than as a sibling action. */
.leaderboard-header .lb-about-scoring-chip--quiet {
  grid-column: 1 / -1;
  grid-row: 2;
  justify-self: center;
  margin-top: -2px;
}
/* Once the panel is open, the CTA's job is done — drop the pulse + hint copy
   so it doesn't keep nagging. */
.lb-perf-panel[open] .lb-perf-cta {
  animation: none;
  opacity: 0.55;
}
body.reduce-motion .lb-perf-cta,
@media (prefers-reduced-motion: reduce) {
  .lb-perf-cta { animation: none !important; }
}
.lb-perf-chev {
  font-size: 14px;
  color: var(--gold);
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
  transform: rotate(-90deg);
}
.lb-perf-panel[open] .lb-perf-chev { transform: rotate(0deg); }

/* Share-to-image chip. Lives INLINE inside <summary>, between the
   .lb-perf-cta hint and the .lb-perf-chev — same shape and visual weight
   as the existing .lb-about-scoring-chip pill so the row stays balanced
   (Title · CTA-hint · Share · Chevron). Triggers html2canvas → blob →
   clipboard/share/download chain in main.js. */
.lb-perf-share-btn {
  appearance: none;
  background: rgba(245, 230, 192, 0.08);
  border: 1px solid rgba(245, 230, 192, 0.45);
  border-radius: 999px;
  width: 30px;
  height: 30px;
  position: relative;  /* anchor for invisible touch-target expander */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--gold-highlight);
  flex: 0 0 auto;
  transition: background 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease;
}
/* Invisible touch-target expander. The visible chip stays 30×30 to keep
   the summary row tight, but the actual hit area extends to 44×44 so iOS
   reliably routes the tap to the button rather than the parent <summary>
   toggle. inset:-7px centers the expansion (30 + 7*2 = 44). */
.lb-perf-share-btn::after {
  content: '';
  position: absolute;
  inset: -7px;
}
.lb-perf-share-btn svg { width: 14px; height: 14px; flex: 0 0 auto; }
.lb-perf-share-btn:hover,
.lb-perf-share-btn:focus-visible {
  background: rgba(245, 230, 192, 0.18);
  border-color: rgba(245, 230, 192, 0.75);
  color: #fff8e6;
}
.lb-perf-share-btn:active { transform: scale(0.92); }
/* Loading state during html2canvas render (~200–500ms). Hides the icon
   and draws a gold border-spinner in its place; pointer-events disabled
   so the button can't be re-tapped mid-render. */
.lb-perf-share-btn.is-busy { pointer-events: none; opacity: 0.85; }
.lb-perf-share-btn.is-busy svg { display: none; }
.lb-perf-share-btn.is-busy::before {
  content: '';
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(245, 230, 192, 0.30);
  border-top-color: var(--gold-highlight);
  border-radius: 50%;
  animation: share-card-spin 700ms linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .lb-perf-share-btn.is-busy::before { animation: none; }
}

/* "Top of the field" — section header that kicks off the ranked list
   below the Field Report. Centered Cinzel uppercase between two thin
   gold rules; hidden via [hidden] when the list is empty. */
.leaderboard-list-header[hidden] { display: none; }
.leaderboard-list-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 14px 4px 8px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-highlight);
}
.leaderboard-list-header-text {
  white-space: nowrap;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
}
.leaderboard-list-header-rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(245, 230, 192, 0.0) 0%,
    rgba(245, 230, 192, 0.35) 50%,
    rgba(245, 230, 192, 0.0) 100%);
}

/* Instagram-style verified badge for signed-in players. Tucked next to
   the alias on every leaderboard row; same icon used inline in the
   scoring section's leaderboard explainer. */
.leaderboard-verified-badge {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 5px;
  vertical-align: -2px;
  color: #5DA9E9;
  flex-shrink: 0;
}
.lb-verified-inline {
  display: inline-block;
  width: 18px;
  height: 18px;
  line-height: 18px;
  text-align: center;
  margin: 0 2px;
  background: #5DA9E9;
  color: #fff;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 700;
  vertical-align: -3px;
}
.lb-perf-body {
  padding: 8px 16px 16px;
  border-top: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.lb-perf-chart {
  width: 100%;
  /* Fixed-aspect SVG container; svg inside renders responsively via
     viewBox so the bars + labels scale with the leaderboard width. */
}
.lb-perf-chart svg { display: block; width: 100%; height: auto; }
.lb-perf-bar-bg { fill: rgba(245, 230, 192, 0.06); }
.lb-perf-avg-line {
  stroke: var(--text-primary);
  stroke-width: 2;
  stroke-linecap: round;
  /* Dashed so it reads as a marker overlay, not a bar boundary. Solid
     was visually similar to the bar's edge in some lightings. */
  stroke-dasharray: 5 4;
  opacity: 0.85;
}
.lb-perf-bar-label {
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  fill: var(--text-muted);
}
.lb-perf-bar-value {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  fill: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
  /* Soft dark outline so the gold digits stay legible even when the
     chip beneath them isn't enough (e.g. low-score bars where the
     dashed avg line crosses through). paint-order:stroke-fill renders
     the stroke BEHIND the fill so the digits don't get bolded. */
  paint-order: stroke fill;
  stroke: rgba(0, 0, 0, 0.55);
  stroke-width: 2;
  stroke-linejoin: round;
}
.lb-perf-bar-value-bg {
  fill: rgba(0, 0, 0, 0.62);
}
.lb-perf-legend:not([hidden]) {
  display: flex;
  justify-content: center;
  gap: 22px;
  flex-wrap: wrap;
  /* Cinzel + uppercase + tracked-out matches every other label-ish bit
     of the panel (summary title, axis labels, value numbers) so the
     legend reads like part of the same artifact, not an afterthought. */
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.lb-perf-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.lb-perf-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
/* Era swatches — same gradients the SVG bars use for each era so the
   legend chips literally match the bar colors at a glance. Keep these
   in lockstep with the <linearGradient> defs in _renderPerfChart().
   Palette: muted, gradient, sit pleasantly alongside the warm-gold UI
   without competing — desaturated brick / sage / steel / slate, all
   reading as "tinted greys" rather than primary colors. */
.lb-perf-swatch-ancient {
  /* warm slate — neutral that doesn't fight the brand */
  background: linear-gradient(180deg, #c8c0b3, #5f5a52);
}
.lb-perf-swatch-medieval {
  /* muted brick / parchment red */
  background: linear-gradient(180deg, #d99e95, #8a4940);
}
.lb-perf-swatch-renaissance {
  /* sage olive — botanical, not bright */
  background: linear-gradient(180deg, #b9cba1, #607a4a);
}
.lb-perf-swatch-modern {
  /* dusty steel blue */
  background: linear-gradient(180deg, #a3b8cc, #4d6580);
}
/* The "All" swatch was retired with the legend slim-down — kept the
   class around in case future layouts surface it. */
.lb-perf-swatch-all {
  background: linear-gradient(180deg, #c8c0b3 0%, #d99e95 33%, #b9cba1 66%, #a3b8cc 100%);
}
.lb-perf-swatch-avg {
  width: 14px;
  height: 0;
  border-top: 2px dashed var(--text-primary);
  background: transparent;
  opacity: 0.85;
}

/* "You are here" row — sits ABOVE the Field Report so it's the first
   thing the player sees. Same dark panel as siblings; distinguished by
   a loud champagne border + outer glow. Text inherits the standard
   gold/cream tokens, so legibility is identical to other rows. */
.leaderboard-me-host:not([hidden]) { display: flex; flex-direction: column; }
.lb-me-list { gap: 0; }
.leaderboard-me-host .leaderboard-row {
  background: var(--bg-panel);
  border-color: rgba(245, 230, 192, 0.85);
  box-shadow:
    0 0 24px rgba(245, 230, 192, 0.35),
    inset 0 0 0 1px rgba(245, 230, 192, 0.40);
}
/* Today me-row is clickable (returns to final-results screen). Add
   click affordance + focus ring; the hover lift mirrors the
   round-history-row pattern so the row reads as a button. */
.leaderboard-me-host .leaderboard-row.is-today-me {
  cursor: pointer;
  transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}
@media (hover: hover) {
  .leaderboard-me-host .leaderboard-row.is-today-me:hover {
    transform: translateY(-1px);
    border-color: var(--gold);
    box-shadow:
      0 0 28px rgba(245, 230, 192, 0.5),
      inset 0 0 0 1px rgba(245, 230, 192, 0.55);
  }
}
.leaderboard-me-host .leaderboard-row.is-today-me:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .leaderboard-me-host .leaderboard-row.is-today-me { transition: none; }
}

.leaderboard-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.leaderboard-row {
  display: grid;
  /* rank | name | meta | time | score — meta and time are auto-sized
     and collapse to zero width when their span has no content, so rows
     without time or rich meta render compactly without empty gaps. */
  grid-template-columns: 56px 1fr auto auto auto;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  /* Uniform vertical sizing across tabs (Today / Past 30 / Hall of Fame /
     era boards). Without this, rows with sparse meta render shorter than
     rows with rich meta, so Today and Past 30 tabs felt inconsistent. */
  min-height: 56px;
  background: var(--bg-panel);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
}
/* Collapse empty meta/time spans so the implicit grid gap doesn't leave
   a phantom slot beside rows that don't have those fields populated. */
.leaderboard-row .leaderboard-meta:empty,
.leaderboard-row .leaderboard-time:empty { display: none; }
.leaderboard-row.is-top {
  border-color: var(--border-strong);
  background: linear-gradient(180deg, rgba(212, 165, 116, 0.08), rgba(18, 14, 10, 0.6));
}
.leaderboard-rank {
  font: 700 16px/1 var(--font-display);
  letter-spacing: 0.04em;
  color: var(--gold);
}
.leaderboard-row.is-top .leaderboard-rank { color: var(--gold-highlight); }

/* Top-3 medal emoji that sits at the start of the name cell, just left of
   the alias. Inline so the row grid stays a clean 5-column layout. */
.leaderboard-medal {
  display: inline-block;
  margin-right: 8px;
  font-size: 18px;
  line-height: 1;
  vertical-align: middle;
}

/* ---------- Podium tinting (1=gold, 2=silver, 3=bronze) ----------------
   Subtle metallic accents on top 3. nth-child works because the renderer
   emits rows in rank order and never inserts non-row siblings into
   #leaderboard-list. Alphas kept low (~7-10% bg, ~45-55% border) so the
   medal hint reads at a glance without dominating the row. */
.leaderboard-row.is-top:nth-child(1) {
  border-color: rgba(245, 230, 192, 0.55);
  background: linear-gradient(180deg, rgba(245, 230, 192, 0.10), rgba(18, 14, 10, 0.6));
  box-shadow: inset 0 1px 0 rgba(245, 230, 192, 0.10);
}
.leaderboard-row.is-top:nth-child(1) .leaderboard-rank,
.leaderboard-row.is-top:nth-child(1) .leaderboard-score { color: #f5e6c0; }

.leaderboard-row.is-top:nth-child(2) {
  border-color: rgba(206, 214, 222, 0.45);
  background: linear-gradient(180deg, rgba(206, 214, 222, 0.07), rgba(18, 14, 10, 0.6));
  box-shadow: inset 0 1px 0 rgba(206, 214, 222, 0.08);
}
.leaderboard-row.is-top:nth-child(2) .leaderboard-rank,
.leaderboard-row.is-top:nth-child(2) .leaderboard-score { color: #d6dde4; }

.leaderboard-row.is-top:nth-child(3) {
  border-color: rgba(184, 124, 70, 0.50);
  background: linear-gradient(180deg, rgba(184, 124, 70, 0.08), rgba(18, 14, 10, 0.6));
  box-shadow: inset 0 1px 0 rgba(184, 124, 70, 0.10);
}
.leaderboard-row.is-top:nth-child(3) .leaderboard-rank,
.leaderboard-row.is-top:nth-child(3) .leaderboard-score { color: #d49a6e; }
.leaderboard-name {
  font: 600 15px/1.2 var(--font-body);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.leaderboard-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-size: 11px;
  color: var(--text-muted);
}
.leaderboard-era-tag {
  text-transform: capitalize;
  letter-spacing: 0.08em;
  font-family: var(--font-display);
}
.leaderboard-date {
  color: var(--text-subtle);
}
.leaderboard-score {
  font: 700 18px/1 var(--font-display);
  letter-spacing: 0.04em;
  color: var(--gold-highlight);
  font-variant-numeric: tabular-nums;
}
/* Sits left of the score; lighter weight + muted color so the score
   stays the visual anchor. Tabular-nums keeps the column tidy as times
   like 4:08 / 3:42 / 5:01 line up across rows. */
.leaderboard-time {
  font: 500 13px/1 var(--font-body);
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 540px) {
  .leaderboard-row {
    grid-template-columns: 44px 1fr auto auto;
    gap: 10px;
    padding: 10px 12px;
  }
  .leaderboard-meta { display: none; }
  .leaderboard-name { font-size: 14px; }
  .leaderboard-score { font-size: 16px; }
  .leaderboard-time { font-size: 12px; }
}

/* Hover/tap popover showing the per-round breakdown for a leaderboard
   entry. Positioned absolute by JS relative to .leaderboard-view (which
   already has position:relative). Pointer-events disabled on desktop so
   moving onto the popover doesn't trigger the row's mouseleave; on touch
   we re-enable so taps land. */
.leaderboard-rounds-popover {
  position: absolute;
  z-index: 60;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 10px 14px;
  font: 500 13px/1.4 var(--font-body);
  color: var(--text-primary);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5);
  max-width: 320px;
  min-width: 240px;
  pointer-events: none;
}
.leaderboard-rounds-popover[hidden] { display: none; }
.leaderboard-rounds-popover .lr-title {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 6px;
}
.leaderboard-rounds-popover ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.leaderboard-rounds-popover li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  align-items: baseline;
  font-variant-numeric: tabular-nums;
}
.leaderboard-rounds-popover .lr-label {
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.leaderboard-rounds-popover .lr-year {
  color: var(--text-muted);
  margin-left: 4px;
  font-size: 11px;
}
.leaderboard-rounds-popover .lr-score {
  color: var(--gold);
  font-family: var(--font-display);
  letter-spacing: 0.04em;
}

/* Touch devices: tap-to-toggle. Allow pointer-events so the popover doesn't
   immediately dismiss on its own focus. */
@media (hover: none) {
  .leaderboard-rounds-popover { pointer-events: auto; }
}

/* Visual cue that a row is interactive (has scene history available). */
.leaderboard-row[data-rounds] { cursor: pointer; }

/* Daily challenge is competitive — hide Restart Game in the in-game
   settings popover so a player can't replay scenes they've already seen
   and cherry-pick scores. JS handler also short-circuits as defense in
   depth. body.daily-active is set when the player enters daily mode and
   cleared on exitToTitle / restart-from-fresh. */
body.daily-active #btn-restart { display: none !important; }

/* =================== PRICING UX (B2) =================== */

/* ---- Pricing modal (reuses .signin-overlay backdrop pattern) ---- */
/* The unconditional `display: flex` below overrides the UA `[hidden] { display: none }`
   rule, so `.pricing-modal-overlay[hidden]` must explicitly hide. Without this, the
   modal renders on every page load (HTML ships with `hidden` set; CSS wins the cascade
   and forces display:flex). Same gotcha that bit the era chip in PR #260 and was
   solved with the same `[hidden] { display: none !important }` override pattern. */
.pricing-modal-overlay[hidden] {
  display: none !important;
}
.pricing-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(8, 7, 10, 0.78);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: fadeIn 0.18s ease-out;
}
.pricing-modal-panel {
  position: relative;
  max-width: 1080px; width: 100%;
  max-height: 92vh; overflow-y: auto;
  background: var(--bg-panel);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid var(--border-soft);
  border-radius: 18px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(245, 230, 192, 0.06);
  padding: 32px 28px 36px;
}
.pricing-modal-close {
  position: absolute; top: 14px; right: 14px;
  width: 36px; height: 36px;
  background: rgba(0,0,0,0.25); border: 1px solid var(--border-soft);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-primary); cursor: pointer;
  transition: background 0.15s, transform 0.15s;
}
.pricing-modal-close:hover { background: rgba(0,0,0,0.45); transform: scale(1.05); }
.pricing-modal-close svg { width: 18px; height: 18px; }
.pricing-modal-title {
  font-family: var(--font-display);
  font-size: 1.6rem; letter-spacing: 0.05em;
  text-align: center;
  background: var(--metallic-gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  margin: 0 0 6px;
}
.pricing-modal-subtitle {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.95rem;
  margin: 0 0 24px;
}

/* ---- Card grid ---- */
.pricing-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
@media (max-width: 700px) {
  .pricing-cards { grid-template-columns: 1fr; }
  .pricing-modal-panel { padding: 24px 18px 28px; }
}
.pricing-card {
  position: relative;
  background: var(--bg-panel);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  padding: 22px 20px 24px;
  display: flex; flex-direction: column;
  box-shadow: 0 8px 32px rgba(0,0,0,0.45), inset 0 1px 0 rgba(245,230,192,0.06);
}
.pricing-card-founder {
  border: 1px solid var(--border-strong);
  box-shadow: 0 8px 32px rgba(0,0,0,0.55), 0 0 0 1px var(--gold-glow), inset 0 1px 0 rgba(245,230,192,0.12);
}
.pricing-founder-pill {
  position: absolute; top: 12px; right: 12px;
  background: var(--metallic-gradient);
  color: #1a120a;
  font-family: var(--font-body); font-weight: 600; font-size: 0.72rem;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(139, 105, 20, 0.4);
}
.pricing-card-tier {
  font-family: var(--font-display);
  font-size: 1.05rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 4px;
}
.pricing-card-tagline {
  font-size: 0.82rem; color: var(--text-muted); margin: 0 0 16px;
}
.pricing-card-price {
  font-family: var(--font-display);
  font-size: 2.2rem; font-weight: 600;
  background: var(--metallic-gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  line-height: 1;
}
.pricing-card-price-unit {
  font-size: 0.82rem; color: var(--text-muted); margin-left: 4px;
}
.pricing-card-price-row { margin: 0 0 16px; }
.pricing-card-features { list-style: none; padding: 0; margin: 0 0 20px; flex: 1; }
.pricing-card-features li {
  font-size: 0.88rem; color: var(--text-primary);
  padding: 4px 0 4px 22px; position: relative;
}
.pricing-card-features li::before {
  content: "\2713"; position: absolute; left: 4px;
  color: var(--gold); font-weight: 700;
}
.pricing-cta {
  background: var(--metallic-gradient);
  color: #1a120a; font-family: var(--font-body); font-weight: 600;
  border: none; border-radius: 10px;
  padding: 12px 16px; cursor: pointer;
  font-size: 0.95rem; letter-spacing: 0.02em;
  transition: transform 0.15s, box-shadow 0.15s;
}
.pricing-cta:hover { transform: translateY(-1px); box-shadow: 0 6px 16px var(--gold-glow); }
.pricing-cta:disabled { opacity: 0.55; cursor: wait; transform: none; box-shadow: none; }
.pricing-modal-footer {
  margin-top: 18px; padding-top: 14px;
  border-top: 1px solid var(--border-soft);
  font-size: 0.78rem; color: var(--text-muted); text-align: center;
}
.pricing-modal-footer a { color: var(--gold); text-decoration: underline; }

/* ---- Leaderboard Pro/Founder badge ---- */
.leaderboard-pro-badge,
.leaderboard-founder-badge {
  display: inline-block;
  margin-left: 4px;
  font-size: 0.78em;
  vertical-align: baseline;
  position: relative;
}
.leaderboard-pro-badge {
  color: var(--gold);
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 1px 5px;
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  background: rgba(212, 165, 116, 0.08);
}
.leaderboard-founder-badge {
  color: var(--gold-highlight);
  cursor: help;
}
.leaderboard-founder-badge::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%; left: 50%; transform: translateX(-50%);
  background: var(--bg-panel-strong);
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.7rem;
  color: var(--text-primary);
  white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity 0.15s;
  margin-bottom: 4px;
}
.leaderboard-founder-badge:hover::after { opacity: 1; }

/* ---- Title-screen plays-left chip ---- */
.title-plays-left-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-panel);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 6px 14px;
  font-family: var(--font-body); font-size: 0.82rem;
  color: var(--text-primary);
  margin: 8px auto 0;
  width: max-content;
}
.title-plays-left-chip[hidden] { display: none; }
.title-plays-left-chip svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--gold); }

/* ---- prefers-reduced-motion: disable fade/transform animations ---- */
@media (prefers-reduced-motion: reduce) {
  .pricing-modal-overlay { animation: none; }
  .pricing-cta { transition: none; }
  .pricing-cta:hover { transform: none; }
  .leaderboard-founder-badge::after { transition: none; }
  .pricing-modal-close { transition: none; }
  .pricing-modal-close:hover { transform: none; }
}

/* ---- Tip jar / settings inline icon sizing ---- */
.settings-action svg { width: 16px; height: 16px; vertical-align: -3px; margin-right: 6px; color: var(--gold); }

