/*  CASCADIA FUTURE / WIP terminal  ──────────────────────────────────── */
/*  Palette tuned for green-on-black CRT noir with magenta+cyan accents.  */

:root {
  --bg:           #07090a;
  --bg-glow:      #0d1413;
  --fg:           #5dff7c;
  --fg-dim:       #2e8c45;
  --fg-bright:    #b6ffc4;
  --accent-cyan:  #5df3ff;
  --accent-mag:   #ff5dd3;
  --accent-amber: #ffb86b;
  --danger:       #ff4d6d;
  --scan-opacity: 0.18;
  --crt-glow:     0 0 4px rgba(93, 255, 124, 0.55), 0 0 12px rgba(93, 255, 124, 0.18);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  /* Use dynamic viewport height — accounts for the mobile keyboard rising. */
  height: 100dvh;
  background: var(--bg);
  color: var(--fg);
  font-family: "JetBrains Mono", "Fira Code", "Courier New", ui-monospace, monospace;
  font-size: clamp(12px, 3.4vw, 15px);
  line-height: 1.5;
  letter-spacing: 0.01em;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

body {
  text-shadow: var(--crt-glow);
}

/*  CRT chrome  ───────────────────────────────────────────────────────── */
.crt {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(ellipse at center, var(--bg-glow) 0%, var(--bg) 70%, #000 100%);
  /* Fluid padding — tight on phones, generous on desktop. */
  padding:
    max(env(safe-area-inset-top), clamp(10px, 2.2vw, 24px))
    max(env(safe-area-inset-right), clamp(10px, 3vw, 32px))
    max(env(safe-area-inset-bottom), 8px)
    max(env(safe-area-inset-left), clamp(10px, 3vw, 32px));
  overflow: hidden;
  animation: crt-flicker 4.2s steps(2) infinite;
}

.scanlines {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(0, 0, 0, var(--scan-opacity)) 3px,
    transparent 4px
  );
  pointer-events: none;
  z-index: 5;
  animation: scanlines-drift 8s linear infinite;
}

.vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse at center,
    transparent 40%,
    rgba(0, 0, 0, 0.55) 100%
  );
  pointer-events: none;
  z-index: 4;
}

@keyframes crt-flicker {
  0%, 100% { opacity: 1; }
  92%      { opacity: 0.97; }
  94%      { opacity: 1; }
  96%      { opacity: 0.94; }
  98%      { opacity: 1; }
}

@keyframes scanlines-drift {
  from { transform: translateY(0); }
  to   { transform: translateY(4px); }
}

/*  Terminal layout  ──────────────────────────────────────────────────── */
.terminal {
  position: relative;
  z-index: 10;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding-bottom: 16px;
  scrollbar-width: thin;
  scrollbar-color: var(--fg-dim) transparent;
}
.terminal::-webkit-scrollbar { width: 8px; }
.terminal::-webkit-scrollbar-thumb { background: var(--fg-dim); border-radius: 4px; }

.banner {
  color: var(--accent-cyan);
  /* Scales fluidly — narrow phones get small font, desktops get the full size. */
  font-size: clamp(6px, 2.2vw, 13px);
  line-height: 1.15;
  margin-bottom: 1.2em;
  text-shadow: 0 0 6px rgba(93, 243, 255, 0.45), 0 0 18px rgba(93, 243, 255, 0.15);
  white-space: pre;
  /* Safety net: if the viewport is somehow narrower than expected, scroll
     horizontally instead of clipping. Hidden scrollbar to keep it clean. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  max-width: 100%;
}
.banner::-webkit-scrollbar { display: none; }

.boot {
  white-space: pre-wrap;
  word-break: break-word;
  margin-bottom: 0.6em;
}

/* boot lines */
.boot .line { display: block; }
.boot .ok    { color: var(--fg-bright); }
.boot .warn  { color: var(--accent-amber); }
.boot .err   { color: var(--danger); }
.boot .mag   { color: var(--accent-mag); }
.boot .cyan  { color: var(--accent-cyan); }
.boot .dim   { color: var(--fg-dim); }
.boot .echo  { color: var(--accent-cyan); }

/*  Prompt line  ──────────────────────────────────────────────────────── */
.prompt-line {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  margin-top: 0.4em;
}
.prompt { color: var(--accent-mag); font-weight: 700; flex: 0 0 auto; }
.input-wrap {
  display: flex;
  align-items: baseline;
  flex: 1 1 auto;
  position: relative;
}
#cmd {
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--fg-bright);
  font: inherit;
  caret-color: transparent;
  flex: 1 1 auto;
  padding: 0;
  text-shadow: var(--crt-glow);
}
#cmd:disabled { color: var(--fg-dim); }
.cursor {
  color: var(--fg);
  margin-left: -0.5ch;
  animation: cursor-blink 1.05s steps(2) infinite;
}
@keyframes cursor-blink { 50% { opacity: 0; } }

/*  Status bar  ───────────────────────────────────────────────────────── */
.status-bar {
  position: relative;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em 0.6em;
  font-size: clamp(9px, 2.4vw, 11px);
  padding: 8px 0 0;
  border-top: 1px solid var(--fg-dim);
  color: var(--fg-dim);
}
.status-bar .sep { opacity: 0.5; }
.status-bar .status-right { margin-left: auto; white-space: nowrap; }
.dim { color: var(--fg-dim); }

/*  Glow utilities  ───────────────────────────────────────────────────── */
.glow-green {
  text-shadow:
    0 0 4px rgba(93, 255, 124, 0.6),
    0 0 12px rgba(93, 255, 124, 0.25);
}

/*  Mobile-first is built into the clamp() rules above. These media queries
    only handle truly tiny screens where the status bar items need to drop. */
@media (max-width: 380px) {
  .status-bar .sep,
  .status-bar > span:nth-of-type(4),
  .status-bar > span:nth-of-type(5) {
    display: none;
  }
}

/* Narrow phones: tighten the lichen header so everything fits without scroll. */
@media (max-width: 440px) {
  body.lichen .crt { padding-left: 10px; padding-right: 10px; }
  .title-name { font-size: 14px; letter-spacing: 0.03em; }
  .title-btn  { padding: 3px 7px; min-height: 26px; }
  .stats-strip { gap: 0.3em; font-size: 11px; }
  .strip-sep   { opacity: 0.3; }
}
@media (max-width: 360px) {
  .stats-strip { font-size: 10px; gap: 0.25em; }
  .strip-cell .lbl { font-size: 0.85em; opacity: 0.65; }
  /* Drop the GM + voice cell labels on truly tiny — keep the dots. */
  #strip-backend .lbl,
  #strip-voice   .lbl { display: none; }
}

/*  Respect reduced motion  ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .crt, .scanlines, .cursor { animation: none !important; }
}

/* ─────────────────────────────────────────────────────────────────────── */
/*  LICHEN game shell  (used at /lichen/)                                  */
/* ─────────────────────────────────────────────────────────────────────── */

body.lichen .crt {
  /* The game crt is laid out as: header / main / prompt — full bleed.
     Use visualViewport-tracked --vvh on mobile so the keyboard pushing up
     doesn't hide the prompt; fall back to 100dvh on desktop. */
  display: flex;
  flex-direction: column;
  height: var(--vvh, 100dvh);
  padding-top: max(env(safe-area-inset-top), clamp(8px, 1.6vw, 14px));
  padding-bottom: max(env(safe-area-inset-bottom), 6px);
}

.game-header {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--fg-dim);
  position: relative;
  z-index: 10;
}

/* Compact title bar — replaces the multi-line ASCII banner on the game page. */
.title-bar {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  padding: 2px 0 2px;
  min-height: 28px;
}
.title-text {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.title-name {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.05em;
  font-size: clamp(13px, 3.6vw, 16px);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.45), 0 0 16px rgba(255, 93, 211, 0.15);
}
.title-sub {
  color: var(--fg-dim);
  font-weight: 400;
  margin-left: 0.6em;
  font-size: 0.78em;
  letter-spacing: 0.04em;
}
@media (max-width: 420px) {
  .title-sub { display: none; }
}
.title-actions {
  display: flex;
  gap: 4px;
  flex: 0 0 auto;
}
.title-btn {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg);
  font: inherit;
  font-size: clamp(10px, 2.4vw, 11px);
  padding: 3px 9px;
  cursor: pointer;
  text-shadow: var(--crt-glow);
  letter-spacing: 0.04em;
  min-height: 28px;
  border-radius: 1px;
}
.title-btn:hover, .title-btn:active {
  color: var(--fg-bright);
  border-color: var(--fg);
  background: rgba(93, 255, 124, 0.06);
}

.glow-mag {
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.4), 0 0 18px rgba(255, 93, 211, 0.15);
}

/* Stats strip — single row, horizontal-scroll fallback. */
.stats-strip {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  align-items: center;
  gap: 0.4em;
  padding: 2px 0;
  font-size: clamp(10px, 2.7vw, 12px);
  color: var(--fg-bright);
  scrollbar-width: none;
  white-space: nowrap;
  min-height: 22px;
}
.stats-strip::-webkit-scrollbar { display: none; }
.strip-cell {
  display: inline-flex;
  gap: 0.25em;
  align-items: baseline;
  flex: 0 0 auto;
}
.strip-cell .lbl {
  color: var(--fg-dim);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.strip-sep { color: var(--fg-dim); opacity: 0.45; flex: 0 0 auto; }
.strip-heat { color: var(--accent-amber); }
.strip-heat .lbl { color: var(--accent-amber); opacity: 0.7; }
.strip-cheat {
  color: var(--accent-mag);
  border: 1px solid var(--accent-mag);
  border-radius: 1px;
  padding: 0 5px;
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.55);
  letter-spacing: 0.1em;
  font-weight: 700;
}
.strip-cheat .lbl { color: var(--accent-mag); opacity: 0.9; }

.game-main {
  flex: 1 1 auto;
  position: relative;
  display: flex;
  min-height: 0;          /* allow narrative to scroll inside flex */
  overflow: hidden;
}

