/* Bundled fonts (latin subset) so the game looks right with no
   internet connection — important for the iOS app. */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(assets/fonts/fraunces-var.woff2) format('woff2');
}
/* Pixel fonts for the LCD play screen (bundled, not CDN — offline rule). */
@font-face {
  font-family: 'Silkscreen';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url(assets/fonts/silkscreen-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Silkscreen';
  font-style: normal; font-weight: 700; font-display: swap;
  src: url(assets/fonts/silkscreen-700.woff2) format('woff2');
}
@font-face {
  font-family: 'VT323';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url(assets/fonts/vt323-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(assets/fonts/manrope-var.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/ibmplexmono-300.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/ibmplexmono-400.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/ibmplexmono-500.woff2) format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(assets/fonts/ibmplexmono-600.woff2) format('woff2');
}

:root {
  color-scheme: dark;
  font-family: 'Manrope', ui-sans-serif, system-ui, sans-serif;

  /* Core palette — deep forest night */
  --bg:          #151a14;
  --bg-2:        #1c2219;
  --bg-3:        #222920;
  --bg-4:        #293027;
  --surface:     #1e251c;
  --surface-2:   #242c22;
  --ink:         #e8e4d8;
  --ink-1:       var(--ink);   /* alias — referenced by several rules */
  --ink-2:       #c4bfb0;
  --ink-3:       #8a8578;
  --ink-4:       #5c5850;
  --line:        rgba(255,255,255,0.07);
  --line-2:      rgba(255,255,255,0.04);

  /* Board */
  --light:       #d4c9a8;
  --dark:        #4a6040;
  --board-frame: #1a2018;

  /* Accents */
  --gold:        #c8a84b;
  --accent:      var(--gold); /* alias — cprompt focus/ok reference it */
  --gold-dim:    #8f7635;
  --gold-glow:   rgba(200,168,75,0.15);
  --amber:       #d4884a;
  --moss:        #5a7a4a;
  --copper:      #a05c3a;

  /* Interactive */
  --active:      #c8a84b;
  --move:        rgba(90,122,74,0.75);
  --capture:     rgba(160,92,58,0.85);

  /* Shadows */
  --shadow-sm:   0 1px 3px rgba(0,0,0,0.5);
  --shadow-md:   0 4px 16px rgba(0,0,0,0.4);
  --shadow-lg:   0 16px 48px rgba(0,0,0,0.55);

  --radius:      10px;
  --radius-sm:   6px;
}

* { box-sizing: border-box; -webkit-font-smoothing: antialiased; }

/* touch-action: manipulation removes the 300ms double-tap-zoom gesture on
   every element — rapid taps (review arrows, squares) stay just taps. */
html { touch-action: manipulation; }

body {
  margin: 0;
  min-height: 100vh;
  /* Prevent iOS Safari bounce/overscroll interfering with drag */
  overscroll-behavior: none;
  /* Game UI: no long-press text selection or callout menus anywhere... */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  background: var(--bg);
  color: var(--ink);
  background-image:
    radial-gradient(ellipse 120% 60% at 50% -10%, rgba(90,122,74,0.07) 0%, transparent 60%);
}

/* ...but text fields must stay selectable/editable (preset naming). */
input, textarea {
  -webkit-user-select: text;
  user-select: text;
}

/* ── Typography ── */
.display {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 300;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

.mono {
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 400;
}

.label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ── Buttons ── */
button {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-3);
  color: var(--ink-2);
  cursor: pointer;
  font-family: 'Manrope', sans-serif;
  font-size: 0.8rem;
  font-weight: 500;
  min-height: 36px;
  padding: 7px 14px;
  transition: all 130ms ease;
  letter-spacing: 0.02em;
}

button:hover:not(:disabled) {
  background: var(--bg-4);
  border-color: rgba(255,255,255,0.12);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

button:active:not(:disabled) { transform: translateY(1px); }

button.primary {
  background: transparent;
  border-color: var(--gold);
  color: var(--gold);
  font-weight: 600;
  letter-spacing: 0.06em;
}

button.primary:hover:not(:disabled) {
  background: var(--gold-glow);
  border-color: var(--gold);
  color: var(--gold);
  box-shadow: 0 0 20px var(--gold-glow), var(--shadow-sm);
}

button:disabled { opacity: 0.3; cursor: not-allowed; }

/* ── App shell ── */
.app {
  width: min(1200px, 100%);
  margin: 0 auto;
  padding: 20px;
  /* Respect iPhone notch / Dynamic Island / home indicator */
  padding-top: max(20px, env(safe-area-inset-top));
  padding-left: max(20px, env(safe-area-inset-left));
  padding-right: max(20px, env(safe-area-inset-right));
  padding-bottom: max(20px, env(safe-area-inset-bottom));
}

/* ── Header ── */
header {
  margin-bottom: 14px;
}
/* Full centered header — config / home screen */
/* Compact header — deployment / play / reveal */
header.header-compact {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  margin-bottom: 12px;
}


h1 {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--ink);
  line-height: 1;
}
header.header-compact h1 {
  font-size: 1.25rem;
  letter-spacing: -0.02em;
}

/* Decorative crown divider between title and subtitle */
.divider-line {
  flex: 1;
  height: 1px;
  background: var(--gold-dim);
  opacity: 0.7;
}

.header-meta {
  display: flex;
  align-items: center;
}


.header-meta .turn-pill {
  font-size: 0.7rem;
  padding: 6px 14px;
}

/* ── Layout ── */
.layout {
  display: grid;
  grid-template-columns: minmax(300px, 660px) minmax(270px, 1fr);
  gap: 18px;
  align-items: start;
}

/* ── Board ── */
.board-shell {
  width: min(100%, 660px);
  padding: 10px;
  background: var(--board-frame);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  border: 1px solid rgba(255,255,255,0.04);
}

.board {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  aspect-ratio: 1;
  border: 1px solid rgba(255,255,255,0.06);
}

.square {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0; min-height: 0;
  aspect-ratio: 1;
  border: 0; border-radius: 0;
  padding: 0;
  font-size: clamp(1.75rem, 7.5vw, 4.4rem);
  line-height: 1;
  cursor: pointer;
  transition: filter 80ms ease;
}

.light { background: var(--light); }
.dark  { background: var(--dark); }

.square.out-zone { filter: brightness(0.55) saturate(0.5); }

/* Positive affordance for legal deployment ranks during setup. */
.square.deploy-zone::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--gold);
  opacity: 0.08;
  pointer-events: none;
}
.square.deploy-zone:hover::before { opacity: 0.16; }

/* King in check: pulsing red ring + glow. */
@keyframes checkPulse {
  0%, 100% { box-shadow: inset 0 0 0 4px rgba(200,70,55,0.85), 0 0 0 0 rgba(200,70,55,0); }
  50%      { box-shadow: inset 0 0 0 4px rgba(220,90,70,1), 0 0 14px 2px rgba(200,70,55,0.55); }
}
.square.in-check {
  animation: checkPulse 1.1s ease-in-out infinite;
  z-index: 2;
}

.square.selected {
  outline: 3px solid var(--gold);
  outline-offset: -3px;
  background-blend-mode: overlay;
}

.square.drag-origin .piece { opacity: 0.28; }

.square.last-from { box-shadow: inset 0 0 0 3px rgba(200,168,75,0.35); }
.square.last-to   { box-shadow: inset 0 0 0 4px rgba(200,168,75,0.65); }

.square.legal::after {
  content: "";
  width: 28%;
  height: 28%;
  border-radius: 50%;
  background: rgba(90,122,74,0.8);
  box-shadow: 0 0 8px rgba(90,122,74,0.5);
}

.square.capture::after {
  content: "";
  position: absolute;
  width: 82%;
  height: 82%;
  border: 3px solid rgba(160,92,58,0.9);
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(160,92,58,0.4);
}

/* Coordinate frame: rank gutter on the left, file gutter underneath. */
.board-frame {
  display: grid;
  grid-template-columns: 18px 1fr;
  grid-template-rows: 1fr 18px;
  gap: 4px;
}

.board { grid-column: 2; grid-row: 1; }

.rank-gutter {
  grid-column: 1; grid-row: 1;
  display: grid;
  grid-template-rows: repeat(8, 1fr);
}

.file-gutter {
  grid-column: 2; grid-row: 2;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
}

.coord {
  display: grid;
  place-items: center;
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(0.55rem, 1.1vw, 0.72rem);
  font-weight: 500;
  color: var(--ink-4);
  letter-spacing: 0.02em;
}

.tray-piece {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
}

.drag-ghost {
  position: fixed;
  z-index: 1000;
  width: 72px; height: 72px;
  pointer-events: none;
  transform: translate(-50%, -50%);
  opacity: 0.9;
  filter: drop-shadow(0 8px 20px rgba(0,0,0,0.6));
}
/* LCD drag ghost: carry the LCD palette (the piece styles live outside
   .lcd-screen but reference these vars) and size the pixel piece. */
.drag-ghost-lcd {
  --lcd-bg: #a6b58c; --lcd-ink: #20271a;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.5));
  display: flex; align-items: center; justify-content: center;
}
.drag-ghost-lcd .lcd-pc { width: 100%; height: 100%; }

/* ── Panels ── */
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: var(--shadow-md);
}

.panel + .panel { margin-top: 10px; }

.panel h2 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin: 0 0 12px;
}

/* ── Tray (piece picker) ── */
.tray {
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 6px;
}

.tray button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-height: 52px;
  padding: 8px 10px;
  background: var(--bg-3);
  border-color: var(--line);
  font-size: 0.78rem;
}

.tray button strong {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  color: var(--ink-3);
  font-weight: 500;
  min-width: 12px;
  text-align: right;
}

.tray .symbol { font-size: 1.6rem; line-height: 1; }

.tray button.active {
  background: var(--gold-glow);
  border-color: var(--gold-dim);
  color: var(--gold);
}
/* ── Segmented control ── */
.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: -0.16em;
}


.icon svg { display: block; }

/* Buttons that carry an icon + label */
button .icon { margin-right: 6px; }
.screen-icon .icon { font-size: 1.4rem; color: var(--gold); }

.small {
  font-size: 0.88rem;
  color: var(--ink-3);
  line-height: 1.55;
  margin: 8px 0 0;
}


.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

/* ── Progress bar ── */
.progress-track {
  height: 3px;
  background: var(--line);
  border-radius: 99px;
  margin-bottom: 12px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  border-radius: 99px;
  background: var(--gold);
  transition: width 300ms ease;
}

.progress-fill.complete { background: var(--moss); }

/* ── Turn pill ── */
.turn-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.turn-pill {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 3px;
  white-space: nowrap;
  border: 1px solid transparent;
}

