:root {
  /* Light theme — "case-file paper" (RESTYLE-PLAN.md). Clean near-white base,
     yellow + terracotta accents in the chrome. Dark "noir" overrides below. */
  --ink: #26221c;       /* warm near-black — titles, headings, body */
  --coal: #2c2721;      /* dark bands (stay dark in both themes) */
  --muted: #6b6353;     /* secondary copy */
  --paper: #faf8f2;     /* page background — warm off-white */
  --sheet: #fcf8ee;     /* cream — text on dark bands */
  --panel: rgba(255, 253, 246, 0.96); /* case sheets / cards */
  --field: #fffdf7;     /* inputs, letter slots */
  --line: #e3dcc8;      /* hairline borders */
  --accent: #cf7a55;    /* soft terracotta — the action color (red read too aggressive) */
  --accent-deep: #b35f3d;
  --accent-ink: #3b1d0e; /* text on terracotta — dark like the chip pattern (AA) */
  --yellow: #f5b51c;    /* cover yellow — chips, badges, highlights */
  --yellow-soft: #fbdf8a;
  --yellow-ink: #5a430c; /* text on yellow chips */
  --moss: #38322b;      /* found-word done state */
  --brick: var(--accent); /* legacy accent name */
  --gold: #ecca80;      /* soft gold — grid selection, small accents */
  --blue: #26221c;      /* secondary accent → ink in light, yellow in dark */
  --teal: var(--accent);
  --wash: rgba(65, 83, 70, 0.08); /* faint fills (word chips etc.) */
  --cell: #fffdf6;      /* grid letter blocks — flip with the theme */
  --cell-line: #e3d9bf;
  --cell-ink: #38322b;
  --cell-hover: rgba(211, 165, 72, 0.28);
  --shadow: 0 14px 30px rgba(58, 40, 12, 0.10);
  --soft-shadow: 0 8px 18px rgba(58, 40, 12, 0.08);

  --font-display: "Black Ops One", Impact, "Arial Black", sans-serif;
  --font-mono: "Courier Prime", "Courier New", monospace;
  --font-body: Georgia, "Times New Roman", serif;
}

[data-theme="dark"] {
  /* Noir — the cover inverted: charcoal field, yellow type, terracotta action. */
  --ink: #f3ead6;
  --muted: #b3a78f;
  --paper: #211d18;
  --panel: #2c2721;
  --field: #1b1813;
  --line: #4a4234;
  --accent: #d98a63;
  --accent-deep: #c06f47;
  --accent-ink: #321608;
  --yellow-soft: #5a4a1d;
  --yellow-ink: #f5c95e;
  --blue: #f5b51c;
  --wash: rgba(252, 248, 238, 0.08);
  --cell: #2e2922;
  --cell-line: #453d30;
  --cell-ink: #ece2c8;
  --cell-hover: rgba(245, 181, 28, 0.22);
  --shadow: 0 14px 30px rgba(0, 0, 0, 0.45);
  --soft-shadow: 0 8px 18px rgba(0, 0, 0, 0.35);
}

/* The hidden attribute must beat class-level display rules (e.g. .streak-pill,
   .login-signed-in set display, which would otherwise override [hidden]). */
[hidden] { display: none !important; }

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  color: var(--ink);
  background: var(--paper);
  font-family: var(--font-body);
  overflow-x: hidden;
}

button,
input {
  font: inherit;
}