/*  Narrative pane — tuned for dyslexia readability:
    - Generous line-height (1.7) gives each line vertical breathing room
    - Stronger paragraph gap (0.95em) creates real navigation between paragraphs
    - max-width caps line length around 70ch (research-backed dyslexia comfort)
    - First-letter accent on narrative paragraphs as a visual anchor          */
.narrative {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 14px 4px 14px 0;
  scrollbar-width: thin;
  scrollbar-color: var(--fg-dim) transparent;
}
.narrative::-webkit-scrollbar { width: 6px; }
.narrative::-webkit-scrollbar-thumb { background: var(--fg-dim); border-radius: 3px; }

.narrative .line {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0 0 0.55em;
  line-height: 1.55;
  max-width: 72ch;
}
.narrative .narrative-line {
  color: #e0ffe9;
  text-shadow: 0 0 3px rgba(93, 255, 124, 0.18);
  line-height: 1.7;             /* extra breathing room between lines within a paragraph */
  letter-spacing: 0.005em;
  margin-bottom: 0.95em;        /* clear gap between paragraphs */
  font-size: 1.02em;            /* slightly larger than UI text */
}
/* First letter of each narrative paragraph — small visual anchor that makes
   paragraph starts easier to find when skimming back. */
.narrative .narrative-line::first-letter {
  color: var(--fg-bright);
  text-shadow: 0 0 6px rgba(182, 255, 196, 0.5);
  font-weight: 700;
}
.narrative .sys    { color: var(--accent-cyan); }
.narrative .echo   { color: var(--accent-mag); font-weight: 700; }
.narrative .update { color: var(--accent-cyan); font-style: italic; }
.narrative .err    { color: var(--danger); }
.narrative .choice { color: var(--fg-bright); }
.narrative .mag    { color: var(--accent-mag); font-weight: 700; }
.narrative .dim    { color: var(--fg-dim); }

/*  Roll card  ──────────────────────────────────────────────────────── */
.roll-card {
  border: 1px solid var(--fg-dim);
  border-left-width: 4px;
  padding: 8px 12px;
  margin: 10px 0;
  background: rgba(13, 20, 19, 0.5);
  border-radius: 2px;
}
.roll-card.ok  { border-left-color: var(--fg);     animation: card-pulse-ok  600ms ease-out; }
.roll-card.bad { border-left-color: var(--danger); animation: card-pulse-bad 600ms ease-out; }
@keyframes card-pulse-ok  { from { box-shadow: 0 0 0 rgba(93,255,124,0.0); } 40% { box-shadow: 0 0 24px rgba(93,255,124,0.5); } to { box-shadow: 0 0 0 rgba(93,255,124,0.0); } }
@keyframes card-pulse-bad { from { box-shadow: 0 0 0 rgba(255,77,109,0.0); } 40% { box-shadow: 0 0 24px rgba(255,77,109,0.55); } to { box-shadow: 0 0 0 rgba(255,77,109,0.0); } }
.roll-head     { font-weight: 700; color: var(--fg-bright); margin-bottom: 4px; }
.roll-card.ok  .roll-body { color: var(--fg); }
.roll-card.bad .roll-body { color: var(--danger); }

/*  Glimpse card  ───────────────────────────────────────────────────── */
.glimpse-card {
  border: 1px solid #2eaa55;
  border-left-width: 4px;
  background: rgba(20, 50, 28, 0.4);
  padding: 10px 14px;
  margin: 12px 0;
  border-radius: 2px;
  color: var(--fg);
  animation: glimpse-pulse 1.2s ease-out;
}
@keyframes glimpse-pulse {
  0%   { box-shadow: 0 0 0 rgba(93,255,124,0.0); transform: translateY(4px); opacity: 0; }
  20%  { box-shadow: 0 0 28px rgba(93,255,124,0.55); transform: translateY(0); opacity: 1; }
  100% { box-shadow: 0 0 0 rgba(93,255,124,0.0); transform: translateY(0); opacity: 1; }
}
.glimpse-head { font-weight: 700; color: var(--fg-bright); margin-bottom: 6px; letter-spacing: 0.04em; }
.glimpse-body { font-style: italic; color: #b6ffc4; }

/*  Sidebar (character sheet)  ──────────────────────────────────────── */
.sidebar {
  position: fixed;        /* fixed → never confuses the prompt layout */
  top: 0; right: 0; bottom: 0;
  width: min(360px, 92vw);
  background: linear-gradient(135deg, rgba(7, 9, 10, 0.97), rgba(13, 20, 19, 0.97));
  border-left: 1px solid var(--accent-mag);
  padding: 18px 18px 18px 22px;
  overflow-y: auto;
  z-index: 30;
  box-shadow: -10px 0 28px rgba(0, 0, 0, 0.6);
  transform: translateX(100%);
  transition: transform 220ms ease-out;
  font-size: clamp(11px, 2.6vw, 13px);
}
/* Defensive: when [hidden] is set (closed), force-collapse on mobile. */
.sidebar[hidden] { display: none !important; }
body.sidebar-open .sidebar { transform: translateX(0); }
.sidebar-close {
  position: absolute;
  top: 8px;
  right: 12px;
  background: transparent;
  border: 0;
  color: var(--fg-dim);
  font: inherit;
  font-size: 16px;
  cursor: pointer;
}
.sidebar-close:hover { color: var(--fg-bright); }

.sheet-empty {
  padding: 16px 0;
  color: var(--fg-dim);
}
.sheet-empty-title {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.35);
}
.sheet-empty p { margin: 0 0 8px; line-height: 1.5; }

.sheet-block { margin: 8px 0 14px; }
.sheet-row {
  display: flex;
  justify-content: space-between;
  gap: 0.8em;
  padding: 2px 0;
}
.sheet-row .k { color: var(--fg-dim); font-weight: 700; letter-spacing: 0.04em; }
.sheet-section {
  margin: 18px 0 6px;
  color: var(--fg-dim);
  font-weight: 700;
  letter-spacing: 0.1em;
  border-top: 1px dashed var(--fg-dim);
  padding-top: 8px;
}
.sheet-stats {
  width: 100%;
  border-collapse: collapse;
}
.sheet-stats th { text-align: left; color: var(--fg-bright); padding: 2px 8px 2px 0; }
.sheet-stats td { padding: 2px 0; }
.sheet-stats td.r { text-align: right; padding-left: 6px; }
.sheet-list { list-style: none; }
.sheet-list li { padding: 1px 0; }
.sheet-list li.cy { color: var(--accent-cyan); }
.sheet-list li.dim, .sidebar .dim { color: var(--fg-dim); }
.inv-item {
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--fg-bright);
  cursor: pointer;
  text-align: left;
  text-shadow: var(--crt-glow);
  border-bottom: 1px dashed transparent;
}
.inv-item:hover, .inv-item:focus {
  color: var(--accent-cyan);
  border-bottom-color: var(--accent-cyan);
  outline: 0;
}
.quests { list-style: none; }
.quests li { padding: 2px 0; }

/*  Desktop: sidebar always visible, inline ─────────────────────────── */
@media (min-width: 880px) {
  body.lichen .game-main { gap: 0; }
  .sidebar {
    position: relative;
    transform: none !important;
    width: 340px;
    flex: 0 0 340px;
    box-shadow: none;
    border-left: 1px solid var(--fg-dim);
    display: block !important;
  }
  .sidebar[hidden] { display: block !important; }
  .sidebar-close { display: none; }
  /* On desktop, the sheet button in the title is also redundant. */
  #burger { display: none; }
}

/*  Prompt at bottom  ───────────────────────────────────────────────── */
.game-prompt {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 10px 0 0;
  border-top: 1px solid var(--fg-dim);
  position: relative;
  z-index: 10;
}
.game-prompt .prompt {
  color: var(--accent-mag);
  font-weight: 700;
  flex: 0 0 auto;
  font-size: clamp(11px, 2.8vw, 13px);
  transition: color 200ms;
}
.game-prompt .prompt.flash { color: var(--fg-bright); }
.game-prompt .prompt-arrow {
  color: var(--fg-dim);
  flex: 0 0 auto;
  transition: color 200ms;
}
body.streaming .game-prompt .prompt-arrow {
  color: var(--accent-cyan);
  animation: arrow-pulse 1.2s ease-in-out infinite;
}
@keyframes arrow-pulse {
  0%, 100% { opacity: 0.4; text-shadow: 0 0 0 transparent; }
  50%      { opacity: 1; text-shadow: 0 0 8px rgba(93, 243, 255, 0.6); }
}
.game-prompt input {
  flex: 1 1 auto;
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--fg-bright);
  font: inherit;
  font-size: clamp(13px, 3.6vw, 15px);
  padding: 6px 0;
  min-width: 0;
  text-shadow: var(--crt-glow);
  /* Visible blinking caret in cyan — used to be transparent which made it
     impossible to tell the input was focused. Browsers don't let us thicken
     the caret directly so we lean on color + the input glow below. */
  caret-color: var(--accent-cyan);
  caret-shape: block;            /* progressive enhancement: thicker block on Chrome 137+ */
  /* Kill the mobile Chrome / iOS Safari input chrome (clear button, contact picker icon). */
  -webkit-appearance: none;
  appearance: none;
  border-bottom: 1px solid transparent;  /* reserved space for the focus underline */
  transition: border-color 180ms;
}
.game-prompt input:focus {
  /* Cyan glow underline when focused — second visual signal that this is the typing zone. */
  border-bottom-color: rgba(93, 243, 255, 0.5);
}
/* Light up the prompt-arrow whenever the input is focused — third indicator
   for users (like dyslexic readers) who scan visual cues over text. */