.turn-pill.white {
  background: rgba(232,228,216,0.08);
  border-color: rgba(232,228,216,0.18);
  color: var(--ink-2);
}

.turn-pill.black {
  background: rgba(30,37,28,0.8);
  border-color: rgba(255,255,255,0.08);
  color: var(--ink-3);
}

.turn-pill.game-over {
  background: rgba(160,92,58,0.15);
  border-color: rgba(160,92,58,0.4);
  color: var(--amber);
}

/* ── Full-page screens (pass / reveal) ── */

.pass-screen,
.reveal-screen {
  display: grid;
  place-items: center;
  min-height: min(72vh, 680px);
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--radius);
  padding: 40px 24px;
  text-align: center;
  box-shadow: var(--shadow-lg);
}


.pass-screen > div,
.reveal-screen > div {
  max-width: 420px;
}


.pass-screen h2,
.reveal-screen h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(1.8rem, 3vw, 2.6rem);
  font-weight: 300;
  letter-spacing: -0.03em;
  margin: 0 0 12px;
  color: var(--ink);
}

.screen-icon {
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--bg-3);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 22px;
  font-size: 1.5rem;
}


/* ── Game-over overlay ── */
@keyframes overlayIn { from { opacity:0; } to { opacity:1; } }
/* Re-renders during engine review must not replay entrance animations —
   that read as the report "appearing and disappearing" on every progress
   update. The first appearance animates; analysis renders don't. */
.game-over-overlay.no-anim,
.game-over-overlay.no-anim .game-over-card { animation: none; }
@keyframes cardIn {
  from { opacity:0; transform: scale(0.94) translateY(16px); }
  to   { opacity:1; transform: scale(1) translateY(0); }
}

.game-over-overlay {
  position: fixed; inset: 0; z-index: 900;
  display: grid; place-items: center;
  padding: max(18px, env(safe-area-inset-top)) 18px max(18px, env(safe-area-inset-bottom));
  /* Solid dim, no backdrop-filter: live blur over the full board DOM
     stalls iPhone compositing (same fix as the preset prompt). */
  background: rgba(10,14,10,0.9);
  animation: overlayIn 220ms ease;
}

.game-over-card {
  width: min(560px, 100%);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  /* iOS: allow momentum finger-scrolling inside the report. */
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  padding: 34px 30px 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
  box-shadow: var(--shadow-lg), 0 0 60px rgba(0,0,0,0.5);
  animation: cardIn 320ms 60ms cubic-bezier(0.34,1.4,0.64,1) both;
}

.game-over-card.victory { border-color: rgba(200,168,75,0.3); }
.game-over-card.defeat  { border-color: rgba(160,92,58,0.3); }
.game-over-card.draw    { border-color: rgba(255,255,255,0.14); }
.game-over-card.draw h2 { color: var(--ink-2); }
.result-kicker {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 8px;
}


.game-over-card h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(2.4rem, 7vw, 3.8rem);
  font-weight: 300;
  letter-spacing: -0.03em;
  margin: 0 0 10px;
  line-height: 1.0;
}

.game-over-card.victory h2 { color: var(--gold); }
.game-over-card.defeat  h2 { color: var(--amber); }

.result-detail {
  color: var(--ink-3);
  font-size: 0.88rem;
  margin: 0 0 20px;
  line-height: 1.5;
}
/* ── Battle report (post-game summary) ── */
.report-title {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 6px;
}


.report-chart { width: 100%; height: auto; display: block; }
.report-zero  { stroke: rgba(255,255,255,0.14); stroke-width: 1; stroke-dasharray: 3 4; }
.report-line  { fill: none; stroke: var(--gold); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.report-dot   { fill: var(--gold-dim); }

.report-axis {
  display: flex;
  justify-content: space-between;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin: 2px 2px 10px;
}
.report-cap-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  border-top: 1px solid var(--line-2);
}


.report-cap-name {
  flex-shrink: 0;
  width: 132px;
  font-size: 0.72rem;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.report-cap-icons { flex: 1; display: flex; flex-wrap: wrap; gap: 1px; min-width: 0; }
.report-cap-piece { width: 17px; height: 17px; }
.report-cap-none { font-size: 0.72rem; color: var(--ink-4); }

.report-cap-pts {
  flex-shrink: 0;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--gold);
}

.report-stats {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line-2);
  font-size: 0.7rem;
  color: var(--ink-4);
  text-align: center;
}

/* ── Campaign ── */
.campaign-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 640px;
  margin: 0 auto;
}
.stage-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
}


.stage-row {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  padding: 9px 12px;
  min-height: 42px;
}

.stage-row.done { opacity: 0.75; }
.stage-row.next {
  border-color: var(--gold-dim);
  background: var(--gold-glow);
}

.stage-row.locked { opacity: 0.45; cursor: not-allowed; }

.stage-icon { font-size: 1.1rem; flex-shrink: 0; }
.stage-name { flex: 1; font-weight: 600; font-size: 0.85rem; }
.dispatch-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 20px 20px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}


.dispatch-from {
  display: flex;
  align-items: center;
  gap: 12px;
}

.dispatch-icon { font-size: 1.9rem; }
.dispatch-name {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.25rem;
  font-weight: 500;
}
.dispatch-tagline {
  color: var(--ink-4);
  font-size: 0.7rem;
  font-family: 'IBM Plex Mono', monospace;
  letter-spacing: 0.06em;
}

.stage-done-pip {
  margin-left: auto;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.64rem;
  color: var(--moss);
  border: 1px solid rgba(90,122,74,0.4);
  border-radius: 3px;
  padding: 2px 7px;
  white-space: nowrap;
}

.dispatch-text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-2);
  font-style: italic;
  border-left: 2px solid var(--gold-dim);
  padding-left: 14px;
}

.dispatch-memory {
  border-left-color: var(--copper);
  color: var(--ink-3);
  font-size: 0.86rem;
}

.dispatch-modifier {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  color: var(--amber);
  border: 1px solid rgba(212,136,74,0.3);
  background: rgba(212,136,74,0.08);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
}

.dispatch-objectives { display: flex; flex-direction: column; gap: 4px; }

.objective-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.8rem;
  color: var(--ink-3);
  padding: 3px 0;
}

.objective-row.earned { color: var(--ink); }
.objective-star { color: var(--gold); flex-shrink: 0; }

.stage-stars {
  font-size: 0.7rem;
  color: var(--gold);
  letter-spacing: 0.1em;
}

/* ── Fog of war ── */
/* The fogged-square rule lives with the body.lcd-theme board rules — it
   must sit after (and outrank) the .square.dark halftone rule there. */

/* Post-game fog replay: dim what the side to move could not see. Veil
   colour comes from the theme's void token so it dims correctly in every
   colourway; opacity keeps the pieces beneath legible. */
.square.fog-veil { position: relative; }
.square.fog-veil::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--lcd-void);
  opacity: 0.62;
  pointer-events: none;
}

/* ── Review walkthrough ── */
.walkthrough-bar {
  border: 1px solid rgba(200,168,75,0.3);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--bg-2);
  padding: 10px 12px;
}

.walkthrough-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.walkthrough-body {
  margin: 7px 0 9px;
  font-size: 0.83rem;
  line-height: 1.5;
  color: var(--ink-2);
}

.walkthrough-body strong {
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 600;
  color: var(--ink);
}
.wt-line { display: block; }
.wt-sub { display: block; margin-top: 4px; color: var(--ink-3); font-size: 0.92em; }
.wt-verdict {
  display: inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72em; font-weight: 600;
  border: 1px solid; border-radius: 4px;
  padding: 1px 6px; margin-left: 2px;
  white-space: nowrap;
}

.walkthrough-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
/* LCD theme: pixel walkthrough bar with mono move labels. */
body.lcd-theme .walkthrough-bar { border: 2.5px solid var(--lcd-ink); background: var(--lcd-bg); border-radius: 0; }
body.lcd-theme .walkthrough-body strong,
.lcd-screen .walkthrough-body strong { font-family: 'VT323', monospace; }
.lcd-screen .walkthrough-bar { border: 2.5px solid var(--lcd-ink); background: var(--lcd-bg); }
.lcd-screen .wt-verdict { font-family: 'VT323', monospace; font-size: 0.9rem; }
/* ── Engine review ── */
.mh-verdict {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.66rem;
  font-weight: 700;
  margin-left: 2px;
}


/* ── Promotion ── */
.promotion {
  position: fixed; inset: 0;
  display: grid; place-items: center;
  /* Solid dim, no backdrop-filter: live blur over the full board DOM
     stalls iOS compositing (same fix as .game-over-overlay/.cprompt). */
  background: rgba(10,14,10,0.88);
  padding: 16px;
  animation: overlayIn 180ms ease;
}

.promotion .panel {
  width: min(360px, 100%);
  animation: cardIn 260ms cubic-bezier(0.34,1.5,0.64,1) both;
}

.promotion-options {
  display: grid;
  grid-template-columns: repeat(4,1fr);
  gap: 6px;
  margin-top: 4px;
}

.promotion-options button {
  min-height: 72px;
  font-size: 2rem;
  flex-direction: column;
  gap: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-3);
}

.promotion-options button:hover:not(:disabled) {
  background: var(--gold-glow);
  border-color: var(--gold-dim);
}
/* ── Bot Personalities ── */
/* ── Badge Gallery ── */
.badge-gallery {
  max-width: 760px;
  margin: 0 auto;
  padding: 8px 0 24px;
}