a {
  color: inherit;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 70px;
  padding: 12px clamp(18px, 4vw, 48px);
  background: var(--paper); /* fallback for browsers without color-mix (older iOS) */
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  border-bottom: 1px solid var(--line);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

/* Without backdrop-filter (older browsers, some in-app webviews) the 92%
   header would let scrolling content bleed through. Fall back to an opaque bar
   so the header always reads cleanly. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .site-header {
    background: var(--paper);
  }
}

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  color: var(--ink);
  background: var(--field);
  border: 1.5px solid var(--line);
  border-radius: 11px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.menu-toggle:hover {
  background: rgba(207, 122, 85, 0.16);
}

.menu-bars {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  width: 18px;
}

.menu-bars span {
  height: 2px;
  width: 100%;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.menu-toggle[aria-expanded="true"] .menu-bars span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.menu-toggle[aria-expanded="true"] .menu-bars span:nth-child(2) {
  opacity: 0;
}
.menu-toggle[aria-expanded="true"] .menu-bars span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.menu-panel {
  position: absolute;
  top: 100%;
  right: clamp(18px, 4vw, 48px);
  display: none;
  flex-direction: column;
  min-width: 210px;
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
}

.menu-panel.open {
  display: flex;
  animation: panel-drop 170ms ease-out;
}

@keyframes panel-drop {
  from {
    opacity: 0;
    transform: translateY(-7px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.menu-panel a,
.menu-panel button {
  margin: 0;
  padding: 13px 18px;
  text-align: left;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

.menu-panel a:last-child,
.menu-panel button:last-child {
  border-bottom: 0;
}

.menu-panel a:hover,
.menu-panel button:hover {
  background: rgba(207, 122, 85, 0.14);
}

/* Archive popup */
.archive-dialog {
  width: min(94vw, 560px);
  padding: 0;
  border: 2px solid var(--ink);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.archive-dialog[open] {
  animation: dialog-rise 210ms cubic-bezier(0.2, 1.1, 0.35, 1);
}

.archive-dialog::backdrop {
  background: rgba(40, 34, 27, 0.55);
  animation: backdrop-fade 210ms ease;
}

@keyframes dialog-rise {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes backdrop-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.archive-dialog-inner {
  position: relative;
  padding: clamp(22px, 4vw, 36px);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
  font-weight: 700;
}

.brand span {
  display: grid;
  gap: 2px;
}

.brand strong {
  font-size: 1rem;
  line-height: 1;
}

.brand small,
nav,
.eyebrow,
.primary-button,
.ghost-button,
.icon-button,
.primary-link,
.text-link,
.case-meta,
dt,
.status-line,
.toolbar-value,
.word-list,
.clue-box p,
label,
.form-note,
.stamp {
  font-family: var(--font-mono);
}

.brand small {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1;
  text-transform: uppercase;
}

.brand-mark {
  width: 36px;
  height: 36px;
  object-fit: contain;
}

/* Header mark — a mini-cover: the detective silhouette in a terracotta block. */
.brand-glyph {
  display: grid;
  place-items: end center;
  flex: none;
  width: 36px;
  height: 42px;
  overflow: hidden;
  background: var(--brick);
  border: 1.5px solid var(--ink);
  box-shadow: 2px 2px 0 var(--ink);
}

.brand-glyph img {
  width: 92%;
  height: auto;
  align-self: end;
}

nav {
  display: flex;
  gap: 18px;
  font-size: 0.9rem;
  font-weight: 700;
}

nav a {
  color: var(--muted);
  text-decoration: none;
}

nav a:hover {
  color: var(--ink);
}

main {
  min-height: 100vh;
  min-height: 100dvh; /* iOS Safari counts the toolbar area in 100vh; dvh is the visible height */
}

#daily,
#casebook,
#readers {
  scroll-margin-top: 86px;
}





.daily-shell > *,
.reader-band > * {
  min-width: 0;
}

.eyebrow {
  margin: 0 0 10px;
  color: var(--accent);
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  line-height: 1.35;
  text-transform: uppercase;
}

/* Eyebrows are yellow highlight chips — the cover yellow's home on the clean base. */
.eyebrow {
  display: inline-block;
  padding: 3px 9px;
  color: var(--yellow-ink);
  background: var(--yellow-soft);
  border-radius: 4px;
}

/* Case chip + date sit side by side; only the case number gets the yellow box. */
.case-tag {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  margin: 0 0 10px;
  font-family: var(--font-mono);
}

.case-tag .eyebrow {
  margin: 0;
}

.case-date {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  overflow-wrap: anywhere;
}

h1,
h2 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}



h1 {
  margin: 0;
  max-width: 16ch;
  font-size: clamp(2.5rem, 5.4vw, 5rem);
  line-height: 0.98;
  letter-spacing: 0;
  overflow-wrap: normal;
}

h2 {
  margin: 0 0 14px;
  font-size: clamp(1.55rem, 3vw, 3rem);
  line-height: 1;
  letter-spacing: 0;
}

h3 {
  margin: 0 0 8px;
  font-size: 1.05rem;
}



.case-copy,
.book-copy p,
.reader-copy p,
.steps p,
.account-card p,
.form-note,
.status-line {
  color: var(--muted);
  line-height: 1.55;
}



.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.primary-link,
.text-link {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  text-decoration: none;
  font-weight: 800;
}

.primary-link {
  padding: 0 18px;
  color: var(--accent-ink);
  background: var(--accent);
  border: 1px solid var(--accent-deep);
}

.text-link {
  color: var(--blue);
}







.daily-shell {
  display: grid;
  grid-template-columns: minmax(260px, 0.9fr) minmax(360px, 1.15fr) minmax(280px, 0.86fr);
  gap: 18px;
  align-items: start;
  padding: 24px clamp(18px, 4vw, 48px) clamp(42px, 6vw, 76px);
}

.case-panel,
.puzzle-panel,
.word-panel,
.signup-form,
.account-card {
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.case-panel,
.puzzle-panel,
.word-panel {
  padding: clamp(18px, 2.4vw, 30px);
}

.case-panel {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  border-left: 7px solid var(--brick);
}

.case-panel h2 {
  max-width: 14ch;
  font-size: clamp(1.7rem, 2.8vw, 2.8rem);
  line-height: 1;
}

.case-copy {
  margin: 10px 0 14px;
  font-size: 0.98rem;
}

.case-meta {
  margin-bottom: 20px;
  color: var(--blue);
  font-size: 0.82rem;
  font-weight: 800;
  line-height: 1.45;
  text-transform: uppercase;
}

.case-facts {
  display: grid;
  gap: 8px;
  margin: 0 0 24px;
}

.case-facts div {
  display: grid;
  grid-template-columns: 116px 1fr;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

dt {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 800;
  text-transform: uppercase;
}

dd {
  margin: 0;
  font-weight: 800;
}

.case-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.primary-button,
.secondary-button,
.ghost-button,
.icon-button {
  min-height: 44px;
  border: 1px solid var(--ink);
  cursor: pointer;
  font-weight: 800;
}

.primary-button {
  padding: 0 18px;
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent-deep);
  transition: background 0.15s ease, transform 0.12s ease;
}

.primary-button:hover,
.primary-link:hover {
  background: var(--accent-deep);
}

.primary-button:hover {
  transform: translateY(-1px);
}

.primary-button:active {
  transform: translateY(0);
}

.secondary-button {
  padding: 0 14px;
  color: var(--ink);
  background: var(--sheet);
}

.secondary-button:hover {
  background: rgba(211, 165, 72, 0.22);
}

.ghost-button {
  padding: 0 16px;
  color: var(--ink);
  background: transparent;
}

.ghost-button:hover {
  background: rgba(49, 93, 115, 0.08);
}

.icon-button {
  width: 44px;
  color: var(--ink);
  background: var(--field);
  border-color: var(--line);
  font-size: 1.3rem;
}

.btn-icon {
  vertical-align: -3px;
  margin-right: 7px;
}

.status-line {
  min-height: 3.2em;
  margin: 18px 0 0;
  font-size: 0.92rem;
}

.puzzle-panel {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 16px;
}

.puzzle-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

/* Lone counter above the grid — no label, just the ticker. */
.puzzle-toolbar {
  /* Counter left, overflow menu right — the menu sits ABOVE the grid so a
     called tip's glow is on screen (mobile users were scrolled past it). */
  justify-content: space-between;
}

.toolbar-value {
  margin: 0;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 800;
}

#foundCount {
  display: inline-block;
  color: var(--ink);
}

#foundCount.tick {
  animation: count-tick 240ms ease;
}

@keyframes count-tick {
  from {
    transform: translateY(0.45em);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.grid-wrap {
  position: relative;
  display: grid;
  place-items: center;
}

/* "CASE CLOSED" rubber stamp — slams onto the grid on solve. */
.case-stamp {
  position: absolute;
  inset: 0;
  display: none;
  place-items: center;
  pointer-events: none;
  z-index: 2;
}

.case-solved .case-stamp {
  display: grid;
}

.case-stamp span {
  padding: 14px 26px;
  border: 5px solid #a83a2a;
  border-radius: 8px;
  color: #a83a2a;
  background:
    radial-gradient(ellipse at 30% 40%, rgba(168, 58, 42, 0.06), transparent 60%),
    rgba(252, 248, 238, 0.6);
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4.6vw, 2.5rem);
  line-height: 1.04;
  letter-spacing: 0.12em;
  text-align: center;
  text-transform: uppercase;
  transform: rotate(-11deg);
  mix-blend-mode: multiply;
  box-shadow: 0 0 0 2px rgba(168, 58, 42, 0.25) inset;
  animation: stamp-slam 420ms cubic-bezier(0.2, 1.6, 0.35, 1) both;
}

@keyframes stamp-slam {
  0% {
    opacity: 0;
    transform: rotate(-11deg) scale(2.4);
  }
  60% {
    opacity: 1;
    transform: rotate(-11deg) scale(0.94);
  }
  100% {
    opacity: 1;
    transform: rotate(-11deg) scale(1);
  }
}

.letter-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(22px, 1fr));
  width: min(100%, 540px);
  aspect-ratio: 1;
  /* Discrete rounded letter blocks with small gutters — no outer frame. */
  gap: clamp(3px, 0.8cqw, 6px);
  background: transparent;
  /* Container so the letter size can be a fixed % of the grid (cell) width. */
  container-type: inline-size;
  /* Anchor for the found-word snake overlay. */
  position: relative;
}

/* Skeleton while puzzle-data.json loads: faint cell ruling + a passing sheen.
   The grid keeps its aspect-ratio box while :empty, so this paints full-size. */
.letter-grid:empty {
  background:
    linear-gradient(110deg, transparent 42%, var(--cell-hover) 50%, transparent 58%),
    var(--cell);
  border: 1px solid var(--cell-line);
  border-radius: 12px;
  background-size: 240% 100%, auto;
  background-position: 200% 0, 0 0;
  animation: grid-shimmer 1.3s ease-in-out infinite;
}

@keyframes grid-shimmer {
  to {
    background-position: -140% 0, 0 0;
  }
}