.game-prompt:has(input:focus) .prompt-arrow {
  color: var(--accent-cyan);
  animation: arrow-pulse 1.4s ease-in-out infinite;
}
.game-prompt input::-webkit-search-cancel-button,
.game-prompt input::-webkit-search-decoration,
.game-prompt input::-webkit-clear-button,
.game-prompt input::-webkit-contacts-auto-fill-button,
.game-prompt input::-webkit-credentials-auto-fill-button {
  display: none !important;
  -webkit-appearance: none !important;
}
.game-prompt input:disabled {
  color: var(--fg-dim);
}
.game-prompt input::placeholder { color: var(--fg-dim); opacity: 0.6; }
.cmd-go {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg);
  font: inherit;
  font-size: 14px;
  padding: 6px 12px;
  cursor: pointer;
  text-shadow: var(--crt-glow);
  flex: 0 0 auto;
}
.cmd-go:hover { color: var(--fg-bright); border-color: var(--fg); }
.cmd-go:disabled { color: var(--fg-dim); cursor: default; }

/* ─────────────────────────────────────────────────────────────────────── */
/*  Cascadia map overlay                                                   */
/* ─────────────────────────────────────────────────────────────────────── */

.map-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(3, 6, 10, 0.985);
  display: flex;
  flex-direction: column;
  pointer-events: auto;
  padding: max(env(safe-area-inset-top), 14px)
          max(env(safe-area-inset-right), 12px)
          max(env(safe-area-inset-bottom), 14px)
          max(env(safe-area-inset-left), 12px);
  animation: map-fade-in 220ms ease-out;
}
@keyframes map-fade-in {
  from { opacity: 0; transform: scale(0.985); }
  to   { opacity: 1; transform: scale(1); }
}

/* CRITICAL: defensive [hidden] rules. The HTML `hidden` attribute defaults
   to display:none via the UA stylesheet, but any author CSS that sets
   display on the same element wins by specificity/source order. Without
   these rules, .map-overlay and .map-confirm stay rendered on top of the
   page even when "closed", silently intercepting every click. */
.map-overlay[hidden]  { display: none !important; }
.map-confirm[hidden]  { display: none !important; }

.map-head {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  border-bottom: 1px solid var(--accent-mag);
  padding-bottom: 8px;
  margin-bottom: 8px;
  flex: 0 0 auto;
}
.map-title {
  color: var(--accent-mag);
  font-weight: 700;
  font-size: clamp(12px, 3.0vw, 14px);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.4);
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.map-close {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg);
  font: inherit;
  padding: 4px 10px;
  cursor: pointer;
  flex: 0 0 auto;
}
.map-close:hover { color: var(--danger); border-color: var(--danger); }

.map-body {
  flex: 1 1 auto;
  overflow: auto;
  font-family: "JetBrains Mono", "Fira Code", "Courier New", ui-monospace, monospace;
  font-size: clamp(8px, 2.0vw, 12px);
  line-height: 1.25;
  color: var(--fg-bright);
  padding: 4px 0;
  scrollbar-width: thin;
  scrollbar-color: var(--fg-dim) transparent;
}
.map-body::-webkit-scrollbar { width: 8px; height: 8px; }
.map-body::-webkit-scrollbar-thumb { background: var(--fg-dim); border-radius: 4px; }

.map-row {
  white-space: pre;
  letter-spacing: 0;
}

/* Geography canvas — the terrain is a single <pre>, waypoints overlay it. */
.map-canvas {
  position: relative;
  font-family: "JetBrains Mono", "Fira Code", "Courier New", ui-monospace, monospace;
  font-size: clamp(8px, 2.0vw, 12px);
  line-height: 1.2;
  letter-spacing: 0;
  /* tab-size: 1 in case any tabs slip in */
  tab-size: 1;
  font-variant-ligatures: none;  /* prevent ligature reflow of -- => etc. */
}
.map-terrain {
  margin: 0;
  padding: 0;
  white-space: pre;
  color: var(--fg-bright);
  font: inherit;
}
.map-wps {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.wp-overlay {
  position: absolute;
  /* --r row, --c column — 0-indexed */
  top: calc(var(--r) * 1lh);
  left: calc(var(--c) * 1ch);
  margin: 0;
  padding: 0 2px;
  border: 0;
  background: rgba(7, 9, 10, 0.85);
  color: var(--accent-cyan);
  font: inherit;
  font-weight: 700;
  letter-spacing: 0;
  white-space: nowrap;
  cursor: pointer;
  text-shadow: 0 0 6px rgba(93, 243, 255, 0.4);
  pointer-events: auto;
  border-radius: 2px;
  z-index: 2;
  transition: color 120ms, background 120ms, text-shadow 120ms;
}
.wp-overlay:hover, .wp-overlay:focus {
  color: var(--fg-bright);
  background: rgba(7, 30, 20, 0.95);
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.7), 0 0 16px rgba(93, 243, 255, 0.5);
  outline: 0;
}
.wp-overlay.danger {
  color: var(--accent-mag);
  animation: danger-pulse 3.4s ease-in-out infinite;
}
@keyframes danger-pulse {
  0%, 100% {
    text-shadow: 0 0 6px rgba(255, 93, 211, 0.4);
  }
  50% {
    text-shadow: 0 0 8px rgba(255, 93, 211, 0.7), 0 0 18px rgba(255, 93, 211, 0.4);
  }
}
.wp-overlay.danger:hover {
  color: #fff;
  background: rgba(40, 7, 24, 0.95);
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.7), 0 0 16px rgba(255, 93, 211, 0.5);
  animation: none;
}
@media (prefers-reduced-motion: reduce) {
  .wp-overlay.danger { animation: none; }
}
.wp-overlay:active { transform: translateY(1px); }

/* Hover tooltip — shows the blurb below the waypoint on hover. */
.wp-overlay::after {
  content: attr(data-tip);
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  background: rgba(7, 9, 10, 0.96);
  color: var(--fg-bright);
  font-weight: 400;
  font-style: italic;
  font-size: 0.92em;
  padding: 4px 8px;
  border: 1px solid var(--accent-cyan);
  border-radius: 2px;
  white-space: normal;
  width: max-content;
  max-width: min(360px, 80vw);
  z-index: 10;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms 60ms;  /* small delay before showing */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.7);
  text-shadow: none;
}
.wp-overlay.danger::after {
  border-color: var(--accent-mag);
}
.wp-overlay:hover::after, .wp-overlay:focus::after {
  opacity: 1;
}
/* Suppress the native browser tooltip from the title attribute — we use our own. */
.wp-overlay {
  /* keep title for a11y but prevent native tooltip via JS (see app.js) */
}