.badge-gallery-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}
.badge-gallery-header h2 { margin: 0; font-size: 1.25rem; flex: 1; }
.badge-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.badge-card {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.15s;
}
.badge-card.earned { border-color: var(--gold); }
.badge-card.locked { opacity: 0.45; }
.badge-card-icon { line-height: 1; margin-top: 2px; min-width: 1.6rem; color: var(--lcd-ink); display: grid; place-items: center; }
.badge-card-body { flex: 1; min-width: 0; }
.badge-card-name {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-1);
  margin-bottom: 2px;
}
.badge-card.earned .badge-card-name { color: var(--gold); }
.badge-card-desc {
  font-size: 0.7rem;
  color: var(--ink-3);
  line-height: 1.4;
  margin-bottom: 6px;
}
.badge-tiers { display: flex; gap: 5px; align-items: center; }
.badge-tier {
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 2px solid var(--line);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.45rem;
  font-weight: 800;
  letter-spacing: 0;
  color: transparent;
}
.badge-tier.bronze-earned { background: #cd7f32; border-color: #cd7f32; color: #fff; }
.badge-tier.silver-earned { background: #a8a9ad; border-color: #a8a9ad; color: #fff; }
.badge-tier.gold-earned   { background: var(--gold); border-color: var(--gold); color: #fff; }
.badge-tier-label { font-size: 0.6rem; color: var(--ink-4); margin-left: 2px; }
/* New-badge toast in game-over card */
/* ── Setup config screen ── */
.config-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin: 0 0 9px;
  display: block;
}

/* Color picker – large tappable tiles */
/* Difficulty cards */
.config-deploy-btn {
  width: 100%;
  margin-top: 6px;
  min-height: 50px;
  font-size: 0.92rem;
}

/* ── Hero card (setup intro) ── */
/* Mini board inside hero card */
/* ── Personality list (step 1, bot mode) ── */
/* ── Step 2 nav (back + bot badge) ── */
/* ── Preset army slots ── */
.preset-section {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.preset-slots {
  /* 3×3: six built-in armies then the player's three save slots. A grid
     (not a flex row) so names get real room instead of truncating. */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.preset-slot-wrap {
  position: relative;
  min-width: 0; /* F1: without this, nowrap names force slots past the screen edge */
}
.preset-slot-btn {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 5px 3px;
  min-height: 52px;
  gap: 2px;
  overflow: hidden;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: none;
  transform: none;
  cursor: pointer;
}
.preset-slot-btn.empty {
  border-style: dashed;
  background: transparent;
}
.preset-slot-btn.empty:disabled { opacity: 0.2; cursor: not-allowed; }
.preset-slot-btn.filled:hover { border-color: var(--line-2); background: var(--bg-4); }
.preset-slot-btn.locked {
  opacity: 0.5;
  cursor: not-allowed;
  border-style: dashed;
  border-color: var(--copper);
}
.preset-slot-btn.locked .preset-slot-summary { color: var(--amber); }
.preset-slot-num {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.5rem;
  color: var(--ink-4);
  line-height: 1;
}
.preset-slot-name {
  font-size: 0.58rem;
  color: var(--ink-1);
  font-weight: 600;
  text-align: center;
  line-height: 1.2;
  max-width: 100%;
  padding: 0 2px;
}
.preset-slot-summary {
  font-size: 0.48rem;
  color: var(--ink-4);
  text-align: center;
  line-height: 1.2;
  letter-spacing: -0.01em;
  max-width: 100%;
}
.preset-slot-icon {
  font-size: 1rem;
  color: var(--ink-4);
  line-height: 1;
}
.preset-clear-btn {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 22px;
  height: 22px;
  font-size: 0.62rem;
  padding: 0;
  min-height: 0;
  border-radius: 50%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--ink-4);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: none;
  transform: none;
  line-height: 1;
  cursor: pointer;
  z-index: 1;
}
.preset-clear-btn:hover { color: var(--ink-1); border-color: var(--line-2); background: var(--bg-3); }
/* F11: destructive controls need a real target - invisible 38px hit area */
.preset-clear-btn::after { content: ""; position: absolute; inset: -8px; }

/* ── Custom prompt modal ── */
.cprompt-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: grid; place-items: center; padding: 18px;
  /* Solid dim, no backdrop-filter: live blur over a full board DOM caused
     multi-second compositing stalls on iPhone when this prompt opened. */
  background: rgba(10,14,10,0.88);
  animation: overlayIn 200ms ease;
}
.cprompt-overlay.hidden { display: none; }
.cprompt-card {
  width: min(360px, 100%);
  padding: 28px 24px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  animation: cardIn 280ms 40ms cubic-bezier(0.34,1.4,0.64,1) both;
  display: flex; flex-direction: column; gap: 14px;
}
.cprompt-label {
  font-size: 0.95rem; font-weight: 600; color: var(--ink-1);
}
.cprompt-input {
  width: 100%; box-sizing: border-box;
  padding: 10px 12px;
  font-size: 1.15rem; font-family: inherit;
  background: var(--bg-2); color: var(--ink-1);
  border: 2px solid var(--line); border-radius: var(--radius-sm);
  outline: none;
}
.cprompt-input:focus { border-color: var(--accent); }
.cprompt-btns {
  display: flex; gap: 10px; justify-content: flex-end;
}
.cprompt-cancel {
  padding: 9px 18px; border-radius: var(--radius-sm); border: 2px solid var(--line);
  background: transparent; color: var(--ink-2); font-size: 0.9rem; cursor: pointer;
}
.cprompt-ok {
  padding: 9px 22px; border-radius: var(--radius-sm); border: 2px solid var(--line);
  background: var(--accent); color: var(--surface); font-size: 0.9rem;
  font-weight: 600; cursor: pointer;
}
/* Beat the generic button remap so the confirm reads as the primary. */
body.lcd-theme .cprompt-ok { background: var(--lcd-fill); color: var(--lcd-on-fill, var(--lcd-bg)); }
body.lcd-theme .cprompt-input { background: var(--lcd-bg); }

/* ── Horizontal move history ── */
.move-history-h {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  padding: 7px 8px;
  scrollbar-width: none;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-top: none;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  /* Horizontal scrolling is owned by the manual drag-to-scroll in main.js —
     native iOS overflow panning proved unreliable on this composited flex
     row of buttons (two CSS attempts failed on device). pan-y (not none)
     so a VERTICAL swipe starting on the strip still scrolls the page:
     the JS scrub only drives X, and blocking Y made the report feel dead. */
  touch-action: pan-y;
  overscroll-behavior-x: contain;
}
.move-history-h::-webkit-scrollbar { display: none; }
/* Fog mid-game: inert chips (no navigation) + redacted enemy moves. */
.mh-chip.static { cursor: default; }
.mh-chip.redacted { opacity: 0.55; }
.mh-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  touch-action: pan-x;
  padding: 3px 9px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 3px;
  white-space: nowrap;
  cursor: pointer;
  flex-shrink: 0;
  min-height: 32px;
  font-size: 0.72rem;
  color: var(--ink-2);
  box-shadow: none;
  transform: none;
  font-weight: 400;
}
.mh-chip:hover { border-color: var(--line-2); background: var(--bg-4); transform: none; }
.mh-chip.active {
  background: var(--gold-glow);
  border-color: var(--gold-dim);
  color: var(--gold);
  font-weight: 600;
}
.mh-chip-num {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  color: var(--ink-4);
}
.mh-chip.active .mh-chip-num { color: var(--gold-dim); }

/* ── Divider ── */
.divider {
  border: none;
  border-top: 1px solid var(--line);
  margin: 12px 0;
}

/* ── Responsive ── */
/* ── Board touch: prevent page-scroll conflicting with piece drag ──
   Only on a LIVE board (your move possible). Post-game / review / setup
   boards keep native scrolling — a dead board that eats vertical swipes
   made the report and engine-review pages impossible to scroll. */
.board-live { touch-action: none; }
/* ── Play-mode header: compact strip at all viewport sizes ── */
header.header-compact {
  padding: 8px 16px;
  margin-bottom: 10px;
  flex-wrap: nowrap;
  gap: 10px;
}

/* (header-compact base styles are defined above in the main header block) */

/* ── Tablet (601px – 860px) ── */
@media (max-width: 860px) {
  .app { padding: max(12px, env(safe-area-inset-top)) 12px max(12px, env(safe-area-inset-bottom)); }
  header { margin-bottom: 14px; }
  .layout { display: block; }
  .board-shell { width: 100%; }
.badge-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}

/* ── Phone (≤ 600px) — primary mobile target ── */
@media (max-width: 600px) {
  .app { padding: max(8px, env(safe-area-inset-top)) 8px max(32px, env(safe-area-inset-bottom)); }
/* Header */
header.header-compact { padding: 6px 10px; }

  header.header-compact h1 { font-size: 1rem; }

  /* Board shell */
  .board-shell { padding: 5px; }

  /* Panels */
  .panel { padding: 10px 11px; }
  .panel h2 { font-size: 0.57rem; margin-bottom: 9px; }
  .panel + .panel { margin-top: 7px; }

  /* Tray */
  .tray { grid-template-columns: repeat(3, 1fr); gap: 4px; }
  .tray button { min-height: 50px; padding: 5px 7px; font-size: 0.73rem; gap: 4px; }
  .tray-piece { width: 28px; height: 28px; }
/* Segmented controls */
/* Buttons */
button { min-height: 40px; font-size: 0.79rem; }

  .actions { gap: 6px; margin-top: 9px; }
  .actions button { min-height: 40px; }

  /* Badge gallery */
  .badge-grid { grid-template-columns: 1fr; }
  .badge-gallery-header h2 { font-size: 1rem; }
  .badge-card { padding: 8px 9px; }

  /* Game-over overlay: scrollable */
  .game-over-overlay {
    align-items: flex-start;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: max(12px, env(safe-area-inset-top)) 12px max(12px, env(safe-area-inset-bottom));
  }
  .game-over-card { margin: auto; padding: 24px 16px 18px; width: 100%; }
  .game-over-card h2 { font-size: clamp(1.9rem, 10vw, 2.8rem); }
  .result-detail { font-size: 0.8rem; margin-bottom: 16px; }

  /* Promotion */
  .promotion-options button { min-height: 60px; font-size: 1.7rem; }

  /* Pass / Reveal screens */
  .pass-screen, .reveal-screen { min-height: min(58vh, 420px); padding: 22px 12px; }
  .pass-screen h2, .reveal-screen h2 { font-size: clamp(1.4rem, 6vw, 1.9rem); }
}

/* ════════════════════════════════════════════════════════════════════
   LCD PLAY SCREEN — monochrome-LCD reskin, scoped to .lcd-screen only.
   Everything else in the app keeps the forest theme.
   ════════════════════════════════════════════════════════════════════ */
.app-lcd { max-width: 100%; padding: 0; }

.lcd-screen {
  /* Tokens inherit from body.lcd-theme — the single source of truth, so a
     theme (dark mode, colourways) is one override block, not two. */
  background: var(--lcd-bg);
  color: var(--lcd-ink);
  font-family: 'Silkscreen', monospace;
  -webkit-font-smoothing: none;
  image-rendering: pixelated;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: max(8px, env(safe-area-inset-top)) 9px max(8px, env(safe-area-inset-bottom));
  position: relative;
  overflow: hidden;
}
/* Scanlines + vignette for the lit-LCD feel */
.lcd-screen::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 5;
  background:
    repeating-linear-gradient(0deg, var(--lcd-scan, rgba(20,26,16,0.10)) 0 1px, transparent 1px 3px),
    radial-gradient(120% 80% at 50% 40%, transparent 60%, rgba(20,26,16,0.16) 100%);
  mix-blend-mode: multiply;
}