/* Rounded "snake" capsules for found words (and the live selection pill).
   The overlay is the grid's first positioned child, so cells — and their
   letters and borders — paint on top of it. */
.snake-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /* The cells are opaque rounded blocks now, so the capsules paint on top of
     them and rely on blending to keep the letters readable. The z-index makes
     the svg its own stacking context, which isolates the per-line blending —
     so the svg itself must carry the blend against the cells below. */
  z-index: 1;
  mix-blend-mode: multiply;
}

[data-theme="dark"] .snake-overlay {
  /* Dimmed so the pills read as a glow under the cream letters instead of
     washing them out — screen at full pastel strength is too hot. */
  mix-blend-mode: screen;
  opacity: 0.48;
}

.snake-overlay line {
  /* Multiply keeps dark letters dark under the pastel pills, and overlapping
     pills blend where words cross, so a shared (crossing) letter visibly
     carries every covering word's color. */
  mix-blend-mode: multiply;
}

[data-theme="dark"] .snake-overlay line {
  /* Screen is multiply's dual on the dark blocks: cream letters stay bright,
     the block lightens to the word's pastel, overlaps still compound. */
  mix-blend-mode: screen;
}

.snake-overlay line.snake-grow {
  /* pathLength=1 is set in app.js, so the dash math is unit-free. */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: snake-grow 320ms ease-out forwards;
}

@keyframes snake-grow {
  to {
    stroke-dashoffset: 0;
  }
}

.cell {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  border: 1px solid var(--cell-line);
  border-radius: clamp(5px, 1.4cqw, 9px);
  color: var(--cell-ink);
  background: var(--cell);
  transition: background 0.12s ease, transform 0.1s ease;
  font-family: var(--font-mono);
  /* Letter is ~52% of cell width on every screen: 100cqw / cols = cell width.
     Clamp guards the extremes; mobile cells are large, so letters scale up. */
  font-size: clamp(0.9rem, calc(52cqw / var(--cols, 8)), 1.6rem);
  font-weight: 900;
  user-select: none;
}

/* Circle the crossing (evidence) letters once a covering word is found. */
.cell.crossing::after {
  content: "";
  position: absolute;
  inset: 9%;
  border: 2px solid rgba(56, 50, 43, 0.85);
  border-radius: 50%;
  pointer-events: none;
}

[data-theme="dark"] .cell.crossing::after {
  border-color: rgba(252, 248, 238, 0.8);
}

.cell:hover {
  /* Tint ON TOP of the opaque block (a bare translucent bg would let the dark
     page show through), and no z-index lift — the cell must stay under the
     blended snake capsules. */
  background-color: var(--cell);
  background-image: linear-gradient(var(--cell-hover), var(--cell-hover));
  transform: scale(1.07);
}

.cell:active {
  transform: scale(0.94);
}

.cell:focus-visible {
  outline: 3px solid var(--accent-deep);
  outline-offset: 1px;
  z-index: 1;
}

.cell.selected,
.cell.found {
  /* Word/selection color comes from the snake-overlay capsule blended on top. */
  background: var(--cell);
}

.evidence-entry {
  display: grid;
  gap: 10px;
}

/* ── Letter-slot evidence input ───────────────────────────────────────────── */
.evidence-slots {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.evidence-slots .slot {
  width: clamp(34px, 9vw, 46px);
  height: clamp(40px, 10.5vw, 52px);
  min-height: 0;
  padding: 0;
  text-align: center;
  color: var(--ink);
  background: var(--field);
  border: 1.5px solid var(--line);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: clamp(1.05rem, 4vw, 1.35rem);
  font-weight: 900;
  text-transform: uppercase;
  caret-color: var(--brick);
  transition: border-color 0.12s ease, background 0.12s ease, transform 0.12s ease;
}

.evidence-slots .slot:focus {
  border-color: var(--ink);
  outline: 2px solid rgba(226, 60, 28, 0.45);
  outline-offset: 1px;
}

.evidence-slots .slot.filled {
  border-color: var(--ink);
  background: rgba(236, 202, 128, 0.22);
  animation: slot-pop 170ms ease;
}

@keyframes slot-pop {
  0% {
    transform: scale(0.85);
  }
  60% {
    transform: scale(1.09);
  }
  100% {
    transform: scale(1);
  }
}

.evidence-slots .slot:disabled {
  color: var(--muted);
  background: var(--wash);
  border-style: dashed;
}

.evidence-slots .slot-gap {
  width: 12px;
  flex: none;
}

.evidence-slots.shake {
  animation: inputShake 360ms ease;
}

.evidence-slots.shake .slot {
  border-color: var(--brick);
}





input {
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--line);
}

input:focus,
button:focus-visible,
a:focus-visible {
  outline: 3px solid rgba(226, 60, 28, 0.55);
  outline-offset: 2px;
}

/* Skip link — off-screen until keyboard-focused, then anchored top-left. */
.skip-link {
  position: absolute;
  left: 8px;
  top: -48px;
  z-index: 1000;
  padding: 8px 14px;
  background: var(--ink);
  color: var(--sheet);
  font-family: var(--font-mono);
  font-weight: 700;
  text-decoration: none;
  border-radius: 4px;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 8px;
}

/* The word list floats beside the grid — no card chrome, just the words. */
.word-panel {
  display: grid;
  align-content: start;
  gap: 18px;
  background: transparent;
  border: 0;
  box-shadow: none;
}





.word-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 11px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.word-list li {
  display: flex;
  align-items: center;
  font-size: 1rem;
  font-weight: 900;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  transition: color 200ms ease, opacity 200ms ease;
}

/* The strike draws itself left-to-right when a word is found. It lives on the
   word's own span, so it is exactly as long as the word, no longer. */
.word-list li span {
  position: relative;
}

.word-list li span::after {
  content: "";
  position: absolute;
  left: -2px;
  right: -2px;
  top: 50%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 260ms ease;
}

.word-list li.done {
  /* Grayed out + struck through — quietly closed. */
  color: var(--muted);
  opacity: 0.62;
  animation: word-found 420ms ease;
}

@keyframes word-found {
  0% {
    background: rgba(236, 202, 128, 0.6);
  }
  100% {
    background: transparent;
  }
}

.word-list li.done span::after {
  transform: scaleX(1);
}

.clue-box {
  padding: 16px;
  background: rgba(211, 165, 72, 0.16);
  border: 1px solid rgba(154, 70, 58, 0.28);
}

.clue-box p {
  margin: 0;
  color: var(--muted);
  font-size: 0.92rem;
  font-weight: 800;
  line-height: 1.45;
}

.clue-box p.unlocked {
  color: var(--brick);
  font-size: 1.12rem;
  letter-spacing: 0.1em;
}

/* The anagram letters are individual spans (flight targets). */
#clueLetters {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 11px;
}

.clue-letter {
  display: inline-block;
  transition: opacity 0.12s ease;
}

.clue-letter.pre-flight {
  opacity: 0;
}

/* A letter mid-flight from its grid cell to the anagram box. */
.flying-letter {
  position: fixed;
  z-index: 60;
  transform: translate(-50%, -50%);
  color: var(--brick);
  font-family: var(--font-mono);
  font-size: 1.25rem;
  font-weight: 900;
  pointer-events: none;
  text-shadow: 0 1px 0 rgba(252, 248, 238, 0.8);
}