/* Terrain layers — colored spans rendered into the ASCII rows. */
.m-mt   { color: #7a99a1; text-shadow: 0 0 3px rgba(122, 153, 161, 0.3); }
.m-peak { color: #c4dde4; text-shadow: 0 0 6px rgba(196, 221, 228, 0.55), 0 0 14px rgba(196, 221, 228, 0.2); font-weight: 700; }
.m-snow { color: #e8f4f8; text-shadow: 0 0 8px rgba(232, 244, 248, 0.55), 0 0 16px rgba(196, 221, 228, 0.25); font-weight: 700; }
.m-riv  { color: #5df3ff; text-shadow: 0 0 6px rgba(93, 243, 255, 0.5), 0 0 16px rgba(93, 243, 255, 0.25); }
.m-will { color: #7ec8ff; text-shadow: 0 0 5px rgba(126, 200, 255, 0.45); }
.m-pac  { color: #4ad4e8; text-shadow: 0 0 6px rgba(74, 212, 232, 0.5), 0 0 14px rgba(74, 212, 232, 0.18); }
.m-frs-d { color: #2a6a3c; text-shadow: 0 0 4px rgba(42, 106, 60, 0.55); }   /* densest */
.m-frs-m { color: #3a9656; text-shadow: 0 0 5px rgba(58, 150, 86, 0.5); }
.m-frs-l { color: #5cc578; text-shadow: 0 0 6px rgba(92, 197, 120, 0.45); }
.m-frm   { color: #4a7a82; }
.m-lbl   { color: #d6ffe2; font-weight: 700; letter-spacing: 0.05em; text-shadow: 0 0 4px rgba(214, 255, 226, 0.25); }
.m-cmp   { color: #c4dde4; opacity: 0.75; font-weight: 700; letter-spacing: 0.1em; }
.m-dim   { color: var(--fg-dim); font-style: italic; }
.m-brg   { color: var(--accent-amber); font-weight: 700; text-shadow: 0 0 5px rgba(255, 184, 107, 0.4); }
.m-orn   { color: var(--accent-mag); text-shadow: 0 0 6px rgba(255, 93, 211, 0.5), 0 0 14px rgba(255, 93, 211, 0.15); }
.m-cld   { color: #9bb0b8; opacity: 0.5; font-style: italic; }
.m-road  { color: #d2c39a; text-shadow: 0 0 4px rgba(210, 195, 154, 0.3); }   /* highway asphalt */
.m-hwy   { color: #ffd76b; font-weight: 700; text-shadow: 0 0 5px rgba(255, 215, 107, 0.55), 0 0 12px rgba(255, 215, 107, 0.2); letter-spacing: 0.02em; }
.m-wnd   {
  color: #b6dfff;
  opacity: 0.7;
  animation: wind-drift 5.5s linear infinite;
}
@keyframes wind-drift {
  0%   { opacity: 0.4; }
  50%  { opacity: 0.95; }
  100% { opacity: 0.4; }
}
.m-rail  {
  color: #ff9d6b;
  text-shadow: 0 0 4px rgba(255, 157, 107, 0.4);
  letter-spacing: 0;
  animation: rail-pulse 4.5s ease-in-out infinite;
}
@keyframes rail-pulse {
  0%, 100% { opacity: 0.65; }
  50%      { opacity: 1;    text-shadow: 0 0 8px rgba(255, 157, 107, 0.6); }
}
.m-dam   {
  color: #c2b18a;
  text-shadow: 0 0 4px rgba(194, 177, 138, 0.4);
  animation: dam-pulse 2.8s ease-in-out infinite;
}
@keyframes dam-pulse {
  0%, 100% { color: #8a7c5e; }
  50%      { color: #ffd76b; text-shadow: 0 0 8px rgba(255, 215, 107, 0.6); }
}
.m-riv {
  animation: river-shimmer 6s ease-in-out infinite;
}
@keyframes river-shimmer {
  0%, 100% { text-shadow: 0 0 6px rgba(93, 243, 255, 0.5), 0 0 16px rgba(93, 243, 255, 0.25); }
  50%      { text-shadow: 0 0 8px rgba(93, 243, 255, 0.8), 0 0 22px rgba(93, 243, 255, 0.4); }
}
@media (prefers-reduced-motion: reduce) {
  .m-wnd, .m-rail, .m-dam, .m-riv { animation: none; }
}

/* Waypoints — clickable, glow on hover/tap */
.wp {
  color: var(--accent-cyan);
  font-weight: 700;
  cursor: pointer;
  text-shadow: 0 0 6px rgba(93, 243, 255, 0.4);
  border-radius: 2px;
  transition: color 120ms, text-shadow 120ms, background 120ms;
  padding: 0 1px;
}
.wp:hover, .wp:focus {
  color: var(--fg-bright);
  background: rgba(93, 243, 255, 0.18);
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.8), 0 0 18px rgba(93, 243, 255, 0.6);
  outline: 0;
}
.wp.danger { color: var(--accent-mag); }
.wp.danger:hover {
  color: #fff;
  background: rgba(255, 93, 211, 0.2);
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.8), 0 0 18px rgba(255, 93, 211, 0.6);
}
.wp:active { transform: translateY(1px); }

.map-foot {
  flex: 0 0 auto;
  padding-top: 8px;
  border-top: 1px solid var(--fg-dim);
  font-size: clamp(9px, 2.4vw, 11px);
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.map-confirm {
  position: absolute;
  bottom: max(env(safe-area-inset-bottom), 14px);
  left: 50%;
  transform: translateX(-50%);
  max-width: min(560px, calc(100% - 28px));
  background: linear-gradient(135deg, rgba(7, 9, 10, 0.97), rgba(20, 50, 28, 0.92));
  border: 1px solid var(--fg);
  padding: 10px 14px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6em;
  z-index: 60;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.7), 0 0 14px rgba(93, 255, 124, 0.25);
  font-size: clamp(11px, 2.6vw, 13px);
}
.map-confirm #map-confirm-text { flex: 1 1 200px; color: var(--fg-bright); }
.map-confirm .confirm-yes,
.map-confirm .confirm-no {
  background: transparent;
  font: inherit;
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 2px;
  text-shadow: var(--crt-glow);
}
.map-confirm .confirm-yes {
  color: var(--fg);
  border: 1px solid var(--fg);
}
.map-confirm .confirm-yes:hover { color: var(--fg-bright); background: rgba(93, 255, 124, 0.15); }
.map-confirm .confirm-no {
  color: var(--fg-dim);
  border: 1px solid var(--fg-dim);
}
.map-confirm .confirm-no:hover { color: var(--fg); border-color: var(--fg); }

/* hide the rest of the screen's input while map is open */
body.map-open .game-prompt { opacity: 0.4; pointer-events: none; }

/* ═══════════════════════════════════════════════════════════════════════
   LOCATION DECK — region-grouped CSS cards. Primary map view as of v31.
   ═══════════════════════════════════════════════════════════════════════ */

.map-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 12px;
  padding: 6px 4px 10px;
  border-bottom: 1px dashed rgba(93, 243, 255, 0.18);
  margin-bottom: 10px;
  font-size: clamp(10px, 2.4vw, 12px);
}
.map-mode { display: inline-flex; gap: 4px; }
.map-tab {
  font: inherit;
  background: transparent;
  color: var(--fg-dim);
  border: 1px solid rgba(93, 243, 255, 0.25);
  padding: 4px 12px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 2px;
  transition: color 120ms, background 120ms, border-color 120ms;
}
.map-tab:hover { color: var(--fg-bright); border-color: var(--accent-cyan); }
.map-tab.active {
  color: #050811;
  background: var(--accent-cyan);
  border-color: var(--accent-cyan);
  box-shadow: 0 0 10px rgba(93, 243, 255, 0.4);
}

/* The cards live inside .map-canvas; reset the legacy ASCII font sizing */
.map-canvas:has(.loc-deck),
.map-canvas:has(.map-illustrated) {
  font: inherit;
  position: relative;
  width: 100%;
}

.loc-deck {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 2px;
}
.loc-region { display: flex; flex-direction: column; gap: 10px; }
.region-title {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(93, 243, 255, 0.2);
}
.region-title::before {
  content: "›";
  color: var(--accent-cyan);
  opacity: 0.6;
  margin-right: -8px;
}
.region-name {
  font-size: clamp(11px, 2.4vw, 14px);
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--accent-cyan);
  text-shadow: 0 0 6px rgba(93, 243, 255, 0.4);
}
.region-meta {
  font-size: clamp(9px, 2vw, 11px);
  font-style: italic;
  color: var(--fg-dim);
  letter-spacing: 0.05em;
}
.loc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 8px;
}
@media (max-width: 480px) {
  .loc-grid { grid-template-columns: 1fr; }
}
.loc-card {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 12px;
  text-align: left;
  background: linear-gradient(135deg, rgba(7, 13, 18, 0.85), rgba(10, 18, 26, 0.65));
  border: 1px solid rgba(93, 243, 255, 0.18);
  padding: 11px 14px 11px 12px;
  cursor: pointer;
  font: inherit;
  color: var(--fg);
  border-radius: 2px;
  transition: border-color 140ms, background 140ms, transform 140ms, box-shadow 140ms;
  overflow: hidden;
}
.loc-card::before {
  /* corner notch decoration — adds a tiny cyberpunk diagonal cut */
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 10px;
  height: 10px;
  background: linear-gradient(225deg, rgba(93, 243, 255, 0.45) 50%, transparent 50%);
  opacity: 0.5;
  transition: opacity 140ms;
}
.loc-card:hover, .loc-card:focus {
  border-color: var(--accent-cyan);
  background: linear-gradient(135deg, rgba(10, 30, 38, 0.92), rgba(14, 44, 52, 0.78));
  outline: 0;
  box-shadow:
    0 0 0 1px rgba(93, 243, 255, 0.22),
    0 4px 18px rgba(0, 0, 0, 0.55),
    0 0 22px rgba(93, 243, 255, 0.16);
  transform: translateY(-1px);
}
.loc-card:hover::before, .loc-card:focus::before { opacity: 1; }
.loc-card:active { transform: translateY(0); }
.loc-sigil {
  flex: 0 0 auto;
  width: 32px;
  font-size: 24px;
  line-height: 1;
  color: var(--accent-cyan);
  text-shadow: 0 0 10px rgba(93, 243, 255, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid rgba(93, 243, 255, 0.15);
  padding-right: 10px;
  margin-right: -2px;
}
.loc-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding-right: 8px;
}
.loc-name {
  font-size: clamp(11px, 2.4vw, 13px);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--fg-bright);
  text-shadow: 0 0 4px rgba(93, 243, 255, 0.25);
}
.loc-vibe {
  font-size: clamp(9.5px, 2.1vw, 11px);
  font-style: italic;
  color: var(--fg-dim);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.loc-badge {
  position: absolute;
  bottom: 6px;
  right: 8px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--accent-mag);
  background: rgba(40, 6, 22, 0.8);
  border: 1px solid rgba(255, 93, 211, 0.45);
  padding: 1px 6px;
  border-radius: 1px;
  text-shadow: 0 0 4px rgba(255, 93, 211, 0.5);
}

/* Danger variant — magenta accents */
.loc-card.danger {
  border-color: rgba(255, 93, 211, 0.3);
  background: linear-gradient(135deg, rgba(15, 7, 13, 0.88), rgba(22, 10, 18, 0.7));
}
.loc-card.danger::before {
  background: linear-gradient(225deg, rgba(255, 93, 211, 0.5) 50%, transparent 50%);
}
.loc-card.danger .loc-sigil {
  color: var(--accent-mag);
  text-shadow: 0 0 10px rgba(255, 93, 211, 0.55);
  border-right-color: rgba(255, 93, 211, 0.2);
}
.loc-card.danger .loc-name {
  text-shadow: 0 0 4px rgba(255, 93, 211, 0.3);
}
.loc-card.danger:hover, .loc-card.danger:focus {
  border-color: var(--accent-mag);
  background: linear-gradient(135deg, rgba(38, 8, 22, 0.92), rgba(48, 14, 30, 0.78));
  box-shadow:
    0 0 0 1px rgba(255, 93, 211, 0.25),
    0 4px 18px rgba(0, 0, 0, 0.55),
    0 0 22px rgba(255, 93, 211, 0.2);
}

/* ───── Illustrated mode (AI image + HTML hotspots) ───── */
.map-illustrated {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #050811;
  border: 1px solid rgba(93, 243, 255, 0.12);
  border-radius: 3px;
  overflow: hidden;
  isolation: isolate;
}

/* The satellite image is the bottom layer. Darken + slightly desaturate so
   the neon vectors on top read clearly. CSS filters here are cheap. */
.map-illustration {
  filter: brightness(0.42) saturate(0.55) contrast(1.05);
}

/* Dark blue tint over the satellite. Combines with the brightness filter
   above to give the cyberpunk-night vibe without losing geography. */
.map-tint {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 60%, rgba(8, 12, 24, 0) 0%, rgba(4, 6, 14, 0.55) 100%),
    linear-gradient(135deg, rgba(0, 30, 60, 0.30), rgba(40, 0, 50, 0.18));
  mix-blend-mode: multiply;
}

/* ═══ SVG vector overlay ═════════════════════════════════════════════════
   Performance notes:
   - The OSM data has ~6000 way-segments. SVG <filter> on a <g> containing
     thousands of paths forces the browser to render the whole group offscreen
     and blur every frame → unusable. So glow is faked via brighter, slightly
     wider strokes and pure color saturation. No filter URL references.
   - Animations are scoped to <g> wrappers and use opacity/color/transform
     only (GPU-accelerated). No per-path stroke-dashoffset animation across
     thousands of paths.
*/
.map-vectors {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  pointer-events: none;
}

/* HUD regulator grid — faint pale-blue tactical grid across the canvas. */
.vec-hud-grid line {
  stroke: rgba(93, 243, 255, 0.10);
  stroke-width: 0.5;
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* Coastline — bright cyan, slightly wider stroke = fake glow without filter. */
.vec-coast {
  stroke: #9ff5ff;
  stroke-width: 1.4;
  fill: none;
  vector-effect: non-scaling-stroke;
  opacity: 0.95;
}

/* Rivers. Major (Columbia, Willamette) bright + thick, minor dim. */
.vec-river {
  stroke: #5df3ff;
  stroke-width: 0.5;
  fill: none;
  vector-effect: non-scaling-stroke;
  opacity: 0.45;
  stroke-linecap: round;
}
.vec-river.major {
  stroke: #b6ffff;
  stroke-width: 1.7;
  opacity: 0.95;
}

/* Highways — magenta. Motorway = bright + wide, trunk = dim. */
.vec-hwy {
  fill: none;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
}
.vec-hwy.motorway {
  stroke: #ff9ee2;
  stroke-width: 1.3;
  opacity: 0.85;
}
.vec-hwy.trunk {
  stroke: #ff5dd3;
  stroke-width: 0.55;
  opacity: 0.35;
}

/* Metro polygon — cross-hatch fill via the SVG <pattern>, plus a glowing
   magenta outline. Pulsing via opacity (GPU-only, cheap). */
.vec-metro {
  opacity: 0.85;
}
.vec-metro-outline {
  fill: none;
  stroke: #ff5dd3;
  stroke-width: 1.2;
  opacity: 0.75;
  vector-effect: non-scaling-stroke;
}

/* Animations live only on the wrapper <g> elements — one transform per layer,
   not thousands. Browser can fold these into composite layers cheaply. */
@keyframes group-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.85; }
}
.vec-hwy-g   { animation: group-pulse 5s ease-in-out infinite; }
.vec-river-g { animation: group-pulse 7s ease-in-out infinite; }

@keyframes hud-drift {
  from { transform: translate(0, 0); }
  to   { transform: translate(0.5%, 0.3%); }
}
.vec-hud-grid { animation: hud-drift 24s ease-in-out infinite alternate; }

@media (prefers-reduced-motion: reduce) {
  .vec-hwy-g, .vec-river-g, .vec-hud-grid { animation: none !important; }
}

/* Calibration mode — activated via ?cal=1 on the URL. */
.cal-toolbar {
  position: fixed;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  background: rgba(7, 9, 10, 0.96);
  border: 1px solid var(--accent-cyan);
  padding: 10px 14px;
  border-radius: 3px;
  font-size: 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: center;
  max-width: calc(100% - 20px);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.7);
}
.cal-toolbar .cal-current {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.cal-toolbar .cal-counter { color: var(--fg-dim); }
.cal-toolbar button {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg);
  font: inherit;
  font-size: 11px;
  padding: 3px 9px;
  cursor: pointer;
  border-radius: 2px;
}
.cal-toolbar button:hover { border-color: var(--accent-cyan); color: var(--fg-bright); }
.cal-toolbar button.cal-done {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}
.map-illustrated.cal-mode { cursor: crosshair; }
.map-illustrated.cal-mode .map-hotspot {
  opacity: 0.4;
  pointer-events: none;
}
.map-illustrated.cal-mode .map-hotspot.cal-active {
  opacity: 1;
  pointer-events: auto;
}
.map-illustrated.cal-mode .map-hotspot.cal-active .hotspot-dot {
  background: var(--accent-mag);
  border-color: var(--accent-mag);
  box-shadow: 0 0 14px rgba(255, 93, 211, 0.9);
  transform: scale(1.6);
}
.map-illustration {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.map-illustrated.no-image .map-illustration { display: none; }
.map-illustration-fallback {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  color: var(--fg);
  font-size: clamp(11px, 2.4vw, 14px);
  gap: 8px;
  background:
    repeating-linear-gradient(45deg,
      rgba(93, 243, 255, 0.03) 0,
      rgba(93, 243, 255, 0.03) 12px,
      transparent 12px, transparent 24px);
}
.map-illustrated.no-image .map-illustration-fallback { display: flex; }
.map-illustration-fallback code {
  background: rgba(93, 243, 255, 0.08);
  border: 1px solid rgba(93, 243, 255, 0.25);
  padding: 4px 10px;
  border-radius: 2px;
  color: var(--accent-cyan);
}
.map-illustration-fallback .dim { color: var(--fg-dim); font-style: italic; max-width: 520px; }
.hotspot-layer { position: absolute; inset: 0; }
.map-hotspot {
  position: absolute;
  transform: translate(-50%, -50%);
  background: transparent;
  border: 0;
  padding: 6px;
  cursor: pointer;
  font: inherit;
  color: var(--accent-cyan);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.map-hotspot .hotspot-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #050811;
  border: 1.6px solid var(--accent-cyan);
  box-shadow: 0 0 8px rgba(93, 243, 255, 0.5);
  transition: transform 120ms, box-shadow 120ms;
}
.map-hotspot .hotspot-label {
  font-size: clamp(9px, 1.8vw, 11px);
  font-weight: 700;
  letter-spacing: 0.05em;
  background: rgba(5, 8, 17, 0.78);
  padding: 1px 5px;
  border-radius: 2px;
  white-space: nowrap;
}
.map-hotspot:hover .hotspot-dot,
.map-hotspot:focus .hotspot-dot {
  transform: scale(1.4);
  box-shadow: 0 0 14px rgba(93, 243, 255, 0.9);
}
.map-hotspot:hover .hotspot-label,
.map-hotspot:focus .hotspot-label { color: #fff; }
.map-hotspot.danger .hotspot-dot {
  border-color: var(--accent-mag);
  box-shadow: 0 0 8px rgba(255, 93, 211, 0.5);
}
.map-hotspot.danger { color: var(--accent-mag); }

/* ─── VANPORT METRO zoom marker (overview only) ──────────────────────── */
.map-hotspot.zoom {
  /* z-index high enough to sit above the metro polygon's pattern fill. */
  z-index: 5;
}
.map-hotspot.zoom .hotspot-dot {
  width: 18px;
  height: 18px;
  border: 2.5px solid var(--accent-mag);
  background: rgba(255, 93, 211, 0.18);
  box-shadow:
    0 0 10px rgba(255, 93, 211, 0.6),
    inset 0 0 6px rgba(255, 93, 211, 0.4);
  animation: zoom-ring 2.4s ease-in-out infinite;
}
.map-hotspot.zoom .hotspot-label {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.18em;
  font-size: clamp(10px, 2.0vw, 12px);
  background: rgba(20, 5, 14, 0.85);
  border: 1px solid rgba(255, 93, 211, 0.55);
  padding: 2px 8px;
  margin-top: 3px;
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.6);
}
.map-hotspot.zoom:hover .hotspot-dot,
.map-hotspot.zoom:focus .hotspot-dot {
  transform: scale(1.25);
  background: rgba(255, 93, 211, 0.32);
}
.map-hotspot.zoom:hover .hotspot-label,
.map-hotspot.zoom:focus .hotspot-label {
  color: #fff;
  border-color: var(--accent-mag);
  background: rgba(40, 8, 28, 0.95);
}
@keyframes zoom-ring {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 93, 211, 0.55), inset 0 0 6px rgba(255, 93, 211, 0.4); }
  50%      { box-shadow: 0 0 0 14px rgba(255, 93, 211, 0),     inset 0 0 6px rgba(255, 93, 211, 0.5); }
}
@media (prefers-reduced-motion: reduce) {
  .map-hotspot.zoom .hotspot-dot { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   RUNNER CREATOR OVERLAY  —  full-screen modal, FORT VAN registry vibe.
   ═══════════════════════════════════════════════════════════════════════ */
.creator-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(20, 6, 24, 0.55) 0%, rgba(3, 5, 9, 0.92) 100%),
    repeating-linear-gradient(0deg, transparent 0, transparent 3px, rgba(0,0,0,0.18) 3.5px, transparent 4px);
  display: flex;
  align-items: stretch;
  justify-content: center;
  overflow-y: auto;
  padding: max(env(safe-area-inset-top), 16px)
          max(env(safe-area-inset-right), 16px)
          max(env(safe-area-inset-bottom), 16px)
          max(env(safe-area-inset-left), 16px);
  animation: cr-fade-in 280ms ease-out;
}
@keyframes cr-fade-in {
  from { opacity: 0; transform: scale(0.985); }
  to   { opacity: 1; transform: scale(1); }
}

.creator-frame {
  width: 100%;
  max-width: 1100px;
  margin: auto;
  background: linear-gradient(135deg, rgba(8, 11, 18, 0.92), rgba(14, 18, 28, 0.86));
  border: 1px solid var(--accent-mag);
  border-radius: 2px;
  box-shadow:
    0 0 0 1px rgba(255, 93, 211, 0.15),
    0 24px 70px rgba(0, 0, 0, 0.75),
    0 0 30px rgba(255, 93, 211, 0.18);
  padding: 24px 26px 22px;
  position: relative;
}
.creator-frame::before {
  /* corner brackets — FORT VAN registry signaling */
  content: '';
  position: absolute;
  inset: 6px;
  border: 1px solid rgba(255, 93, 211, 0.18);
  pointer-events: none;
}

.creator-head {
  text-align: center;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px dashed rgba(255, 93, 211, 0.3);
}
.creator-eyebrow {
  display: block;
  color: var(--accent-cyan);
  font-size: clamp(9px, 1.8vw, 11px);
  letter-spacing: 0.32em;
  margin-bottom: 4px;
}
.creator-title {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.16em;
  font-size: clamp(18px, 4vw, 24px);
  margin: 0;
  text-shadow: 0 0 8px rgba(255, 93, 211, 0.55), 0 0 22px rgba(255, 93, 211, 0.2);
}
.creator-subtitle {
  display: block;
  color: var(--fg-dim);
  font-size: clamp(9px, 1.8vw, 11px);
  letter-spacing: 0.18em;
  margin-top: 4px;
}

.creator-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
}
@media (max-width: 820px) {
  .creator-body { grid-template-columns: 1fr; gap: 18px; }
}

.creator-col { display: flex; flex-direction: column; gap: 16px; }

.cr-label {
  display: block;
  color: var(--accent-cyan);
  font-size: clamp(10px, 2vw, 12px);
  letter-spacing: 0.18em;
  font-weight: 700;
  margin-bottom: 7px;
}
.cr-label .cr-hint {
  color: var(--fg-dim);
  font-weight: 400;
  letter-spacing: 0.04em;
  margin-left: 8px;
  font-size: 0.88em;
  text-transform: none;
}
.cr-section { display: flex; flex-direction: column; }

/* ── handle field ── */
.cr-handle {
  background: rgba(7, 9, 14, 0.85);
  border: 1px solid var(--fg-dim);
  border-left-width: 3px;
  border-left-color: var(--accent-mag);
  color: var(--fg-bright);
  font: inherit;
  font-size: clamp(14px, 3vw, 17px);
  letter-spacing: 0.04em;
  padding: 10px 12px;
  outline: none;
  border-radius: 1px;
  text-shadow: var(--crt-glow);
}
.cr-handle::placeholder { color: var(--fg-dim); opacity: 0.5; }
.cr-handle:focus {
  border-color: var(--accent-cyan);
  border-left-color: var(--accent-mag);
  box-shadow: 0 0 0 1px rgba(93, 243, 255, 0.25);
}

/* ── class cards (4-up grid) ── */
.cr-class-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.cr-class-card {
  background: linear-gradient(135deg, rgba(7, 12, 18, 0.85), rgba(10, 16, 24, 0.65));
  border: 1px solid rgba(93, 243, 255, 0.22);
  color: var(--fg);
  font: inherit;
  text-align: left;
  padding: 9px 11px;
  cursor: pointer;
  border-radius: 1px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: border-color 120ms, background 120ms, box-shadow 120ms;
}
.cr-class-card:hover {
  border-color: var(--accent-cyan);
  background: linear-gradient(135deg, rgba(10, 22, 30, 0.9), rgba(14, 32, 42, 0.75));
}
.cr-class-card.selected {
  border-color: var(--accent-mag);
  box-shadow: 0 0 0 1px var(--accent-mag), 0 0 16px rgba(255, 93, 211, 0.3);
  background: linear-gradient(135deg, rgba(28, 8, 22, 0.85), rgba(36, 12, 28, 0.7));
}
.cr-card-name {
  color: var(--accent-cyan);
  font-weight: 700;
  letter-spacing: 0.1em;
  font-size: clamp(11px, 2.2vw, 13px);
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.35);
}
.cr-class-card.selected .cr-card-name {
  color: var(--accent-mag);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.55);
}
.cr-card-blurb {
  color: var(--fg-dim);
  font-size: clamp(9.5px, 2vw, 11px);
  line-height: 1.4;
}

/* ── origin cards (3-col grid, smaller) ── */
.cr-origin-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 6px;
}
@media (max-width: 540px) {
  .cr-origin-grid { grid-template-columns: 1fr 1fr; }
}
.cr-origin-card {
  background: rgba(7, 12, 18, 0.7);
  border: 1px solid rgba(93, 243, 255, 0.18);
  color: var(--fg);
  font: inherit;
  text-align: left;
  padding: 7px 9px;
  cursor: pointer;
  border-radius: 1px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: border-color 120ms, background 120ms;
  min-height: 56px;
}
.cr-origin-card:hover {
  border-color: var(--accent-cyan);
  background: rgba(10, 22, 30, 0.85);
}
.cr-origin-card.selected {
  border-color: var(--accent-mag);
  background: rgba(28, 8, 22, 0.85);
  box-shadow: 0 0 0 1px var(--accent-mag);
}
.cr-origin-card .cr-card-name {
  font-size: clamp(10px, 2vw, 12px);
  letter-spacing: 0.06em;
}
.cr-card-bonus {
  color: var(--accent-amber);
  font-size: clamp(8.5px, 1.7vw, 10px);
  font-style: italic;
  opacity: 0.85;
}
.cr-origin-blurb {
  color: var(--fg-bright);
  font-style: italic;
  font-size: clamp(10px, 2vw, 12px);
  line-height: 1.55;
  margin: 8px 2px 0;
  padding: 8px 12px;
  border-left: 2px solid var(--accent-mag);
  background: rgba(20, 6, 16, 0.4);
}

/* ── stats / point-buy ── */
.cr-stats-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
}
.cr-budget {
  font-size: clamp(11px, 2.2vw, 13px);
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 2px 9px;
  border-radius: 1px;
  border: 1px solid;
}
.cr-budget.under { color: var(--accent-amber); border-color: rgba(255, 184, 107, 0.6); background: rgba(60, 40, 12, 0.3); }
.cr-budget.exact { color: var(--fg-bright);    border-color: var(--fg);                 background: rgba(20, 50, 28, 0.4); }
.cr-budget.over  { color: var(--danger);       border-color: var(--danger);             background: rgba(60, 12, 22, 0.4); }

.cr-stats {
  background: rgba(7, 9, 14, 0.5);
  border: 1px solid rgba(93, 243, 255, 0.15);
  padding: 10px 12px;
  border-radius: 1px;
}
.cr-stat-row {
  display: grid;
  grid-template-columns: 44px 28px 44px 28px 36px 1fr;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  border-bottom: 1px dashed rgba(93, 243, 255, 0.08);
  font-size: clamp(11px, 2.2vw, 13px);
}
.cr-stat-row:last-child { border-bottom: 0; }
.cr-stat-name {
  color: var(--accent-cyan);
  font-weight: 700;
  letter-spacing: 0.06em;
}
.cr-stat-btn {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg);
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  width: 26px;
  height: 26px;
  cursor: pointer;
  border-radius: 1px;
  padding: 0;
  line-height: 1;
}
.cr-stat-btn:hover:not(:disabled) {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}
.cr-stat-btn:disabled {
  opacity: 0.3;
  cursor: default;
}
.cr-stat-val {
  text-align: center;
  font-weight: 700;
  color: var(--fg-bright);
  font-size: clamp(13px, 2.6vw, 15px);
  position: relative;
}
.cr-stat-bonus {
  color: var(--accent-mag);
  font-size: 0.6em;
  vertical-align: super;
  margin-left: 1px;
  font-weight: 700;
}
.cr-stat-mod {
  color: var(--fg-dim);
  font-size: 0.92em;
  text-align: right;
}
.cr-stat-bar {
  color: var(--accent-cyan);
  font-size: 0.85em;
  letter-spacing: -1px;
  opacity: 0.75;
  white-space: nowrap;
  overflow: hidden;
}

.cr-stats-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 6px;
}
.cr-stat-reset, .cr-stat-roll {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg-dim);
  font: inherit;
  font-size: clamp(9.5px, 1.9vw, 11px);
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 1px;
  letter-spacing: 0.06em;
}
.cr-stat-reset:hover, .cr-stat-roll:hover {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}