/* ── Status bar ── */
.lcd-status { display: flex; align-items: center; justify-content: space-between; }
.lcd-title { font-weight: 700; font-size: 1.1rem; letter-spacing: 0.22em; }
.lcd-signal { display: flex; align-items: flex-end; gap: 2px; height: 15px; }
.lcd-signal i { width: 4px; background: var(--lcd-ink); display: block; }
.lcd-signal i:nth-child(1){height:5px}.lcd-signal i:nth-child(2){height:8px}
.lcd-signal i:nth-child(3){height:11px}.lcd-signal i:nth-child(4){height:14px}
.lcd-batt { display: flex; gap: 2px; border: 2px solid var(--lcd-ink); padding: 2px; position: relative; }
.lcd-batt::after{ content:""; position:absolute; right:-5px; top:4px; width:3px; height:7px; background:var(--lcd-ink); }
.lcd-batt i { width: 4px; height: 10px; background: var(--lcd-ink); display:block; }

/* ── Player plates ── */
.lcd-plate {
  border: 2.5px solid var(--lcd-ink);
  padding: 5px 8px;
  display: flex; align-items: center; gap: 8px;
  min-height: 34px;
}
.lcd-swatch { width: 16px; height: 16px; border: 2.5px solid var(--lcd-ink); flex-shrink: 0; }
.lcd-swatch.black { background: var(--lcd-ink); }
.lcd-plate-name { font-size: 0.85rem; letter-spacing: 0.04em; white-space: nowrap; }
.lcd-plate-sub { color: var(--lcd-dim); font-size: 0.7rem; }
.lcd-plate-caps { display: flex; align-items: center; gap: 0; flex: 1; flex-wrap: wrap; min-width: 0; justify-content: flex-end; }
.lcd-cap-none { color: var(--lcd-dim); font-family: 'VT323', monospace; font-size: 1.1rem; }
.lcd-mini { width: 19px; height: 19px; display: inline-block; flex-shrink: 0; }

/* ── Board ── */
.lcd-board-host { display: flex; justify-content: center; }
.lcd-screen .board-frame {
  display: grid;
  grid-template-columns: 16px 1fr;
  grid-template-rows: 1fr 16px;
  gap: 0;
  width: 100%;
  background: none;
  border: none; padding: 0; box-shadow: none;
}
.lcd-screen .rank-gutter {
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column;
  background: none; padding: 0;
}
.lcd-screen .rank-gutter .coord,
.lcd-screen .file-gutter .coord {
  display: flex; align-items: center; justify-content: center;
  color: var(--lcd-ink); font-family: 'Silkscreen', monospace; font-size: 0.62rem;
  flex: 1;
}
.lcd-screen .board {
  grid-column: 2; grid-row: 1;
  border: 3px solid var(--lcd-ink);
  gap: 0; background: none; box-shadow: none; border-radius: 0;
}
.lcd-screen .file-gutter {
  grid-column: 2; grid-row: 2;
  display: grid; grid-template-columns: repeat(8, 1fr);
  background: none; padding: 0;
}
.lcd-screen .file-gutter .coord { height: 16px; }

/* Squares */
.lcd-screen .square {
  border: none; border-radius: 0; box-shadow: none;
  background: var(--lcd-bg);
  display: flex; align-items: center; justify-content: center;
  position: relative;
  transform: none;
  padding: 0;
}
.lcd-screen .square.dark {
  /* Light base with thin HORIZONTAL ink lines — reads as a medium halftone
     gray: clearly darker than a light square, but not heavy, and no moiré
     (horizontal lines don't shimmer the way the diagonal hatch did). */
  background-color: var(--lcd-bg);
  background-image: repeating-linear-gradient(0deg, var(--lcd-ink) 0 1px, transparent 1px 3px);
}
/* Dark squares are now only medium gray, so dark-ink markers read on both. */
.lcd-screen .square { --mark: var(--lcd-ink); }