#bookSource {
  color: var(--ink);
}

#puzzleSource {
  overflow-wrap: anywhere;
}

.reader-band {
  display: grid;
  gap: 28px;
  padding: clamp(46px, 7vw, 96px) clamp(18px, 6vw, 72px);
}







.book-copy p,
.reader-copy p {
  max-width: 46rem;
  margin: 0;
}



















.reader-band {
  grid-template-columns: minmax(280px, 0.9fr) minmax(300px, 0.7fr);
  align-items: center;
}

.signup-form,
.account-card {
  display: grid;
  gap: 14px;
  padding: 24px;
}

label {
  display: grid;
  gap: 8px;
  font-size: 0.88rem;
  font-weight: 800;
}

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-weight: 700;
}

.checkbox-row input {
  width: 18px;
  min-height: 18px;
}

.form-note {
  min-height: 1.5em;
  margin: 0;
  font-size: 0.86rem;
}

.account-dialog {
  width: min(92vw, 460px);
  padding: 0;
  border: 0;
  background: transparent;
}

.account-dialog::backdrop {
  background: rgba(32, 33, 29, 0.58);
}

.account-card {
  position: relative;
}

.dialog-close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  background: transparent;
  cursor: pointer;
  font-size: 1.4rem;
}

/* Case-panel footer: meta + streak chip */
.case-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.streak-icon {
  flex: none;
  margin-right: 4px;
  color: var(--accent-deep);
}

/* Answer box + action buttons grouped together under the grid */
.evidence-entry .case-actions {
  flex-wrap: wrap;
  margin-top: 2px;
}

.reveal-note {
  margin: 2px 0 0;
  color: var(--brick);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 800;
}

.danger-button {
  border-color: var(--brick);
  color: var(--brick);
}

.danger-button:hover:not(:disabled) {
  background: rgba(207, 122, 85, 0.16);
}

/* Big book call-to-action (the main conversion) */
.book-band {
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
  margin: clamp(24px, 4vw, 48px) clamp(18px, 6vw, 72px);
  padding: clamp(28px, 4vw, 56px);
}

.book-cta-button {
  display: inline-block;
  margin: 8px 0 14px;
  padding: 16px 26px;
  background: var(--brick);
  color: var(--sheet);
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 2.1vw, 1.5rem);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: 2px solid var(--ink);
  box-shadow: 6px 6px 0 var(--ink);
}

.book-cta-button:hover {
  background: var(--ink);
  transform: translate(2px, 2px);
  box-shadow: 4px 4px 0 var(--ink);
}

/* "Coming soon" CTA — stays inviting, but doesn't navigate or fake a press. */
.is-soon { cursor: default; }
.book-cta-button.is-soon:hover {
  background: var(--brick);
  transform: none;
  box-shadow: 6px 6px 0 var(--ink);
}

/* "‹ Tiny Gambit" back-to-imprint affordance (menu + footer). */
.menu-home {
  color: var(--brick);
}
.imprint-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.imprint-link:hover {
  color: var(--sheet);
}

/* Buy CTA — the main call to purchase (render kept here; the hero's was the dup) */
.buy-band {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(220px, 0.6fr);
  gap: clamp(24px, 4vw, 48px);
  align-items: center;
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
  margin: clamp(24px, 4vw, 48px) clamp(18px, 6vw, 72px);
  padding: clamp(28px, 4vw, 56px);
}

.buy-band .book-copy p {
  margin: 0 0 4px;
  color: var(--muted);
  line-height: 1.55;
}

/* Hero is text-only now (its render moved to the buy section) */
.hero {
  grid-template-columns: 1fr;
  min-height: auto;
}

/* Prominent "early reader" signup panel */
.reader-band.emphasis {
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
  margin: clamp(24px, 4vw, 48px) clamp(18px, 6vw, 72px);
  padding: clamp(28px, 4vw, 56px);
}

/* Two-up engage section: leave a review (left) + early reader (right) */
.dual-band {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 3vw, 36px);
  margin: clamp(24px, 4vw, 48px) clamp(18px, 6vw, 72px);
  align-items: stretch;
}
.dual-card {
  display: grid;
  gap: 16px;
  align-content: start;
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
  padding: clamp(24px, 3vw, 44px);
}
.dual-card h2 { margin: 0; }
.dual-card p { margin: 0; color: var(--muted); line-height: 1.55; }
/* eyebrow is a fit-to-text chip; stop the grid from stretching it full width */
.dual-card .eyebrow { justify-self: start; }
.dual-card a.primary-button {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  text-decoration: none;
  padding: 0 22px;
  margin-top: 4px;
}
.dual-card .signup-form {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  margin-top: 4px;
}
[data-theme="dark"] .dual-card { border-color: var(--line); }
@media (max-width: 860px) {
  .dual-band { grid-template-columns: 1fr; }
}

/* Quiet feedback-by-email line under the two cards */
.feedback-line {
  margin: 0 clamp(18px, 6vw, 72px) clamp(24px, 4vw, 48px);
  text-align: center;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.9rem;
}
.feedback-line a { color: var(--brick); font-weight: 800; }

.book-cta-link {
  display: inline-block;
  margin-top: 14px;
  color: var(--brick);
  font-family: var(--font-mono);
  font-weight: 800;
}

/* Tiny "how to play" strip at the very top */


.archive-head {
  max-width: 48rem;
}

.archive-head p {
  color: var(--muted);
  line-height: 1.55;
  margin: 0 0 16px;
}

.archive-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 14px;
}

.archive-case {
  position: relative;
  padding: 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--soft-shadow);
}

.archive-case.locked {
  opacity: 0.72;
}

.archive-card-top {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.archive-case h3 {
  margin: 0 0 12px;
  font-family: var(--font-body);
  font-size: 1.05rem;
}

.lock-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--brick);
}

.archive-note {
  margin: 10px 0 0;
  color: var(--brick);
  font-family: var(--font-mono);
  font-weight: 800;
  font-size: 0.8rem;
}

/* ---- Mobile delight: touch-drag + micro-animations ---- */

/* Critical: let drag-select work without the page scrolling under the finger. */
.letter-grid,
.cell {
  touch-action: none;
}

.cell {
  transition: background-color 150ms ease, color 150ms ease, transform 120ms ease;
}

@keyframes cellPop {
  0% { transform: scale(1); }
  40% { transform: scale(1.22); }
  100% { transform: scale(1); }
}

.cell.just-found {
  animation: cellPop 450ms ease;
}

@keyframes cluePop {
  0% { transform: scale(0.96); opacity: 0.6; }
  50% { transform: scale(1.05); }
  100% { transform: scale(1); opacity: 1; }
}

#clueLetters.pop {
  animation: cluePop 420ms ease;
}

@keyframes inputShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

.evidence-entry input.shake {
  animation: inputShake 360ms ease;
  border-color: var(--brick);
}




@keyframes streakPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.14); }
}

/* The streak celebrates with the solve (chip in the case panel + header pill). */
.case-solved .streak-pill {
  animation: streakPulse 520ms ease 2;
}