/* ── preview pane ── */
.cr-preview {
  background: rgba(7, 9, 14, 0.55);
  border: 1px solid rgba(93, 243, 255, 0.18);
  padding: 12px 14px;
  border-radius: 1px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cr-preview-head {
  color: var(--fg-bright);
  font-style: italic;
  font-size: clamp(10.5px, 2.2vw, 12.5px);
  line-height: 1.45;
  padding-bottom: 8px;
  border-bottom: 1px dashed rgba(93, 243, 255, 0.18);
}
.cr-preview-stats {
  display: flex;
  gap: 18px;
  font-size: clamp(11px, 2.2vw, 13px);
}
.cr-preview-stats b { color: var(--accent-cyan); font-weight: 700; letter-spacing: 0.08em; margin-right: 4px; }
.cr-preview-block { display: flex; flex-direction: column; gap: 4px; }
.cr-preview-label {
  color: var(--accent-cyan);
  font-size: clamp(9px, 1.8vw, 11px);
  letter-spacing: 0.2em;
  font-weight: 700;
}
.cr-preview-list {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: clamp(10px, 2vw, 12px);
  line-height: 1.55;
  color: var(--fg);
}
.cr-preview-list .dim { color: var(--fg-dim); font-style: italic; }
.cr-preview-origin { border-top: 1px dashed rgba(255, 93, 211, 0.25); padding-top: 8px; }
.cr-preview-contact {
  color: var(--accent-mag);
  font-style: italic;
  font-size: clamp(10px, 2vw, 12px);
  margin: 0;
  padding-left: 8px;
  border-left: 2px solid var(--accent-mag);
}

/* ── footer / CTA ── */
.creator-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed rgba(93, 243, 255, 0.22);
  flex-wrap: wrap;
}
.cr-cancel {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg-dim);
  font: inherit;
  font-size: clamp(10px, 2vw, 12px);
  padding: 8px 14px;
  cursor: pointer;
  letter-spacing: 0.08em;
  border-radius: 1px;
}
.cr-cancel:hover { color: var(--fg); border-color: var(--fg); }
.cr-spacer { flex: 1; }
.cr-error {
  color: var(--danger);
  font-size: clamp(10px, 2vw, 12px);
  font-style: italic;
  flex: 1;
  text-align: center;
}
.cr-begin {
  background: rgba(255, 93, 211, 0.12);
  border: 1px solid var(--accent-mag);
  color: var(--accent-mag);
  font: inherit;
  font-size: clamp(12px, 2.6vw, 15px);
  font-weight: 700;
  letter-spacing: 0.18em;
  padding: 10px 22px;
  cursor: pointer;
  border-radius: 1px;
  text-shadow: 0 0 5px rgba(255, 93, 211, 0.6);
  box-shadow: 0 0 0 1px rgba(255, 93, 211, 0.25), 0 0 18px rgba(255, 93, 211, 0.2);
  transition: color 140ms, background 140ms, box-shadow 140ms;
}
.cr-begin:hover:not(:disabled) {
  color: #fff;
  background: rgba(255, 93, 211, 0.22);
  box-shadow: 0 0 0 1px var(--accent-mag), 0 0 26px rgba(255, 93, 211, 0.45);
}
.cr-begin:disabled {
  opacity: 0.35;
  cursor: default;
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .creator-overlay { animation: none; }
}