/* Pieces */
.lcd-pc { position: relative; display: block; width: 86%; height: 86%; }
.lcd-pc .lcd-lay {
  position: absolute; inset: 0;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
/* Piece layers use DEDICATED tokens, not bg/ink — a piece must read the
   same in every theme (black = dark fill haloed light; white = light body
   with a dark outline), so these must NOT invert with the screen. pc-back
   is always the light halo/body; pc-art is always the dark fill/outline. */
.lcd-pc .backing { -webkit-mask-image: var(--out); mask-image: var(--out); background: var(--lcd-pc-back, var(--lcd-bg)); }
.lcd-pc .art     { -webkit-mask-image: var(--art); mask-image: var(--art); background: var(--lcd-pc-art, var(--lcd-ink)); }
.lcd-mini .lcd-pc { width: 100%; height: 100%; }

/* Interaction markers (pixel style) — override the forest theme fully.
   All use var(--mark), which contrasts the square underneath. */
.lcd-screen .square.selected {
  outline: 3px solid var(--mark); outline-offset: -3px;
  box-shadow: none; background-blend-mode: normal;
}
.lcd-screen .square.legal::after {
  content: ""; position: absolute; width: 30%; height: 30%;
  background: var(--mark); border-radius: 0; box-shadow: none;
}
.lcd-screen .square.capture::after {
  content: ""; position: absolute; inset: 9%; width: auto; height: auto;
  border: 3px solid var(--mark); border-radius: 0; box-shadow: none;
  background: none;
}
.lcd-screen .square.last-from,
.lcd-screen .square.last-to { box-shadow: inset 0 0 0 2px var(--mark); }
.lcd-screen .square.in-check {
  box-shadow: inset 0 0 0 3px var(--mark);
  animation: lcdBlink 0.7s steps(1) infinite; z-index: 2;
}
@keyframes lcdBlink { 50% { box-shadow: inset 0 0 0 3px transparent; } }

/* ── Turn line ── */
.lcd-turn { text-align: center; font-size: 0.95rem; letter-spacing: 0.08em; padding: 1px 0; }
.lcd-note {
  font-family: 'VT323', monospace; font-size: 0.95rem; text-align: center;
  border: 2px solid var(--lcd-ink); padding: 4px 8px;
}

/* ── Move strip (reuse .move-history-h, restyle) ── */
.lcd-screen .move-history-h {
  background: none; border: 2.5px solid var(--lcd-ink); border-radius: 0;
  padding: 5px 6px; gap: 4px;
}
.lcd-screen .mh-chip {
  background: none; border: 1.5px solid var(--lcd-dim); border-radius: 0;
  color: var(--lcd-ink); font-family: 'VT323', monospace; font-size: 0.95rem;
  min-height: 28px; padding: 1px 7px;
}
.lcd-screen .mh-chip.active { background: var(--lcd-ink); color: var(--lcd-bg); border-color: var(--lcd-ink); }
.lcd-screen .mh-chip-num { color: var(--lcd-dim); font-size: 0.8rem; }
.lcd-screen .mh-chip.active .mh-chip-num { color: var(--lcd-bg); }
.lcd-screen .mh-verdict { font-family: 'VT323', monospace; }

/* ── Controls + soft keys ── */
.lcd-controls { display: flex; justify-content: center; gap: 6px; }
.lcd-key, .lcd-soft {
  font-family: 'Silkscreen', monospace; font-weight: 700;
  background: none; border: 2.5px solid var(--lcd-ink); color: var(--lcd-ink);
  border-radius: 0; min-height: 40px; letter-spacing: 0.04em;
  transition: none; box-shadow: none;
}
.lcd-key { font-size: 0.85rem; padding: 6px 14px; min-width: 52px; }
.lcd-key.wide { flex: 0 0 auto; }
.lcd-key:disabled { opacity: 0.3; }
.lcd-key:active:not(:disabled), .lcd-soft:active { background: var(--lcd-ink); color: var(--lcd-bg); transform: none; }
.lcd-softkeys { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: auto; }
.lcd-soft { font-size: 0.9rem; padding: 12px 0; }

/* ════════════════════════════════════════════════════════════════════
   WHOLE-APP LCD THEME — body.lcd-theme remaps the design tokens to the
   monochrome-LCD palette so every screen (home, setup, campaign, badges,
   report, modals) adopts the look using its existing markup. The play
   screen has its own self-contained .lcd-screen treatment.
   ════════════════════════════════════════════════════════════════════ */
body.lcd-theme {
  --lcd-bg:   #909e6a;   /* lit Nokia screen */
  --lcd-bg-2: #7f8d5a;   /* darker — dark squares, locked rows, shadows */
  --lcd-ink:  #1b2312;   /* dark pixels */
  --lcd-fill: #3a4a26;   /* dark green — primary/active button fills */
  --lcd-dim:  #3e4a28;   /* faded ink — F10: ≥3:1 on the lit screen */
  --lcd-void: #11160f;   /* fog-of-war unseen squares — darker than everything */

  --bg: var(--lcd-bg);      --bg-2: var(--lcd-bg);
  --bg-3: var(--lcd-bg);    --bg-4: var(--lcd-bg-2);
  --surface: var(--lcd-bg); --surface-2: var(--lcd-bg);
  --ink: var(--lcd-ink);    --ink-1: var(--lcd-ink); --ink-2: var(--lcd-ink);
  --ink-3: var(--lcd-dim);  --ink-4: var(--lcd-dim);
  --line: var(--lcd-ink);   --line-2: rgba(27,35,18,0.45);
  --light: var(--lcd-bg);   --dark: var(--lcd-bg-2); --board-frame: var(--lcd-ink);
  --gold: var(--lcd-ink);   --gold-dim: var(--lcd-dim); --gold-glow: rgba(27,35,18,0.14);
  --amber: var(--lcd-ink);  --moss: var(--lcd-ink); --copper: var(--lcd-ink);
  --active: var(--lcd-ink); --move: var(--lcd-ink); --capture: var(--lcd-ink);
  --shadow-sm: none; --shadow-md: none; --shadow-lg: none;
  --radius: 0px; --radius-sm: 0px;

  background: var(--lcd-bg);
  color: var(--lcd-ink);
  font-family: 'VT323', monospace;
}

/* App-wide CRT feel: venetian-blind scanlines + a soft vignette, fixed over
   everything (the play screen has its own; this covers all other screens). */
body.lcd-theme::after {
  content: ""; position: fixed; inset: 0; z-index: 9000; pointer-events: none;
  background:
    repeating-linear-gradient(0deg, var(--lcd-scan, rgba(20,26,12,0.13)) 0 1px, transparent 1px 3px),
    radial-gradient(130% 100% at 50% 45%, transparent 58%, rgba(20,26,12,0.30) 100%);
  mix-blend-mode: multiply;
}

/* Primary + active buttons fill dark green with light text. */
body.lcd-theme button.primary,
body.lcd-theme button.active,
body.lcd-theme .segmented button.active,
body.lcd-theme .opt.on,
body.lcd-theme .menu-big.primary {
  background: var(--lcd-fill);
  color: var(--lcd-on-fill, var(--lcd-bg));
  border-color: var(--lcd-ink);
}

/* Typography: pixel display font for headings/labels/buttons, readable
   terminal font (VT323) for body prose. */
body.lcd-theme h1,
body.lcd-theme h2,
body.lcd-theme h3,
body.lcd-theme .display,
body.lcd-theme .label,
body.lcd-theme .config-label,
body.lcd-theme button,
body.lcd-theme .segmented button,
body.lcd-theme .brand-sub,
body.lcd-theme .dispatch-name,
body.lcd-theme .act-title,
body.lcd-theme .hero-title,
body.lcd-theme .result-kicker {
  font-family: 'Silkscreen', monospace !important;
  letter-spacing: 0.04em;
  font-weight: 400;
}
/* Serif display names become pixel — dial the size so they don't dwarf. */
body.lcd-theme .dispatch-name { font-size: 1rem; }
body.lcd-theme .display,
body.lcd-theme h1 { font-weight: 700; }
body.lcd-theme p,
body.lcd-theme .small,
body.lcd-theme .mono,
body.lcd-theme .status,
body.lcd-theme .hero-body,
body.lcd-theme .dispatch-text,
body.lcd-theme .config-deploy-btn,
body.lcd-theme input {
  font-family: 'VT323', monospace !important;
}
/* VT323 is small per em — bump body sizes a touch for legibility. */
body.lcd-theme p, body.lcd-theme .small { font-size: 0.95rem; line-height: 1.4; }
body.lcd-theme { -webkit-font-smoothing: none; image-rendering: pixelated; }
/* Sharp corners + solid ink borders everywhere (beveled-box LCD look). */
body.lcd-theme .config-card,
body.lcd-theme .panel,
body.lcd-theme .campaign-act,
body.lcd-theme .dispatch-card,
body.lcd-theme .game-over-card,
body.lcd-theme .cprompt-card,
body.lcd-theme .badge-card.earned {
  border: 2.5px solid var(--lcd-ink);
  background: var(--lcd-bg);
}

body.lcd-theme button {
  border: 2px solid var(--lcd-ink);
  background: var(--lcd-bg);
  color: var(--lcd-ink);
  transition: none;
}

body.lcd-theme button,
body.lcd-theme .panel,
body.lcd-theme .preset-slot-btn,
body.lcd-theme .stage-row,
body.lcd-theme .dispatch-card,
body.lcd-theme .badge-card,
body.lcd-theme .game-over-card,
body.lcd-theme .cprompt-card {
  border-radius: 0 !important;
  box-shadow: none !important;
}


body.lcd-theme button:hover:not(:disabled),
body.lcd-theme button.active {
  background: var(--lcd-ink);
  color: var(--lcd-bg);
}

body.lcd-theme button.primary {
  background: var(--lcd-ink);
  color: var(--lcd-bg);
  border-color: var(--lcd-ink);
}

body.lcd-theme button.primary:hover:not(:disabled) {
  background: var(--lcd-bg);
  color: var(--lcd-ink);
}
/* Header wordmark */
body.lcd-theme .header-home h1,
body.lcd-theme .header-compact h1 { color: var(--lcd-ink); letter-spacing: 0.18em; }

body.lcd-theme .divider-line { background: var(--lcd-ink); opacity: 0.5; }

body.lcd-theme .turn-pill {
  border: 2px solid var(--lcd-ink); background: var(--lcd-bg);
  color: var(--lcd-ink); border-radius: 0; font-family: 'Silkscreen', monospace;
}

/* Board on non-play screens (deployment, hero): same medium-gray LCD cells */
body.lcd-theme .board-frame { background: none; }
body.lcd-theme .board { border: 3px solid var(--lcd-ink); gap: 0; box-shadow: none; }
body.lcd-theme .square { border: none; box-shadow: none; background: var(--lcd-bg); }
body.lcd-theme .square.dark {
  background-color: var(--lcd-bg);
  background-image: repeating-linear-gradient(0deg, var(--lcd-ink) 0 1px, transparent 1px 3px);
}
/* Fog of war: unseen squares drop to the void tone — the darkest colour in
   every theme. Must come AFTER .square.dark and match its specificity,
   otherwise the halftone repaints fogged dark squares as normal squares
   (the "fog tiles look like plain dark squares" bug). */
body.lcd-theme .square.fogged {
  background-color: var(--lcd-void);
  background-image: none;
  cursor: default;
}
body.lcd-theme .square.deploy-zone { outline: 1px solid rgba(32,39,26,0.4); outline-offset: -1px; }
body.lcd-theme .coord { color: var(--lcd-ink); font-family: 'Silkscreen', monospace; font-size: 0.6rem; }

/* Progress / budget bar */
body.lcd-theme .progress-track { background: var(--lcd-bg-2); border: 2px solid var(--lcd-ink); border-radius: 0; }
body.lcd-theme .progress-fill { background: var(--lcd-ink); border-radius: 0; }

/* Pieces inside trays/captured rows fill their fixed-size container. */
body.lcd-theme .tray-piece .lcd-pc,
body.lcd-theme .piece .lcd-pc { width: 100%; height: 100%; }
body.lcd-theme .tray-piece { width: 32px; height: 32px; }

/* Board frame: light, no dark backing (the .board has its own ink border). */
body.lcd-theme .board-shell {
  background: var(--lcd-bg); border: none; box-shadow: none; padding: 0;
}
/* Deployment: the non-deployment ranks shouldn't read as a heavy dark
   block. Faint hatch on light, no brightness filter / opacity. */
body.lcd-theme .square.out-zone {
  filter: none; opacity: 1;
  background: var(--lcd-bg);
  background-image: repeating-linear-gradient(0deg, rgba(32,39,26,0.16) 0 1px, transparent 1px 5px);
}
body.lcd-theme .square.deploy-zone.dark {
  background-image: repeating-linear-gradient(0deg, var(--lcd-ink) 0 1px, transparent 1px 3px);
}
/* Hero intro board: simple LCD squares, hide the decorative glyphs. */
/* ════════════════════════════════════════════════════════════════════
NEW MENU FLOW — Home, Custom, Appearance, Settings, paged Campaign.
Pixel buttons: stepped corners (clip-path) + ink frame (inset shadow)
+ hard offset drop shadow (filter, which respects the clip).
════════════════════════════════════════════════════════════════════ */
body.lcd-theme .app-menu { padding: max(18px, env(safe-area-inset-top)) 16px max(18px, env(safe-area-inset-bottom)); }


body.lcd-theme .menu-big,
body.lcd-theme .opt,
body.lcd-theme .opt-sprite,
body.lcd-theme .home-icon,
body.lcd-theme .icon-btn,
body.lcd-theme .stage-row,
body.lcd-theme .dispatch-card,
body.lcd-theme .badge-card.earned {
  --pc: 4px;
  border: none !important;
  background: var(--lcd-bg);
  clip-path: polygon(0 var(--pc), var(--pc) var(--pc), var(--pc) 0,
    calc(100% - var(--pc)) 0, calc(100% - var(--pc)) var(--pc), 100% var(--pc),
    100% calc(100% - var(--pc)), calc(100% - var(--pc)) calc(100% - var(--pc)), calc(100% - var(--pc)) 100%,
    var(--pc) 100%, var(--pc) calc(100% - var(--pc)), 0 calc(100% - var(--pc)));
  box-shadow: inset 0 0 0 3px var(--lcd-ink) !important;
  filter: drop-shadow(3px 3px 0 var(--lcd-ink));
}
body.lcd-theme .menu-big:active,
body.lcd-theme .opt:active,
body.lcd-theme .opt-sprite:active,
body.lcd-theme .home-icon:active,
body.lcd-theme .icon-btn:active,
body.lcd-theme .stage-row:active {
  filter: none; transform: translate(2px, 2px);
}
body.lcd-theme .menu-big:disabled,
body.lcd-theme .stage-row.locked { opacity: 0.55; filter: none; }

/* ── Home ── */
.home { display: flex; flex-direction: column; align-items: center; gap: 0; min-height: 86vh; }
.home-logo { display: flex; flex-direction: column; align-items: center; margin-top: 4vh; }
.home-bishop { width: 110px; height: 110px; }
.home-bishop .lcd-pc { width: 100%; height: 100%; }
/* Solid ink-filled bishop logo (single mask layer) — solid in every theme,
   so it reads as a filled silhouette on dark backgrounds too. */
.lcd-logo-bishop {
  display: block; width: 100%; height: 100%;
  background: var(--lcd-ink);
  -webkit-mask-image: var(--art); mask-image: var(--art);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.home-wordmark { font-family: 'Silkscreen', monospace; font-weight: 700; font-size: 3.1rem; letter-spacing: 0.12em; margin: 8px 0 4px; color: var(--lcd-ink); }
.home-sub { font-family: 'Silkscreen', monospace; font-size: 0.78rem; letter-spacing: 0.14em; color: var(--lcd-ink); }
.home-main { width: 100%; display: flex; flex-direction: column; gap: 18px; margin-top: 7vh; }
/* Secondary, quieter than the two big buttons — no pixel frame, just text.
   Scoped under body.lcd-theme to beat the generic button border/bg remap. */
body.lcd-theme .home-howto {
  align-self: center; margin-top: -4px;
  background: none; border: none; box-shadow: none; filter: none;
  font-family: 'Silkscreen', monospace; font-size: 0.78rem; letter-spacing: 0.1em;
  color: var(--lcd-dim); cursor: pointer; padding: 6px 10px;
}
body.lcd-theme .home-howto:active { transform: translateY(1px); }
.menu-big {
  width: 100%; min-height: 58px;
  font-family: 'Silkscreen', monospace; font-size: 1.5rem; letter-spacing: 0.08em;
  color: var(--lcd-ink); display: flex; align-items: center; justify-content: center; gap: 10px;
  cursor: pointer;
}
.menu-big.primary { color: var(--lcd-on-fill, var(--lcd-bg)); }
.menu-big .pic { width: 18px; height: 18px; }
.home-mini { display: flex; gap: 18px; margin-top: 5vh; }
.home-icon { width: 58px; height: 58px; display: grid; place-items: center; color: var(--lcd-ink); cursor: pointer; }

/* ── Menu screens (Custom / Appearance / Settings) ── */
.menu-screen { display: flex; flex-direction: column; gap: 18px; max-width: 560px; margin: 0 auto; }
.menu-head { display: flex; align-items: center; gap: 14px; }
.menu-head h2 { font-family: 'Silkscreen', monospace; font-size: 1.6rem; letter-spacing: 0.08em; margin: 0; }
.icon-btn { width: 46px; height: 46px; display: grid; place-items: center; color: var(--lcd-ink); cursor: pointer; flex-shrink: 0; }
.quick-start { min-height: 54px; font-size: 1.3rem; }
.opt-group { display: flex; flex-direction: column; gap: 8px; }
.opt-label { font-family: 'Silkscreen', monospace; font-size: 1rem; letter-spacing: 0.06em; color: var(--lcd-ink); }
.opt-row { display: flex; gap: 12px; }
.opt {
  flex: 1; min-height: 50px;
  font-family: 'Silkscreen', monospace; font-size: 1rem; letter-spacing: 0.04em;
  color: var(--lcd-ink); cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.opt.on { color: var(--lcd-on-fill, var(--lcd-bg)); }
.opt-note { font-family: 'VT323', monospace; font-size: 0.95rem; color: var(--lcd-dim); margin: 2px 0 0; }
/* Web build only: quiet donate link in Settings. */
.coffee-link { color: var(--lcd-ink); text-decoration: underline; }
.opt-sprites { display: flex; flex-wrap: wrap; gap: 8px; }
.opt-sprite { width: 46px; height: 46px; display: grid; place-items: center; cursor: pointer; }
.opt-sprite.on { background: var(--lcd-fill); }
.opt-sprite.on .lcd-pc .backing { background: var(--lcd-fill); }
.opt-sprite .lcd-pc { width: 30px; height: 30px; }
.bot-q { font-family: 'Silkscreen', monospace; font-weight: 700; font-size: 1.3rem; color: var(--lcd-ink); }
.opt-sprite.on .bot-q { color: var(--lcd-on-fill, var(--lcd-bg)); }
.menu-foot { display: flex; gap: 12px; align-items: stretch; margin-top: 8px; }
.menu-foot .menu-big { flex: 1; min-height: 52px; font-size: 1.2rem; }
.menu-foot .icon-btn { width: 52px; height: auto; }

/* ── Campaign (paged Part) ── */
.campaign-part-head { margin-bottom: 4px; }
.part-kick { font-family: 'Silkscreen', monospace; font-size: 0.72rem; letter-spacing: 0.22em; color: var(--lcd-dim); margin: 0 0 2px; }
.part-title { font-family: 'Silkscreen', monospace; font-weight: 700; font-size: 2.2rem; letter-spacing: 0.04em; margin: 0; }
.part-sub { font-family: 'VT323', monospace; font-size: 1.1rem; color: var(--lcd-ink); margin: 4px 0 0; line-height: 1.3; }
body.lcd-theme .stage-row {
  display: flex; align-items: center; gap: 14px; padding: 10px 14px; min-height: 56px; width: 100%;
  cursor: pointer; text-align: left;
}
.stage-icon { width: 34px; height: 34px; display: grid; place-items: center; flex-shrink: 0; }
.stage-icon .lcd-pc { width: 32px; height: 32px; }
.stage-icon .bot-q { font-size: 1.6rem; }
/* Character portraits (Design handoff 5): 1-bit busts tinted by the ink
   token via currentColor — they follow every colourway automatically. */
.bot-portrait { display: grid; place-items: center; color: var(--lcd-ink); }
.dispatch-icon .bot-portrait svg { display: block; }
.lcd-plate-portrait { display: grid; place-items: center; color: var(--lcd-ink); flex-shrink: 0; }
.stage-name { flex: 1; font-family: 'Silkscreen', monospace; font-size: 1.05rem; letter-spacing: 0.04em; color: var(--lcd-ink); }
.stage-stars { display: flex; gap: 3px; flex-shrink: 0; color: var(--lcd-ink); }
.stage-stars.locked { opacity: 0.7; }
body.lcd-theme .stage-row.done { background: var(--lcd-bg); }
body.lcd-theme .stage-row.next { background: var(--lcd-bg-2); }
.campaign-screen { display: flex; flex-direction: column; gap: 14px; max-width: 560px; margin: 0 auto; }
.campaign-screen .stage-list { display: flex; flex-direction: column; gap: 12px; }

.pic { vertical-align: middle; }

/* ── Bots page: accordion opponent + difficulty picker ── */
.bot-acc-list { display: flex; flex-direction: column; gap: 12px; }
body.lcd-theme .bot-acc.open,
body.lcd-theme .bot-acc:not(.open) .bot-acc-head {
  --pc: 4px;
  border: none !important;
  background: var(--lcd-bg);
  clip-path: polygon(0 var(--pc), var(--pc) var(--pc), var(--pc) 0,
    calc(100% - var(--pc)) 0, calc(100% - var(--pc)) var(--pc), 100% var(--pc),
    100% calc(100% - var(--pc)), calc(100% - var(--pc)) calc(100% - var(--pc)), calc(100% - var(--pc)) 100%,
    var(--pc) 100%, var(--pc) calc(100% - var(--pc)), 0 calc(100% - var(--pc)));
  box-shadow: inset 0 0 0 3px var(--lcd-ink) !important;
  filter: drop-shadow(3px 3px 0 var(--lcd-ink));
}
.bot-acc-head {
  display: flex; align-items: center; gap: 14px; padding: 10px 14px; min-height: 56px;
  width: 100%; cursor: pointer; text-align: left; color: var(--lcd-ink);
}
.bot-acc:not(.open) .bot-acc-head:active { filter: none; transform: translate(2px, 2px); }
.bot-acc.open .bot-acc-head { padding-bottom: 4px; }
.bot-acc-chev { margin-left: auto; display: grid; place-items: center; }
.bot-diffs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 4px 14px 14px; }
.bot-diffs .opt { min-height: 50px; }

/* ── F2: sticky deployment action bar ── */
/* The page is the scroller, so sticky pins the commit action + budget truth
   to the viewport bottom while the tray/presets scroll behind. */
.deploy-bar {
  position: sticky; bottom: 0; z-index: 6;
  display: flex; gap: 10px; align-items: center;
  margin-top: 10px;
  padding: 10px 0 max(10px, env(safe-area-inset-bottom));
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.deploy-bar .menu-big { flex: 1; min-height: 50px; }
.deploy-pts { flex-shrink: 0; font-size: 0.82rem; color: var(--ink-3); }
.deploy-pts.ready { color: var(--gold); }
body.lcd-theme .deploy-bar {
  background: var(--lcd-bg);
  border-top: 3px solid var(--lcd-ink);
}
body.lcd-theme .deploy-pts { font-family: 'VT323', monospace; font-size: 1.2rem; color: var(--lcd-dim); }
body.lcd-theme .deploy-pts.ready { color: var(--lcd-ink); }

/* ── P1 design-review fixes ── */

/* F5: campaign star legend + running total */
.star-legend {
  margin: 6px 0 0;
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
}
.star-legend .pic { margin: 0 1px; }
.star-total { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
body.lcd-theme .star-legend { font-family: 'Silkscreen', monospace; color: var(--lcd-dim); }

/* Restored (false positive in the dead-code sweep — renderCampaign uses it) */
.act-lock-note {
  margin: 0 0 8px;
  color: var(--ink-4);
  font-style: italic;
}
body.lcd-theme .act-lock-note { font-family: 'VT323', monospace; font-style: normal; font-size: 1.05rem; color: var(--lcd-dim); }

/* F6: quick-start summary + saved-default feedback */
.quick-start { display: flex; flex-direction: column; gap: 3px; align-items: center; }
.qs-title { display: inline-flex; align-items: center; gap: 8px; }
.qs-sub {
  font-family: 'VT323', monospace;
  font-size: 1.02rem; font-weight: 400;
  letter-spacing: 0.02em; opacity: 0.85;
}

/* F7: personality tagline inside the open bots-accordion row */
.bot-acc-tag {
  font-family: 'VT323', monospace;
  font-size: 1.05rem;
  color: var(--lcd-ink);
  padding: 0 14px 4px;
  line-height: 1.3;
}

/* F9: monochrome sweep — square ink plates instead of round circles,
   ink badge-tier states instead of bronze/silver/gold fills. */
body.lcd-theme .screen-icon {
  border-radius: 0;
  border: 2.5px solid var(--lcd-ink);
  background: transparent;
  box-shadow: none;
  color: var(--lcd-ink);
}
body.lcd-theme .screen-icon .icon { color: var(--lcd-ink); }
body.lcd-theme .badge-tier { border-radius: 0; border: 2px solid var(--lcd-ink); background: transparent; color: var(--lcd-ink); }
body.lcd-theme .badge-tier.bronze-earned { background: transparent; }
body.lcd-theme .badge-tier.silver-earned {
  background-image: repeating-linear-gradient(0deg, var(--lcd-ink) 0 1px, transparent 1px 3px);
  color: var(--lcd-ink);
}
body.lcd-theme .badge-tier.gold-earned { background: var(--lcd-ink); color: var(--lcd-bg); }
/* ── Battle report restage: beats 1 (splash) + 2/3 (report) ─────────────
Written with the generic tokens so Classic gets a sane look and the
body.lcd-theme remap does the LCD; LCD-specific weights/fonts below. */
/* Beat 1 — result splash: full-height card, zero scroll */
.game-over-card { --card-pad-x: 30px; }

.game-over-card.splash,
.game-over-card.report { padding-bottom: 0; }
.game-over-card.splash {
  display: flex; flex-direction: column;
  min-height: min(84vh, 720px);
  position: relative;      /* anchors the burst canvas */
  overflow: hidden;        /* burst pixels + word stamp clip to the card */
}
.splash-center {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  position: relative; z-index: 2;   /* above the burst canvas */
}
/* Full-card burst layer — the pixel king scatters across it. */
.splash-fx {
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
  image-rendering: pixelated;
}
/* Reserves the king's vertical space so the word/stars sit below it. */
.splash-king-space { width: 100%; height: clamp(150px, 30vh, 240px); }
/* Content the animation stamps in — hidden until its cue. */
.splash-fx-anim { opacity: 0; transform-origin: center; will-change: transform, opacity; }
@media (prefers-reduced-motion: reduce) { .splash-fx-anim { opacity: 1; } }

/* ── Desktop / wide-screen web layout (≥900px) ─────────────────────────
   The app is mobile-first; in a desktop browser the single column pushed
   the board below the fold. Wide screens get: a play screen with the board
   sized to FIT the viewport height on the left and everything else (plates,
   move history, controls, soft keys) in a right rail; and capped menu
   columns so home buttons aren't wall-to-wall. iPhone is untouched. */
@media (min-width: 900px) {
  .lcd-screen {
    display: grid;
    grid-template-columns: min(58vw, calc(100dvh - 170px)) minmax(300px, 380px);
    grid-auto-rows: max-content;
    justify-content: center;
    align-content: start;
    row-gap: 7px;
    column-gap: 28px;
  }
  .lcd-screen > .lcd-status { grid-column: 1 / -1; }
  /* The board owns column 1 (span generously; unused rows collapse). */
  .lcd-screen > .lcd-board-host { grid-column: 1; grid-row: 2 / span 14; }
  .lcd-screen > :not(.lcd-status, .lcd-board-host) { grid-column: 2; }

  /* Menus: a desktop window doesn't need phone-wide buttons. */
  .menu-screen { max-width: 460px; }
  .home-main { max-width: 380px; }
}
.rpt-chrome {
  font-family: 'Silkscreen', monospace;
  font-weight: 700; font-size: 0.95rem; letter-spacing: 0.2em;
  text-align: center; margin-bottom: 8px;
}
.shroud-kick { font-size: 0.66rem; letter-spacing: 0.16em; color: var(--ink-3); margin-bottom: 10px; }
.fall-king { margin: 6px 0 10px; transform: rotate(78deg); animation: rptTip 0.5s steps(3) 0.3s both; }
.fall-king .lcd-pc { width: 74px; height: 74px; display: block; }
.fall-glyph { font-size: 70px; line-height: 1; display: block; }
.fall-row { display: flex; align-items: center; gap: 14px; margin: 6px 0 10px; }
.fall-stand .lcd-pc { width: 60px; height: 60px; display: block; }
.draw-half { font-size: 42px; font-weight: 700; }
@keyframes rptTip { from { transform: rotate(0deg); } }
.no-anim .fall-king { animation: none; }
.vword { font-size: 2.4rem; letter-spacing: 0.1em; margin: 0 0 6px; }
.vsub { font-size: 1rem; margin: 0; max-width: 300px; line-height: 1.3; }
.star-row { display: flex; gap: 12px; margin: 24px 0 6px; }
.big-star { display: block; animation: rptStamp 0.3s steps(2) both; }
.big-star.d2 { animation-delay: 0.55s; }
.big-star.d3 { animation-delay: 0.8s; }
@keyframes rptStamp { from { transform: scale(2.4); opacity: 0; } }
.no-anim .big-star { animation: none; }
.star-cap { font-size: 0.6rem; letter-spacing: 0.12em; color: var(--ink-3); margin-top: 2px; }
.unlock-strip {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 9px 12px; margin-top: 16px;
  width: 100%; box-sizing: border-box; text-align: left;
}
.unlock-strip + .unlock-strip { margin-top: 8px; }
.unlock-piece { width: 34px; height: 34px; flex-shrink: 0; display: grid; place-items: center; }
.unlock-piece .lcd-pc, .unlock-piece .tray-piece { width: 32px; height: 32px; }
.unlock-piece .badge-pic { color: var(--lcd-ink); }
.unlock-kick { font-size: 0.6rem; letter-spacing: 0.12em; display: block; color: var(--gold); }
.unlock-sub { font-size: 0.9rem; color: var(--ink-2); line-height: 1.25; }

/* Soft-key pairs: splash exits + the sticky report footer (F4) */
.report-cta {
  position: sticky; bottom: 0; z-index: 3;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin: 16px calc(-1 * var(--card-pad-x)) 0;
  padding: 12px var(--card-pad-x) calc(12px + env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--line);
}
.rpt-key {
  min-height: 50px; font-size: 0.88rem; letter-spacing: 0.05em;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.rpt-key.dark.dark { background: var(--lcd-fill, var(--gold)); color: var(--lcd-bg, #1a1410); }

/* Beat 2 — the report: framed sections in story order */
.rpt-strip {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 6px 8px; margin-top: 4px;
  display: flex; justify-content: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.95rem;
}
.rpt-dot { color: var(--ink-4); }
.rpt-frame {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 8px 10px 9px; margin-top: 10px;
  text-align: left; width: 100%; box-sizing: border-box;
  background: none; display: block; color: inherit;
}
button.rpt-frame { cursor: pointer; box-shadow: none; transform: none; }
.rpt-kick { font-size: 0.6rem; letter-spacing: 0.14em; display: block; margin-bottom: 5px; color: var(--ink-3); font-weight: 700; }
.rpt-crow { display: flex; align-items: center; gap: 9px; font-size: 0.95rem; padding: 3px 0; }
.rpt-crow .pic { flex-shrink: 0; }
.rpt-crow.miss { color: var(--ink-3); }
.rpt-body { font-size: 0.95rem; line-height: 1.35; }
.rpt-note { font-size: 0.85rem; color: var(--ink-3); margin-top: 5px; }
.report-dot-label { font-size: 15px; fill: var(--ink-2); }

/* Engine-review CTA (two-line, dark) */
.rpt-cta {
  margin-top: 10px; width: 100%; min-height: 56px;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
  padding: 9px 14px; gap: 3px; text-align: left; box-sizing: border-box;
  background: var(--gold); color: #1a1410; border: 1px solid var(--line);
  border-radius: var(--radius-sm); cursor: pointer;
}
.rpt-cta-t { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.06em; display: flex; align-items: center; gap: 8px; width: 100%; }
.rpt-cta-chev { margin-left: auto; display: inline-flex; }
.rpt-cta-s { font-size: 0.8rem; opacity: 0.85; font-weight: 400; }

/* Beat 2½ — segmented analysis progress (countable, very Game Boy) */
.seg-bar { display: flex; gap: 3px; margin: 7px 0 4px; }
.seg { flex: 1; height: 14px; border: 2px solid var(--ink-3); }
.seg.on { background: var(--ink-3); }
.seg.blink { animation: segBlink 0.6s steps(1) infinite; }
@keyframes segBlink { 50% { background: var(--ink-3); } }

/* Beat 3 — verdict: accuracy hero plates + tally table */
.acc-row { display: flex; gap: 10px; margin-top: 10px; }
.acc-plate {
  flex: 1; border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 8px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.acc-num { font-size: 3.2rem; line-height: 0.9; font-weight: 700; }
.acc-who { font-size: 0.6rem; letter-spacing: 0.1em; font-weight: 700; }
.acc-sub { font-size: 0.72rem; color: var(--ink-3); }
.vrow { display: grid; grid-template-columns: 34px 1fr 38px 38px; gap: 6px; align-items: center; font-size: 0.95rem; padding: 1.5px 0; }
.vg { font-weight: 700; font-size: 0.8rem; }
.vc { text-align: right; }
.vc.dim { color: var(--ink-4); }
.vhead { font-size: 0.56rem; letter-spacing: 0.08em; color: var(--ink-3); text-align: right; }

/* Beat 4 — walkthrough plate: kicker, VT323 body, progress pips */
.wt-kick { font-size: 0.6rem; letter-spacing: 0.12em; font-weight: 700; color: var(--ink-3); flex: 1; text-align: left; }
.wt-x {
  width: 26px; height: 26px; flex-shrink: 0;
  display: grid; place-items: center;
  padding: 0; min-height: 0; font-size: 0.72rem;
  border: 1px solid var(--line); background: none; color: inherit; cursor: pointer;
}
.wt-pips { display: flex; gap: 5px; margin-top: 7px; }
.wt-pip { width: 12px; height: 12px; border: 2px solid var(--ink-3); }
.wt-pip.on { background: var(--ink-3); }

/* LCD variants: chunkier ink frames, pixel/terminal type */
body.lcd-theme .rpt-strip,
body.lcd-theme .rpt-frame,
body.lcd-theme .unlock-strip,
body.lcd-theme .acc-plate { border-width: 2.5px; }
body.lcd-theme .rpt-strip,
body.lcd-theme .rpt-crow,
body.lcd-theme .rpt-body,
body.lcd-theme .rpt-note,
body.lcd-theme .unlock-sub,
body.lcd-theme .vsub,
body.lcd-theme .vrow { font-family: 'VT323', monospace; }
body.lcd-theme .rpt-strip { font-size: 1.1rem; }
body.lcd-theme .rpt-crow, body.lcd-theme .rpt-body { font-size: 1.08rem; }
body.lcd-theme .rpt-note, body.lcd-theme .unlock-sub { font-size: 1.02rem; }
body.lcd-theme .vsub { font-size: 1.15rem; }
body.lcd-theme .vrow { font-size: 1.1rem; }
body.lcd-theme .rpt-kick,
body.lcd-theme .unlock-kick,
body.lcd-theme .star-cap,
body.lcd-theme .shroud-kick,
body.lcd-theme .acc-who,
body.lcd-theme .vhead,
body.lcd-theme .vg,
body.lcd-theme .wt-kick,
body.lcd-theme .rpt-cta-t,
body.lcd-theme .rpt-key { font-family: 'Silkscreen', monospace; }
body.lcd-theme .acc-num { font-family: 'VT323', monospace; font-size: 3.6rem; font-weight: 400; }
body.lcd-theme .acc-sub { font-family: 'VT323', monospace; font-size: 0.95rem; }
body.lcd-theme .vword { font-family: 'Silkscreen', monospace; }
body.lcd-theme .rpt-cta { background: var(--lcd-fill); color: var(--lcd-on-fill, var(--lcd-bg)); border: none; }
body.lcd-theme .rpt-cta-s { font-family: 'VT323', monospace; font-size: 1rem; }
body.lcd-theme .seg { border-color: var(--lcd-ink); }
body.lcd-theme .seg.on { background: var(--lcd-ink); }
body.lcd-theme .seg.blink { animation: segBlinkLcd 0.6s steps(1) infinite; }
@keyframes segBlinkLcd { 50% { background: var(--lcd-ink); } }
body.lcd-theme .wt-pip { border-color: var(--lcd-ink); }
body.lcd-theme .wt-pip.on { background: var(--lcd-ink); }
body.lcd-theme .wt-x { border: 2px solid var(--lcd-ink); }
body.lcd-theme .wt-verdict { color: var(--lcd-ink); border-color: var(--lcd-ink); }
body.lcd-theme .report-dot-label { font-family: 'VT323', monospace; fill: var(--lcd-ink); }
body.lcd-theme .lcd-soft.dark { background: var(--lcd-fill); color: var(--lcd-on-fill, var(--lcd-bg)); }
@media (max-width: 700px) {
  .game-over-card { --card-pad-x: 16px; }
}

/* ════════════════════════════════════════════════════════════════════
   LCD MOTION — the motion vocabulary (design workstream 3).
   Rules: steps() only, never ease. Feedback ≤ 300ms; loops are for
   waiting states only. Ink or nothing. One-shot animations are gated by
   state flags consumed on first render. Tile numbers match the sampler.
   ════════════════════════════════════════════════════════════════════ */

/* 02 — capture: square inverts for one frame, the capturer flickers in
   through 3 stepped frames (LCD ghosting, like dying sprites). */
body.lcd-theme .square.just-captured { animation: capFlash 320ms steps(1) both; }
body.lcd-theme .square.just-captured .lcd-pc,
body.lcd-theme .square.just-captured .piece { animation: capDissolve 320ms steps(3) both; }
@keyframes capFlash {
  /* Starts transparent so a stalled frame 0 shows a normal square (iOS
     can suspend animations mid-flight; the pump usually prevents it). */
  0%, 8% { background-color: transparent; }
  9%, 24% { background-color: var(--lcd-ink); }
  25%, 100% { background-color: transparent; }
}
@keyframes capDissolve { from { opacity: 0; } }

/* 03 — screen wipe between menus: 8 chunky columns over a snapshot. */
.wipe-under {
  position: fixed; inset: 0; z-index: 1;
  overflow: hidden; pointer-events: none;
  background: var(--bg);
}
main.app.wipe-in {
  position: relative; z-index: 2;
  animation: screenWipe 260ms steps(8) both;
  background: var(--bg);
}
@keyframes screenWipe {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

/* 04 — boot type-in: the wordmark types on with a block cursor, once per
   session. The "power on" moment. */
.boot-type {
  display: inline-block; overflow: hidden;
  white-space: nowrap; vertical-align: bottom;
  animation: bootType 1s steps(6) both;
}
@keyframes bootType { from { max-width: 0; } to { max-width: 8em; } }
.boot-cursor {
  display: inline-block; width: 0.45em; height: 0.9em;
  margin-left: 6px; background: var(--lcd-ink);
  vertical-align: bottom;
  animation: bootCursor 2.4s steps(1) both;
}
@keyframes bootCursor {
  0%, 16% { opacity: 1; } 17%, 33% { opacity: 0; }
  34%, 50% { opacity: 1; } 51%, 67% { opacity: 0; }
  68%, 84% { opacity: 1; } 85%, 100% { opacity: 0; }
}

/* 05 — thinking orbit: eight ink pixels chase around a square while the
   bot thinks. Zero layout cost, loops only while waiting. */
.orb { position: relative; display: inline-block; width: 18px; height: 18px; vertical-align: -4px; margin-left: 4px; }
.orb .od { position: absolute; width: 4px; height: 4px; background: var(--lcd-ink); animation: orbPulse 1.28s steps(1) infinite; }
.orb .od:nth-child(1) { top: 0; left: 7px; }
.orb .od:nth-child(2) { top: 2px; left: 12px; animation-delay: 0.16s; }
.orb .od:nth-child(3) { top: 7px; right: 0; animation-delay: 0.32s; }
.orb .od:nth-child(4) { bottom: 2px; left: 12px; animation-delay: 0.48s; }
.orb .od:nth-child(5) { bottom: 0; left: 7px; animation-delay: 0.64s; }
.orb .od:nth-child(6) { bottom: 2px; left: 2px; animation-delay: 0.8s; }
.orb .od:nth-child(7) { top: 7px; left: 0; animation-delay: 0.96s; }
.orb .od:nth-child(8) { top: 2px; left: 2px; animation-delay: 1.12s; }
@keyframes orbPulse { 0% { opacity: 1; } 12.5% { opacity: 0.2; } 100% { opacity: 0.2; } }

/* 06 — confirm blink: committing buttons blink the inversion twice, then
   hold inverted while the action executes (main.js delays ~280ms). */
body.lcd-theme .confirm-blink { animation: confirmBlink 280ms steps(1) both !important; }
@keyframes confirmBlink {
  0%, 24% { background: var(--lcd-ink); color: var(--lcd-bg); }
  25%, 49% { background: var(--lcd-bg); color: var(--lcd-ink); }
  50%, 100% { background: var(--lcd-ink); color: var(--lcd-bg); }
}

/* 07 — stepped marquee: long waiting lines ticker through the turn line
   one character-width at a time. Loops only while waiting. */
.lcd-marquee { display: block; overflow: hidden; }
.lcd-marquee-in {
  display: inline-block; white-space: nowrap;
  padding-left: 100%;
  animation: lcdTick 7s steps(35) infinite;
}
@keyframes lcdTick { to { transform: translateX(-100%); } }

/* 08 — lock-in scan: an ink bar sweeps the player's three ranks top to
   bottom — the machine reading the army. One-shot, on lock + preset save. */
body.lcd-theme .board { position: relative; }
body.lcd-theme .board.lock-scan::after {
  content: ""; position: absolute; left: 0; right: 0; height: 12.5%;
  background: var(--lcd-ink); opacity: 0.85; pointer-events: none;
  animation: lockScan 420ms steps(1) both;
}
@keyframes lockScan {
  0% { top: 62.5%; opacity: 0.85; }
  33% { top: 75%; }
  66% { top: 87.5%; }
  100% { top: 87.5%; opacity: 0; }
}

/* 09 — dither fog reveal: squares entering vision dissolve solid →
   checker → clear; squares leaving reverse it. Overlay spans injected
   only on squares whose visibility just changed. */
.square { position: relative; }
.fog-anim { position: absolute; inset: 0; pointer-events: none; }
.fog-anim.solid { background: var(--lcd-void); animation: fogSolidIn 240ms steps(1) both; }
.fog-anim.checker {
  background: repeating-conic-gradient(var(--lcd-void) 0% 25%, transparent 0% 50%);
  background-size: 10px 10px;
  animation: fogCheckerIn 240ms steps(1) both;
}
@keyframes fogSolidIn { 0% { opacity: 1; } 40%, 100% { opacity: 0; } }
@keyframes fogCheckerIn { 0%, 40% { opacity: 1; } 75%, 100% { opacity: 0; } }
.fog-anim.solid.out { animation: fogSolidOut 240ms steps(1) both; }
.fog-anim.checker.out { animation: fogCheckerOut 240ms steps(1) both; }
@keyframes fogSolidOut { 0%, 60% { opacity: 0; } 61%, 100% { opacity: 1; } }
@keyframes fogCheckerOut { 0%, 25% { opacity: 0; } 26%, 100% { opacity: 1; } }

/* 10 — pixel-latency ghosting: released buttons decay through stepped
   residue frames instead of snapping back — slow LCD pixels. */
body.lcd-theme button:not(.square):not(.preset-clear-btn) { position: relative; }
body.lcd-theme button:not(.square):not(.preset-clear-btn)::after {
  content: ""; position: absolute; inset: 0;
  background: var(--lcd-ink); opacity: 0; pointer-events: none;
  transition: opacity 350ms steps(3, start);
}
body.lcd-theme button:not(.square):not(.preset-clear-btn):active::after {
  opacity: 0.25; transition: none;
}

/* F12 — reveal stagger: pieces boot up diagonally across the board in
   under a second (steps(3), per-square inline delay). */
body.lcd-theme .piece-in { animation: pieceIn 220ms steps(3) both; }
@keyframes pieceIn { from { opacity: 0; transform: scale(0.5); } }

/* Accessibility: one query kills all of it. */
@media (prefers-reduced-motion: reduce) {
  body.lcd-theme *, body.lcd-theme *::before, body.lcd-theme *::after,
  .lcd-screen *, .lcd-screen *::before, .lcd-screen *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* King sprite standing in for the crown icon inside buttons (LCD) */
.btn-sprite { width: 22px; height: 22px; display: inline-grid; place-items: center; margin-right: 8px; flex-shrink: 0; }
.btn-sprite .lcd-pc { width: 100%; height: 100%; }

/* ── Appearance: theme swatch picker ── */
.theme-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 8px; }
.theme-swatch {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 12px 8px; cursor: pointer;
}
.theme-chip {
  width: 100%; height: 62px; position: relative; overflow: hidden;
  border: 2px solid var(--lcd-ink);
  background-image: repeating-linear-gradient(0deg, rgba(0,0,0,0.10) 0 1px, transparent 1px 3px);
}
.theme-chip-sq { position: absolute; left: 0; top: 0; width: 40%; height: 100%;
  background-image: repeating-linear-gradient(0deg, rgba(0,0,0,0.35) 0 1px, transparent 1px 3px); }
.theme-chip-dot { position: absolute; right: 22%; top: 50%; width: 16px; height: 16px;
  border-radius: 1px; transform: translateY(-50%); }
.theme-chip-fill { position: absolute; right: 8px; bottom: 8px; width: 22px; height: 10px; }
.theme-name { font-family: 'Silkscreen', monospace; font-size: 0.7rem; letter-spacing: 0.06em; color: var(--lcd-ink); }
body.lcd-theme .theme-swatch.on {
  --pc: 4px;
  box-shadow: inset 0 0 0 3px var(--lcd-ink);
  filter: drop-shadow(3px 3px 0 var(--lcd-ink));
}
body.lcd-theme .theme-swatch.on .theme-name { color: var(--lcd-ink); }

/* ── Colourways Pack: locked swatches + upsell shop ── */
/* Locked swatches stay FULL vibrancy — we're selling the colour, so show
   the colour. Only a small corner padlock marks the lock. */
.theme-lock {
  position: absolute; right: 3px; top: 3px;
  display: grid; place-items: center;
  background: rgba(0,0,0,0.55); color: #fff;
  padding: 2px;
}
.theme-lock .pic { width: 14px; height: 14px; }
.shop-trying {
  font-family: 'Silkscreen', monospace; font-size: 0.72rem;
  letter-spacing: 0.14em; color: var(--lcd-dim); margin: 6px 0 0;
}
.shop-chip.on { outline: 2px solid var(--lcd-ink); outline-offset: 1px; }

.shop-overlay {
  position: fixed; inset: 0; z-index: 1100;
  display: grid; place-items: center;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
  background: rgba(10,14,10,0.9);
  animation: overlayIn 200ms ease;
}
.shop-card {
  width: min(420px, 100%);
  padding: 30px 22px 22px;
  background: var(--lcd-bg); color: var(--lcd-ink);
  border: 3px solid var(--lcd-ink);
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center; position: relative;
}
.shop-close { position: absolute; left: 8px; top: 8px; }
.shop-lede { font-family: 'VT323', monospace; font-size: 1.1rem; margin: 0; line-height: 1.3; max-width: 30ch; }
.shop-swatches { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 6px 0 10px; }
.shop-chip {
  width: 40px; height: 28px; position: relative;
  border: 2px solid var(--lcd-ink);
  background-image: repeating-linear-gradient(0deg, rgba(0,0,0,0.10) 0 1px, transparent 1px 3px);
}
.shop-chip .theme-chip-dot { position: absolute; right: 6px; top: 50%; width: 10px; height: 10px; transform: translateY(-50%); border-radius: 1px; }
.shop-card .menu-big { width: 100%; }