/* "Call a tip" hint flash — soft gold (static bg also covers reduced-motion) */
@keyframes hintPulse {
  0%, 100% { background: rgba(236, 202, 128, 0.25); }
  50% { background: rgba(236, 202, 128, 0.9); }
}

.cell.hint {
  background: rgba(236, 202, 128, 0.85);
  animation: hintPulse 0.7s ease 2;
}

.stats-line {
  margin: 12px 0 0;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--muted);
}

.share-button {
  margin-top: 12px;
}

.next-case {
  margin: 8px 0 0;
  color: var(--moss);
  font-family: var(--font-mono);
  font-size: 0.84rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* Respect users who prefer less motion — but keep the game alive.
   The short, small-amplitude feedback (cell pop on a find, word strike-through,
   clue pop, error shake, streak/hint pulse) stays: it is essential play
   feedback, not decoration, and a brief in-place pulse carries no vestibular
   risk. Only the large, translational, or sweeping motion is dropped below. */
@media (prefers-reduced-motion: reduce) {
  /* Menus/dialogs appear without the drop/rise slide. */
  .menu-panel.open,
  .archive-dialog[open],
  .archive-dialog::backdrop {
    animation: none !important;
  }
  /* The "CASE CLOSED" stamp lands without the slam. */
  .case-stamp span {
    animation: none !important;
  }
  /* The reveal capsule paints fully drawn instead of snaking across. */
  .snake-overlay line.snake-grow {
    animation: none !important;
    stroke-dashoffset: 0;
  }
  html {
    scroll-behavior: auto;
  }
}

/* How-to hint (first-time onboarding) */
/* Overflow "⋯" menu beside File evidence — folds the secondary actions away. */
.action-overflow {
  position: relative;
  display: inline-flex;
}

.actions-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 30;
  min-width: 210px;
  display: grid;
  background: var(--panel);
  border: 2px solid var(--ink);
  box-shadow: var(--shadow);
}

.actions-menu[hidden] {
  display: none;
}

.actions-menu:not([hidden]) {
  animation: panel-drop 170ms ease-out;
}

.actions-menu button {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 46px;
  padding: 12px 14px;
  text-align: left;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 800;
  cursor: pointer;
}

.actions-menu button svg,
.reveal-note svg,
.solve-reveal-tag svg {
  flex: none;
  vertical-align: -2px;
}

.icon-button svg {
  display: block;
  margin: auto;
}

.reveal-note {
  display: flex;
  align-items: center;
  gap: 7px;
}

.dialog-close,
.reader-nudge-close {
  display: grid;
  place-items: center;
}

.actions-menu button:last-child {
  border-bottom: 0;
}

.actions-menu button:hover:not(:disabled) {
  background: rgba(211, 165, 72, 0.2);
}

.actions-menu button:disabled {
  color: var(--muted);
  cursor: not-allowed;
}

.actions-menu .danger-button {
  color: var(--brick);
}

.actions-menu .reveal-note {
  margin: 0;
  padding: 8px 14px;
  background: rgba(207, 122, 85, 0.1);
  border-bottom: 1px solid var(--line);
}

/* In-grid case-closed reveal — the single case-closed block (payoff, stats,
   share) right where the eyes already are. */
.solve-reveal {
  animation: rise-in 280ms ease;
  margin-top: 14px;
  padding: 14px 16px;
  background: rgba(63, 86, 72, 0.12);
  border: 1px solid var(--moss);
  border-left: 5px solid var(--moss);
}

.solve-reveal[hidden] {
  display: none;
}

.solve-reveal-tag {
  margin: 0 0 6px;
  color: var(--moss);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.solve-reveal-text {
  margin: 0;
  font-size: 0.96rem;
  font-style: italic;
  line-height: 1.5;
}

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

/* "How to play" briefing dialog steps */
.how-steps {
  margin: 14px 0 4px;
  padding-left: 20px;
  font-family: var(--font-mono);
  font-size: 0.92rem;
  line-height: 1.5;
}

.how-steps li {
  margin-bottom: 10px;
}



/* Book promo band */
.book-band {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(260px, 0.7fr);
  gap: 28px;
  align-items: center;
  padding: clamp(46px, 7vw, 96px) clamp(18px, 6vw, 72px);
}

.book-copy p {
  max-width: 46rem;
  margin: 0 0 12px;
}



.book-art {
  display: grid;
  place-items: center;
}

.book-art img {
  width: 100%;
  max-width: 360px;
  height: auto;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.optional {
  color: var(--muted);
  font-weight: 600;
}

/* Footer */
.site-footer {
  position: relative;
  overflow: hidden;
  padding: clamp(36px, 5vw, 60px) clamp(18px, 6vw, 72px);
  background: var(--coal);
  color: var(--sheet);
}

/* The cover's detective motif, ghosted into the dark footer as a watermark. */
.footer-silhouette {
  position: absolute;
  right: clamp(-24px, 1vw, 32px);
  bottom: 0;
  height: 118%;
  width: auto;
  opacity: 0.07;
  filter: brightness(0) invert(1);
  pointer-events: none;
  user-select: none;
}

.footer-inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 24px;
  align-items: start;
}

.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.footer-brand .brand-mark {
  filter: brightness(0) invert(1);
}

.footer-brand strong {
  display: block;
  font-size: 1rem;
}

.footer-brand small {
  display: block;
  color: #b9bcb2;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Brand slogan sign-off (locked 2026-06-08): lowercase, no punctuation. */
.footer-slogan {
  display: block;
  margin-top: 6px;
  color: #e7c97d;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: lowercase;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 20px;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 700;
}

.footer-nav a,
.footer-nav .footer-link {
  color: #e0d2b7;
  text-decoration: none;
}

.footer-nav .footer-link {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  cursor: pointer;
}

.footer-nav a:hover,
.footer-nav .footer-link:hover {
  color: var(--sheet);
}

.footer-legal {
  margin: 0;
  color: #9da199;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  line-height: 1.6;
  text-align: right;
}

@media (max-width: 860px) {
  .footer-inner {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .footer-nav {
    justify-content: flex-start;
  }

  .footer-legal {
    text-align: left;
  }
}

@media (max-width: 1120px) {
  .daily-shell {
    grid-template-columns: 1fr 1fr;
  }

  .case-panel {
    grid-column: 1 / -1;
  }

  .case-panel h2 {
    max-width: 18ch;
  }

  .word-panel {
    grid-column: 1 / -1;
  }
}

@media (max-width: 860px) {
  .site-header {
    grid-template-columns: 1fr auto;
  }

  nav {
    grid-column: 1 / -1;
    order: 3;
    overflow-x: auto;
    padding-bottom: 4px;
  }

  .hero,
  .daily-shell,
  .buy-band {
    grid-template-columns: 1fr;
  }

  .book-art {
    order: -1;
  }

  .hero {
    min-height: auto;
  }
}

@media (max-width: 520px) {
  .site-header {
    gap: 8px;
    padding-inline: 10px;
  }

  .header-actions {
    gap: 7px;
  }

  .brand strong {
    font-size: 0.9rem;
  }

  nav {
    flex-wrap: wrap;
    gap: 10px 16px;
    overflow: visible;
  }

  .ghost-button {
    justify-self: start;
    padding-inline: 10px;
  }

  .hero {
    display: block;
    padding-inline: 30px;
  }



  .hero .eyebrow {
    font-size: 0.68rem;
    letter-spacing: 0.08em;
  }

  h1 {
    max-width: 100%;
    font-size: clamp(1.7rem, 7.6vw, 2.2rem);
    line-height: 1.05;
  }



  .hero-actions {
    align-items: flex-start;
    flex-direction: column;
  }



  .daily-shell {
    padding-inline: 12px;
  }

  .case-panel,
  .puzzle-panel,
  .word-panel {
    padding: 16px;
  }

  .case-facts div {
    grid-template-columns: 1fr;
    gap: 3px;
  }



  .preview-sheet {
    padding: 22px;
  }
}

/* Phone/tablet: the Scene Words card rides directly under the grid (app.js
   moves it into the puzzle panel) so the list is visible without scrolling.
   Keep it compact so the evidence entry stays close to the grid. */
@media (max-width: 860px) {
  .puzzle-panel .word-card .word-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 14px;
    margin-top: 10px;
  }

  .puzzle-panel .word-card .word-list li {
    font-size: 0.88rem;
  }
}

/* Phone: collapse the case panel into a slim bar so the grid leads above the fold. */
@media (max-width: 640px) {
  .case-panel {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 4px 14px;
    padding: 14px 16px;
    border-left-width: 5px;
  }

  .case-panel .case-tag {
    flex-basis: 100%;
    margin: 0;
  }

  .case-panel h2 {
    margin: 0;
    max-width: none;
    font-size: 1.35rem;
    line-height: 1.05;
  }

  /* Only the uppercase meta line moves out of the way on phones — the little
     case-brief story stays (readers missed it), just tighter under the title. */
  .case-meta {
    display: none;
  }

  .case-copy {
    flex-basis: 100%;
    margin: 2px 0 0;
    font-size: 0.88rem;
    line-height: 1.45;
  }

  .case-foot {
    margin: 0;
  }
}

/* ── Modern header actions + sign-in ──────────────────────────────────────── */
.header-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.signin-button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  text-decoration: none;
  max-width: 168px;
  height: 44px;
  padding: 0 18px;
  color: var(--sheet);
  background: var(--ink);
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}

.signin-button:hover {
  background: var(--brick);
}

.signin-button:active {
  transform: translateY(1px);
}

/* Signed-in: show the detective's name as a softer chip with an avatar dot. */
.signin-button.is-authed {
  color: var(--ink);
  background: var(--sheet);
}

.signin-button.is-authed::before {
  content: "";
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--gold), var(--brick));
  border: 1.5px solid var(--ink);
}