/* ── connect overlay (re-uses .creator-overlay + .creator-frame) ── */
.connect-frame { max-width: 600px; }
.connect-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 6px 0;
}
.connect-explain {
  color: var(--fg-dim);
  font-size: clamp(11px, 2.2vw, 13px);
  line-height: 1.55;
  margin: 0;
}
.connect-explain code {
  color: var(--accent-cyan);
  background: rgba(93, 243, 255, 0.08);
  border: 1px solid rgba(93, 243, 255, 0.25);
  padding: 1px 5px;
  border-radius: 1px;
  font-size: 0.9em;
}
.connect-token {
  letter-spacing: 0.04em;
  font-family: "JetBrains Mono", "Fira Code", "Courier New", ui-monospace, monospace;
}
.connect-advanced-toggle {
  background: transparent;
  border: 0;
  color: var(--fg-dim);
  font: inherit;
  font-size: clamp(10px, 2vw, 12px);
  padding: 4px 0;
  margin-top: 2px;
  cursor: pointer;
  text-align: left;
  letter-spacing: 0.06em;
  align-self: flex-start;
}
.connect-advanced-toggle:hover { color: var(--accent-cyan); }
.connect-hint {
  color: var(--fg-dim);
  font-size: clamp(9.5px, 1.9vw, 11px);
  font-style: italic;
  margin-top: -4px;
}
.connect-status {
  margin-top: 8px;
  padding: 8px 12px;
  border-radius: 1px;
  font-size: clamp(11px, 2.2vw, 13px);
  letter-spacing: 0.04em;
}
.connect-status.pinging {
  color: var(--accent-cyan);
  border: 1px solid rgba(93, 243, 255, 0.4);
  background: rgba(8, 18, 28, 0.6);
}
.connect-status.error {
  color: var(--danger);
  border: 1px solid var(--danger);
  background: rgba(40, 8, 18, 0.5);
}