.streak-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 44px;
  padding: 0 13px;
  background: var(--sheet);
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-weight: 800;
  font-size: 0.92rem;
  color: var(--ink);
}

.menu-auth {
  color: var(--brick) !important;
}

/* ── Login dialog ─────────────────────────────────────────────────────────── */
.login-dialog {
  width: min(94vw, 440px);
}

.login-value {
  color: var(--muted);
  margin: 0 0 22px;
}

.login-methods {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.oauth-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 0 16px;
  background: #fff;
  color: #1f1f1f;
  border: 1.5px solid var(--ink);
  border-radius: 11px;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease;
}

.oauth-button:hover {
  background: #f1f1f1;
}

.oauth-button:disabled {
  opacity: 0.6;
  cursor: default;
}

.oauth-logo {
  flex: none;
}

.login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.login-divider::before,
.login-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.login-email-form {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.login-email-label {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink);
}

.login-email-form input {
  width: 100%;
  min-height: 46px;
  padding: 0 14px;
  background: var(--field);
  border: 1.5px solid var(--ink);
  border-radius: 10px;
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--ink);
}

.login-email-form .primary-button {
  min-height: 48px;
  border-radius: 10px;
}

.login-note {
  margin: 18px 0 0;
  color: var(--muted);
  font-size: 0.86rem;
}

/* A failed send must be impossible to miss. */
.login-note.is-error {
  color: #a83a2a;
  font-weight: 700;
}

/* Post-send state: where the link went + resend cooldown + escape hatch. */
.login-sent {
  display: grid;
  gap: 10px;
  padding: 16px;
  background: rgba(211, 165, 72, 0.12);
  border: 1px solid var(--line);
}

.login-sent-lede {
  margin: 0;
  font-weight: 700;
}

.login-sent-lede strong {
  overflow-wrap: anywhere;
}

.login-sent-copy {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}

.login-sent-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.login-sent-actions .secondary-button:disabled {
  color: var(--muted);
  cursor: default;
  font-variant-numeric: tabular-nums;
}

.text-button {
  padding: 0;
  background: none;
  border: 0;
  color: var(--brick);
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.login-signed-in {
  display: grid;
  gap: 18px;
}

.account-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

.account-avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: radial-gradient(circle at 35% 30%, var(--gold), var(--brick));
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.4rem;
}

.account-id {
  min-width: 0;
}

.login-greeting {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
}

.account-email {
  margin: 2px 0 0;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  overflow-wrap: anywhere;
}

.account-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
}

.account-stats div {
  display: grid;
  gap: 4px;
  padding: 12px 10px;
  border: 1px solid var(--line);
  background: rgba(211, 165, 72, 0.1);
  text-align: center;
}

.account-stats dt {
  font-size: 0.66rem;
  letter-spacing: 0.06em;
}

.account-stats dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 800;
}

.account-sync-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.5;
}

.login-signed-in .secondary-button {
  justify-self: start;
}

/* Phone: the standalone Sign in button is redundant (Sign in also lives in the
   hamburger menu) and overflows the header row, so drop it and keep the streak,
   theme toggle, and menu button. */
@media (max-width: 640px) {
  .header-actions .signin-button {
    display: none;
  }
  .streak-pill {
    padding: 0 10px;
  }
}

/* Reader capture — post-solve nudge + book-band notify (added 2026-06-09) */
.reader-nudge {
  position: relative;
  margin-top: 14px;
  padding: 16px 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.reader-nudge-text { margin: 0 28px 10px 0; color: var(--ink); font-weight: 600; }
.reader-nudge-form { display: flex; flex-wrap: wrap; gap: 8px; }
.reader-nudge-form input[type="email"],
.book-notify-form input[type="email"] {
  flex: 1 1 200px;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font: inherit;
  background: var(--field);
  color: var(--ink);
}
.reader-nudge-note,
.book-notify-note { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.reader-nudge-close {
  position: absolute; top: 6px; right: 10px;
  background: none; border: none; cursor: pointer;
  font-size: 20px; line-height: 1; color: var(--muted);
}
.book-notify-form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.book-notify-form button {
  padding: 10px 16px; border: 1px solid var(--ink); border-radius: 8px;
  background: transparent; color: var(--ink); font: inherit; font-weight: 600; cursor: pointer;
}
.book-notify-form button:hover { background: var(--ink); color: var(--sheet); }

/* Archive-unlock dialog — "or just get notified" email capture (signed-out alternative). */
.archive-capture { margin-top: 14px; }
.archive-capture .login-divider { margin-bottom: 12px; }
.archive-capture-lede { margin: 0 0 10px; font-size: 14px; color: var(--muted); }
.archive-capture-form { display: flex; flex-wrap: wrap; gap: 8px; }
.archive-capture-form input[type="email"] {
  flex: 1 1 200px;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font: inherit;
  background: var(--field);
  color: var(--ink);
}
.archive-capture-form button {
  padding: 10px 16px; border: 1px solid var(--ink); border-radius: 8px;
  background: transparent; color: var(--ink); font: inherit; font-weight: 600; cursor: pointer;
}
.archive-capture-form button:hover { background: var(--ink); color: var(--sheet); }
.archive-capture-note { margin: 8px 0 0; font-size: 13px; color: var(--muted); }

/* ── Dark theme component fixes ──────────────────────────────────────────────
   Most of the noir theme falls out of the token flips in :root /
   [data-theme="dark"]. These are the spots where a light-theme assumption
   (ink-on-cream chip, cream secondary surface) breaks when ink goes cream. */

[data-theme="dark"] .brand strong {
  color: var(--yellow);
}

[data-theme="dark"] .skip-link {
  background: #3a3122;
  color: #f5c95e;
}

[data-theme="dark"] .icon-button {
  background: #3a3122;
  color: #f5c95e;
  border-color: #6b5a2c;
}

[data-theme="dark"] .secondary-button {
  background: transparent;
}

[data-theme="dark"] .secondary-button:hover {
  background: rgba(245, 181, 28, 0.12);
}

[data-theme="dark"] .clue-box {
  background: rgba(245, 181, 28, 0.10);
  border-color: rgba(245, 181, 28, 0.25);
}

[data-theme="dark"] .brand-glyph {
  border-color: var(--line);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.6);
}

[data-theme="dark"] .book-cta-button {
  border-color: var(--accent-deep);
  box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.55);
}

[data-theme="dark"] .book-band {
  background: var(--panel);
  border-color: var(--line);
}

/* ── Theme toggle (header) ──────────────────────────────────────────────── */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  color: var(--ink);
  background: var(--field);
  border: 1.5px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.theme-toggle:hover {
  background: var(--yellow-soft);
  color: var(--yellow-ink);
}

/* Show the theme you'd switch to: moon in light, sun in dark. */
.theme-toggle .theme-icon-sun { display: none; }
[data-theme="dark"] .theme-toggle .theme-icon-sun { display: block; }
[data-theme="dark"] .theme-toggle .theme-icon-moon { display: none; }

[data-theme="dark"] .signin-button {
  color: #211d18;
}

[data-theme="dark"] .signin-button:hover {
  background: var(--yellow);
}

[data-theme="dark"] .signin-button.is-authed,
[data-theme="dark"] .streak-pill {
  color: #f5c95e;
  background: #3a3122;
  border-color: #6b5a2c;
}

/* Light theme: the streak pill is one of the page's yellow moments. */
.streak-pill {
  color: var(--yellow-ink);
  background: var(--yellow-soft);
  border-color: #e3b53c;
}

[data-theme="dark"] .streak-pill {
  border-color: #6b5a2c;
}

[data-theme="dark"] .reader-band.emphasis,
[data-theme="dark"] .archive-dialog,
[data-theme="dark"] .actions-menu,
[data-theme="dark"] .menu-panel {
  border-color: var(--line);
}

/* ── Streak dialog ("detective record") ─────────────────────────────────── */
.streak-dialog-title {
  margin: 8px 0 6px;
  font-size: clamp(1.7rem, 3.4vw, 2.4rem);
}

.streak-dialog-note {
  margin: 0 0 6px;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.5;
}

.streak-stats {
  display: flex;
  gap: 30px;
  margin: 16px 0 4px;
}

.streak-stats div {
  display: grid;
  gap: 2px;
}

.streak-stats dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 1.35rem;
  font-weight: 800;
}

.rank-track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 8px;
  margin: 18px 0 12px;
  padding: 0;
  list-style: none;
}

.rank-track li {
  display: grid;
  gap: 3px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  font-family: var(--font-mono);
}

.rank-track li strong {
  font-size: 0.85rem;
}

.rank-track li span {
  font-size: 0.68rem;
  color: var(--muted);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.rank-track li.unlocked {
  background: var(--yellow-soft);
  border-color: #e3b53c;
  color: var(--yellow-ink);
}

.rank-track li.unlocked span {
  color: var(--yellow-ink);
}

.rank-track li.locked {
  opacity: 0.6;
}

[data-theme="dark"] .rank-track li.unlocked {
  border-color: #6b5a2c;
}

/* Smooth the theme flip itself (the .cell keeps its own transform transition). */
body,
.site-header,
.case-panel,
.puzzle-panel {
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  body,
  .site-header,
  .case-panel,
  .puzzle-panel,
  .cell {
    transition: none;
  }

  .cell:hover {
    transform: none;
  }
}

/* ── Gloss sweep on a fresh find ────────────────────────────────────────────
   A short white dash rides the capsule path first letter → last (pathLength=1
   keeps the dash math unit-free). Composites normally above the cells, unlike
   the blend-isolated snake overlay where white would vanish under multiply. */
.glaze-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}

.glaze-overlay line.glaze-run {
  stroke-dasharray: 0.22 1.2;
  stroke-dashoffset: 0.22;
  opacity: 0;
  animation: glaze-sweep 680ms ease-out 240ms forwards;
}

@keyframes glaze-sweep {
  0% {
    stroke-dashoffset: 0.22;
    opacity: 0;
  }
  18% {
    opacity: 0.75;
  }
  82% {
    opacity: 0.75;
  }
  100% {
    stroke-dashoffset: -1;
    opacity: 0;
  }
}

[data-theme="dark"] .glaze-overlay {
  /* The white streak lands harder on dark blocks — soften it. */
  opacity: 0.5;
}

@media (prefers-reduced-motion: reduce) {
  .glaze-overlay line.glaze-run {
    animation: none;
    opacity: 0;
  }
}

/* Reveal warning pops in on click (it's hidden until then). */
.reveal-note.pop {
  animation: cluePop 320ms ease;
}

/* A called tip reads as spent, but stays clickable to re-glow the letter. */
.actions-menu .tip-used:not(:disabled) {
  color: var(--muted);
}