/* ─── "← Cascadia" back button on the Vanport zoomed view ─────────────── */
.map-back {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 6;
  background: rgba(7, 9, 10, 0.88);
  border: 1px solid var(--accent-cyan);
  color: var(--accent-cyan);
  font: inherit;
  font-size: clamp(10px, 2.2vw, 12px);
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 4px 11px;
  cursor: pointer;
  border-radius: 2px;
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.5);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  transition: color 120ms, border-color 120ms, background 120ms;
}
.map-back:hover, .map-back:focus {
  color: var(--fg-bright);
  border-color: var(--fg-bright);
  background: rgba(7, 30, 30, 0.95);
  outline: 0;
}

/* ── custom-origin block (creator overlay) ────────────────────────────── */
.cr-origin-custom {
  border-style: dashed !important;
  border-color: rgba(255, 93, 211, 0.35) !important;
  background: rgba(28, 8, 22, 0.45) !important;
}
.cr-origin-custom:hover {
  border-color: var(--accent-mag) !important;
}
.cr-origin-custom.selected {
  border-style: solid !important;
  background: rgba(28, 8, 22, 0.85) !important;
}
.cr-custom-block {
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--accent-mag);
  border-left-width: 3px;
  background: rgba(20, 6, 24, 0.45);
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cr-custom-label {
  color: var(--accent-cyan);
  font-size: clamp(10px, 2vw, 12px);
  letter-spacing: 0.14em;
  font-weight: 700;
}
.cr-custom-text {
  background: rgba(7, 9, 14, 0.9);
  border: 1px solid var(--fg-dim);
  border-left-width: 3px;
  border-left-color: var(--accent-mag);
  color: var(--fg-bright);
  font: inherit;
  font-size: clamp(12px, 2.4vw, 14px);
  line-height: 1.55;
  padding: 10px 12px;
  border-radius: 1px;
  resize: vertical;
  min-height: 110px;
  outline: none;
  text-shadow: var(--crt-glow);
}
.cr-custom-text:focus {
  border-color: var(--accent-cyan);
  border-left-color: var(--accent-mag);
  box-shadow: 0 0 0 1px rgba(93, 243, 255, 0.25);
}
.cr-custom-text::placeholder { color: var(--fg-dim); opacity: 0.55; line-height: 1.5; }
.cr-custom-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cr-custom-count {
  color: var(--fg-dim);
  font-size: clamp(10px, 1.9vw, 11px);
  letter-spacing: 0.04em;
}
.cr-custom-count.dim { opacity: 0.6; }
.cr-custom-interpret,
.cr-custom-reroll {
  background: rgba(7, 9, 14, 0.85);
  border: 1px solid var(--accent-cyan);
  color: var(--accent-cyan);
  font: inherit;
  font-size: clamp(11px, 2.2vw, 13px);
  font-weight: 700;
  letter-spacing: 0.14em;
  padding: 6px 14px;
  cursor: pointer;
  border-radius: 1px;
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.5);
  transition: color 120ms, border-color 120ms, background 120ms;
}
.cr-custom-interpret:hover:not(:disabled),
.cr-custom-reroll:hover {
  color: var(--fg-bright);
  border-color: var(--fg-bright);
  background: rgba(7, 30, 30, 0.95);
}
.cr-custom-interpret:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.cr-custom-error {
  color: var(--danger);
  font-size: clamp(10px, 2vw, 12px);
  border: 1px solid var(--danger);
  border-radius: 1px;
  padding: 6px 10px;
  background: rgba(40, 8, 18, 0.4);
}

/* ── interpreted result card ── */
.cr-custom-result {
  margin-top: 10px;
  padding: 14px;
  border: 1px solid var(--accent-mag);
  border-left-width: 4px;
  background: linear-gradient(135deg, rgba(28, 8, 22, 0.7), rgba(14, 18, 28, 0.85));
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  animation: cr-fade-in 280ms ease-out;
}
.cr-custom-result-name {
  color: var(--accent-mag);
  font-weight: 700;
  letter-spacing: 0.14em;
  font-size: clamp(13px, 2.6vw, 15px);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.5);
}
.cr-custom-result-blurb {
  color: var(--fg-bright);
  font-size: clamp(11px, 2.2vw, 13px);
  line-height: 1.55;
  margin: 0;
}
.cr-custom-result-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
@media (max-width: 540px) {
  .cr-custom-result-grid { grid-template-columns: 1fr; }
}
.cr-custom-bonus,
.cr-custom-penalty {
  padding: 8px 10px;
  border: 1px solid var(--fg-dim);
  border-radius: 1px;
  background: rgba(7, 9, 14, 0.55);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.cr-custom-bonus  { border-left: 3px solid var(--accent-cyan); }
.cr-custom-penalty{ border-left: 3px solid var(--danger); }
.cr-custom-stat {
  font-weight: 700;
  font-size: clamp(11px, 2.2vw, 13px);
  letter-spacing: 0.1em;
}
.cr-custom-stat.plus  { color: var(--accent-cyan); text-shadow: 0 0 5px rgba(93, 243, 255, 0.5); }
.cr-custom-stat.minus { color: var(--danger);      text-shadow: 0 0 5px rgba(255, 77, 109, 0.5); }
.cr-custom-reason {
  color: var(--fg-dim);
  font-size: clamp(10px, 2vw, 12px);
  line-height: 1.45;
}
.cr-custom-contact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 0;
  border-top: 1px dashed rgba(255, 93, 211, 0.3);
}
.cr-custom-contact-label {
  color: var(--accent-cyan);
  font-size: clamp(9.5px, 1.9vw, 11px);
  letter-spacing: 0.18em;
  font-weight: 700;
}
.cr-custom-contact > span:last-child {
  color: var(--fg);
  font-size: clamp(11px, 2.2vw, 13px);
  line-height: 1.45;
}

/* ── retry card (shown when a turn fails) ────────────────────────────── */
.retry-card {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0;
  padding: 10px 14px;
  border: 1px solid var(--danger);
  border-left-width: 4px;
  border-radius: 2px;
  background: rgba(40, 8, 18, 0.5);
  animation: card-pulse-bad 600ms ease-out;
}
.retry-msg {
  color: var(--danger);
  font-size: clamp(11px, 2.2vw, 13px);
  letter-spacing: 0.04em;
  flex: 1;
}
.retry-btn {
  background: rgba(7, 9, 14, 0.85);
  border: 1px solid var(--accent-cyan);
  color: var(--accent-cyan);
  font: inherit;
  font-size: clamp(11px, 2.2vw, 13px);
  font-weight: 700;
  letter-spacing: 0.14em;
  padding: 6px 14px;
  cursor: pointer;
  border-radius: 1px;
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.5);
  transition: color 120ms, border-color 120ms, background 120ms;
}
.retry-btn:hover, .retry-btn:focus {
  color: var(--fg-bright);
  border-color: var(--fg-bright);
  background: rgba(7, 30, 30, 0.95);
  outline: 0;
}