/* ── Streak leaderboard (inside the detective record dialog) ────────────── */
.leaderboard {
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.leaderboard-title {
  margin: 0 0 10px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.leaderboard-list {
  display: grid;
  gap: 6px;
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
  counter-reset: rank;
}

.leaderboard-list li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 0.92rem;
}

.leaderboard-list li::before {
  counter-increment: rank;
  content: counter(rank) ".";
  min-width: 1.4em;
  color: var(--muted);
  font-weight: 800;
}

.leaderboard-list li span {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-list li strong {
  color: var(--yellow-ink);
  background: var(--yellow-soft);
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.8rem;
}

.leaderboard-list li:first-child {
  font-weight: 900;
}

/* <dialog> does NOT inherit body color (UA default is black) — in dark mode
   every dialog's text vanished against the dark panel. */
dialog {
  color: var(--ink);
}

[data-theme="dark"] .buy-band,
[data-theme="dark"] .reader-band.emphasis,
[data-theme="dark"] .signup-form,
[data-theme="dark"] .account-card {
  border-color: var(--line);
}

/* Narrow phones: the two-line imprint crowds the header — keep just the title. */
@media (max-width: 520px) {
  .brand small {
    display: none;
  }

  .brand strong {
    font-size: 0.95rem;
  }
}

/* ── Author page (/author) ──────────────────────────────────────────────── */
.author-shell {
  display: grid;
  place-items: start center;
  padding: clamp(28px, 5vw, 64px) clamp(18px, 4vw, 48px) clamp(48px, 7vw, 90px);
}

.author-card {
  width: min(100%, 720px);
  padding: clamp(24px, 4vw, 44px);
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 7px solid var(--accent);
  box-shadow: var(--shadow);
}

.author-card h1 {
  font-size: clamp(2.1rem, 5vw, 3.4rem);
}

.author-lede {
  margin: 14px 0 0;
  color: var(--accent-deep);
  font-family: var(--font-mono);
  font-size: 1.02rem;
  font-weight: 800;
}

[data-theme="dark"] .author-lede {
  color: var(--accent);
}

.author-body {
  display: grid;
  grid-template-columns: minmax(96px, 120px) 1fr;
  gap: clamp(18px, 4vw, 32px);
  align-items: start;
  margin: 22px 0 6px;
}

.author-portrait {
  display: grid;
  place-items: end center;
  margin: 0;
  aspect-ratio: 5 / 6;
  overflow: hidden;
  background: var(--yellow);
  border: 1.5px solid var(--ink);
  box-shadow: 4px 4px 0 var(--ink);
  border-radius: 8px;
}

[data-theme="dark"] .author-portrait {
  border-color: var(--line);
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.6);
}

.author-portrait img {
  width: 88%;
  align-self: end;
}

.author-facts {
  margin: 0;
}

.author-bio p {
  max-width: 56ch;
  margin: 0 0 14px;
  color: var(--muted);
  line-height: 1.6;
}

@media (max-width: 560px) {
  .author-body {
    grid-template-columns: 1fr;
  }

  .author-portrait {
    max-width: 130px;
  }
}

/* The reveal reads as one story unit: intro echoed above the payoff. */
.solve-reveal-intro {
  margin: 0 0 8px;
  color: var(--muted);
  font-style: italic;
  font-size: 0.92rem;
  line-height: 1.5;
}

/* Reveal unit typography: intro = italic setup, payoff = upright punchline. */
.solve-reveal-text {
  font-style: normal;
  font-weight: 700;
}

/* --moss is a light-theme green; it disappears on the dark panel. */
[data-theme="dark"] .solve-reveal-tag,
[data-theme="dark"] .next-case {
  color: var(--yellow-ink);
}

[data-theme="dark"] .solve-reveal {
  background: rgba(245, 181, 28, 0.07);
  border-color: var(--line);
  border-left-color: var(--yellow);
}

/* Once the case closes, the intro lives inside the reveal unit — showing it
   in the case panel too is duplication. Reset restores it. */
.case-solved .case-copy {
  display: none;
}

/* ── Past-cases archive strip (ARCHIVE-PLAN.md, Phase 1) ───────────────────────
   Visible, locked past-daily cases as the sign-in incentive. Locked + blurred
   when signed out; the .is-unlocked flip (set on sign-in) clears the blur and
   hides the locks. Hidden entirely until at least one case is behind us. */
.recent-cases {
  max-width: 1120px;
  margin: 8px auto 0;
  padding: 8px 20px 4px;
}
.recent-cases .eyebrow { display: block; }
.recent-lede {
  color: var(--muted);
  margin: 4px 0 18px;
  max-width: 52ch;
}
.recent-strip {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}
.recent-card {
  position: relative;
  text-align: left;
  width: 100%;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px;
  overflow: hidden;
  font: inherit;
  color: inherit;
  cursor: default;
}
button.recent-card { cursor: pointer; transition: border-color 0.15s ease; }
button.recent-card:hover,
button.recent-card:focus-visible { border-color: var(--accent); }
.recent-thumb { position: relative; margin-bottom: 10px; }
.recent-mini {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 3px;
}
.recent-mini span {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cell);
  border: 1px solid var(--cell-line);
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--cell-ink);
}
.recent-cases:not(.is-unlocked) .recent-mini { filter: blur(3px); opacity: 0.7; }
.recent-lock {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.recent-lock > span {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--coal);
  color: var(--yellow);
  display: flex;
  align-items: center;
  justify-content: center;
}
.recent-cases.is-unlocked .recent-lock { display: none; }
.recent-ctitle {
  font-family: var(--font-display);
  font-size: 13px;
  letter-spacing: 0.3px;
  margin: 2px 0;
}
.recent-cdate {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  margin: 0;
}
.recent-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--wash);
}
.recent-more-n {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--accent-deep);
}
.recent-cta {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 18px;
}
.recent-alt {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
  margin: 0;
}

/* ── Past-case replay + full archive (ARCHIVE-PLAN.md, Phase 2) ────────────── */
a.recent-card { text-decoration: none; cursor: pointer; transition: border-color 0.15s ease; }
a.recent-card:hover,
a.recent-card:focus-visible { border-color: var(--accent); }
.recent-action {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.3px;
  color: var(--accent-deep);
  margin-top: 4px;
}
.recent-action.is-closed { color: var(--muted); }
.recent-card.is-closed { opacity: 0.85; }

.replay-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  max-width: 1120px;
  margin: 0 auto 14px;
  padding: 10px 16px;
  background: var(--yellow-soft);
  color: var(--yellow-ink);
  border-radius: 10px;
  font-family: var(--font-mono);
  font-size: 13px;
}
.replay-banner span { display: inline-flex; align-items: center; gap: 7px; }
.replay-banner a { color: var(--accent-deep); font-weight: 700; }

/* The full "View archive" wall lives inside the existing archive dialog. */
.archive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(116px, 1fr));
  gap: 10px;
  margin: 6px 0 16px;
  max-height: 46vh;
  overflow-y: auto;
}
.archive-grid:empty { display: none; }
.archive-dialog:not(.is-unlocked) .recent-mini { filter: blur(3px); opacity: 0.7; }
.archive-dialog.is-unlocked .recent-lock { display: none; }

/* ── Archive rail — minimal, peripheral (ARCHIVE-PLAN.md) ──────────────────────
   Demoted from a hero section to a small pill below the daily. Signed out: a
   quiet sign-in nudge with faint case-file motifs. Signed in: just a pointer to
   the full archive dialog. The real browsing lives in that dialog. */
.archive-rail { max-width: 1120px; margin: 2px auto 0; padding: 0 20px; }
.archive-rail-inner {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--wash);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
}
.archive-rail-inner strong { color: var(--ink); font-weight: 700; }
.archive-rail-ico { color: var(--muted); flex: none; }
.archive-rail-thumbs { display: inline-flex; gap: 4px; }
.archive-thumb {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  width: 22px;
  height: 22px;
  padding: 2px;
  background: var(--cell);
  border: 1px solid var(--cell-line);
  border-radius: 4px;
  filter: blur(1.2px);
  opacity: 0.8;
}
.archive-thumb span { background: var(--cell-ink); opacity: 0.25; border-radius: 1px; }
.linklike {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--accent-deep);
  font-weight: 700;
  cursor: pointer;
}
.linklike:hover { text-decoration: underline; }