/* ── narrator settings overlay (reuses .creator-overlay + .creator-frame) ── */
.voice-frame { max-width: 520px; }
.voice-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 0 8px;
}
.voice-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.voice-toggle {
  background: rgba(7, 9, 14, 0.85);
  border: 1px solid var(--fg-dim);
  border-left-width: 3px;
  color: var(--fg-bright);
  font: inherit;
  font-size: clamp(12px, 2.6vw, 14px);
  font-weight: 700;
  letter-spacing: 0.14em;
  padding: 6px 14px;
  cursor: pointer;
  border-radius: 1px;
  text-shadow: var(--crt-glow);
  transition: color 120ms, border-color 120ms, background 120ms;
}
.voice-toggle.on  { border-left-color: var(--accent-cyan); color: var(--accent-cyan); }
.voice-toggle.off { border-left-color: var(--fg-dim);      color: var(--fg-dim);      }
.voice-toggle:hover { color: var(--fg-bright); border-color: var(--accent-cyan); }
.voice-select {
  font-size: clamp(12px, 2.6vw, 14px);
  padding: 8px 10px;
  cursor: pointer;
}
.voice-select option { background: rgba(7, 9, 14, 1); color: var(--fg-bright); }
.voice-provider-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: -4px;
}
.voice-prov-btn {
  background: rgba(7, 12, 18, 0.7);
  border: 1px solid rgba(93, 243, 255, 0.18);
  color: var(--fg);
  font: inherit;
  text-align: left;
  padding: 8px 10px;
  cursor: pointer;
  border-radius: 1px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  transition: border-color 120ms, background 120ms;
}
.voice-prov-btn:hover {
  border-color: var(--accent-cyan);
  background: rgba(10, 22, 30, 0.85);
}
.voice-prov-btn.selected {
  border-color: var(--accent-mag);
  background: rgba(28, 8, 22, 0.85);
  box-shadow: 0 0 0 1px var(--accent-mag);
}
.vp-name {
  color: var(--accent-cyan);
  font-weight: 700;
  letter-spacing: 0.1em;
  font-size: clamp(11px, 2.2vw, 13px);
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.35);
}
.voice-prov-btn.selected .vp-name {
  color: var(--accent-mag);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.55);
}
.vp-sub {
  color: var(--fg-dim);
  font-size: clamp(9.5px, 1.9vw, 11px);
  letter-spacing: 0.02em;
}
.voice-cloud-blurb {
  font-size: clamp(10px, 2vw, 12px);
  margin-top: -4px;
  font-style: italic;
  padding: 4px 0;
}
.voice-showall {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--fg-dim);
  font-size: clamp(10px, 2vw, 12px);
  letter-spacing: 0.04em;
  cursor: pointer;
  margin-top: -4px;
}
.voice-showall input { accent-color: var(--accent-cyan); }
.voice-slider-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: clamp(10px, 2vw, 11px);
}
.voice-rate {
  flex: 1;
  accent-color: var(--accent-mag);
  height: 22px;
  cursor: pointer;
}
.voice-hint {
  font-size: clamp(10px, 2vw, 12px);
  line-height: 1.5;
  letter-spacing: 0.02em;
  padding: 8px 10px;
  border-left: 2px solid rgba(93, 243, 255, 0.35);
  background: rgba(8, 18, 28, 0.4);
  border-radius: 1px;
}
.voice-sample {
  letter-spacing: 0.12em;
}
.voice-close {
  /* DONE button — use cyan to distinguish from the magenta primary action */
  border-left-color: var(--accent-cyan) !important;
}

/* ── cheats overlay (reuses .creator-overlay + .creator-frame + .voice-toggle) ── */
.cheat-frame { max-width: 560px; }
.cheat-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 6px 0 10px;
}
.cheat-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 12px;
  background: rgba(7, 12, 18, 0.5);
  border: 1px solid rgba(93, 243, 255, 0.12);
  border-left-width: 3px;
  border-left-color: var(--fg-dim);
  border-radius: 1px;
  transition: border-color 120ms, background 120ms;
}
.cheat-row.on {
  border-left-color: var(--accent-mag);
  background: rgba(28, 8, 22, 0.55);
}
.cheat-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cheat-name {
  color: var(--accent-cyan);
  font-weight: 700;
  letter-spacing: 0.12em;
  font-size: clamp(12px, 2.4vw, 14px);
  text-shadow: 0 0 5px rgba(93, 243, 255, 0.35);
}
.cheat-row.on .cheat-name {
  color: var(--accent-mag);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.55);
}
.cheat-blurb {
  color: var(--fg-dim);
  font-size: clamp(10px, 2vw, 12px);
  letter-spacing: 0.02em;
}
.cheat-foot { gap: 8px; flex-wrap: wrap; }
.cheat-all {
  border-left-color: var(--accent-amber) !important;
  color: var(--accent-amber) !important;
}
.cheat-all:disabled { opacity: 0.35; cursor: not-allowed; }
.cheat-close {
  border-left-color: var(--accent-cyan) !important;
}

/* ── narrator highlighting ────────────────────────────────────────────── */
/* Clickable: the cursor hint tells the player they can resume from here. */
.narrative .narrative-line {
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
  border-left: 2px solid transparent;
  padding-left: 6px;
  margin-left: -8px;     /* keep visual alignment when the border appears */
}
.narrative .narrative-line:hover {
  background: rgba(93, 243, 255, 0.04);
  border-left-color: rgba(93, 243, 255, 0.25);
}
/* Active paragraph the narrator is reading right now. */
.narrative .narrative-line.speaking {
  background: linear-gradient(90deg,
    rgba(93, 243, 255, 0.10) 0%,
    rgba(93, 243, 255, 0.04) 60%,
    transparent 100%);
  border-left-color: var(--accent-cyan);
  box-shadow: inset 0 0 18px rgba(93, 243, 255, 0.10);
}
/* The current word being spoken — karaoke style. */
.narrative .narrative-line mark.tts-word {
  background: rgba(93, 243, 255, 0.22);
  color: var(--fg-bright);
  text-shadow: 0 0 6px rgba(93, 243, 255, 0.7);
  padding: 0 1px;
  border-radius: 2px;
  /* Avoid the default yellow background browsers give <mark> */
}
@media (prefers-reduced-motion: reduce) {
  .narrative .narrative-line { transition: none; }
}

/* ─────────────────────────── Story Time mode ───────────────────────────
   Hands-free read-along. Hides chrome, swells the prose, swaps the text
   input for a big mic button at the bottom of the viewport. */

/* `.on` indicator for the title button */
.title-btn.on {
  color: var(--accent-mag);
  border-color: var(--accent-mag);
  text-shadow: 0 0 6px rgba(255, 93, 211, 0.55);
  background: rgba(28, 8, 22, 0.5);
}

body.storytime .stats-strip,
body.storytime .game-prompt,
body.storytime #map-button,
body.storytime #burger {
  display: none !important;
}

/* Theatrical prose: bigger, calmer, dim the past, glow the present. */
body.storytime .narrative {
  padding: 32px clamp(16px, 4vw, 48px) 220px;
  font-size: clamp(16px, 3.4vw, 22px);
  line-height: 1.85;
}
body.storytime .narrative .line {
  max-width: 60ch;
  margin-left: auto;
  margin-right: auto;
}
body.storytime .narrative .narrative-line {
  color: var(--fg-dim);
  transition: color 350ms ease, opacity 350ms ease;
  opacity: 0.55;
}
body.storytime .narrative .narrative-line.speaking {
  color: var(--fg-bright);
  opacity: 1;
  text-shadow: 0 0 8px rgba(182, 255, 196, 0.25);
}

/* Mic button cluster, pinned bottom-center. */
.storytime-mic-wrap {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 16px calc(20px + env(safe-area-inset-bottom));
  background: linear-gradient(
    to top,
    rgba(7, 9, 10, 0.96) 0%,
    rgba(7, 9, 10, 0.85) 60%,
    rgba(7, 9, 10, 0) 100%
  );
  pointer-events: none;
  z-index: 30;
}
/* `display: flex` above overrides the browser's UA `[hidden] { display: none }`
   rule, so without this guard the mic + exit button stay on screen even when
   Story Time is off and the user can't tell they're not in the mode. */
.storytime-mic-wrap[hidden] { display: none !important; }
.storytime-mic-wrap > * { pointer-events: auto; }

.storytime-transcript {
  max-width: min(620px, 90vw);
  min-height: 0;
  padding: 0;
  font-size: clamp(13px, 2.6vw, 15px);
  line-height: 1.5;
  color: var(--fg-bright);
  text-shadow: 0 0 6px rgba(182, 255, 196, 0.3);
  text-align: center;
  opacity: 0;
  transition: opacity 200ms;
  letter-spacing: 0.01em;
}
.storytime-transcript.visible {
  opacity: 1;
  padding: 10px 14px;
  background: rgba(7, 18, 12, 0.85);
  border: 1px solid var(--fg-dim);
  border-radius: 4px;
}
.storytime-transcript.err {
  color: var(--danger);
  border-color: var(--danger);
  text-shadow: 0 0 6px rgba(255, 77, 109, 0.5);
}

.storytime-mic {
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: rgba(7, 18, 12, 0.95);
  border: 2px solid var(--fg);
  color: var(--fg-bright);
  font: inherit;
  font-weight: 700;
  letter-spacing: 0.12em;
  font-size: 10px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  box-shadow:
    0 0 0 1px rgba(93, 255, 124, 0.15),
    0 0 24px rgba(93, 255, 124, 0.18),
    inset 0 0 16px rgba(0, 0, 0, 0.6);
  transition: transform 120ms, border-color 120ms, box-shadow 200ms, background 120ms;
}
.storytime-mic:hover { transform: scale(1.03); }
.storytime-mic:active { transform: scale(0.97); }
.storytime-mic:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  transform: none;
}
.storytime-mic-glyph { font-size: 28px; line-height: 1; }
.storytime-mic-label {
  font-size: 9px;
  letter-spacing: 0.16em;
  white-space: nowrap;
}
.storytime-mic.listening {
  border-color: var(--accent-mag);
  background: rgba(28, 8, 22, 0.95);
  color: var(--accent-mag);
  animation: st-pulse 1.2s ease-in-out infinite;
}
@keyframes st-pulse {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(255, 93, 211, 0.25),
      0 0 24px rgba(255, 93, 211, 0.35),
      inset 0 0 16px rgba(0, 0, 0, 0.6);
  }
  50% {
    box-shadow:
      0 0 0 6px rgba(255, 93, 211, 0.12),
      0 0 36px rgba(255, 93, 211, 0.55),
      inset 0 0 16px rgba(0, 0, 0, 0.6);
  }
}

.storytime-exit {
  background: transparent;
  border: 1px solid var(--fg-dim);
  color: var(--fg-dim);
  font: inherit;
  font-size: 10px;
  letter-spacing: 0.14em;
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 2px;
  margin-top: 2px;
}
.storytime-exit:hover { color: var(--fg-bright); border-color: var(--fg); }

@media (prefers-reduced-motion: reduce) {
  .storytime-mic.listening { animation: none; }
  body.storytime .narrative .narrative-line { transition: none; }
}

