/* Desk Puzzle — Stain Room (2D)
   Cool slide-glass ground, hematoxylin-indigo actions, sparing eosin-pink
   highlights, a slate lab bench, and four stain-named tiers (Saffron,
   Light Green, Prussian Blue, PAS). Light and dark themes.

   Play screen: a top-down desk. Pieces are freely draggable physical
   objects; the microscope stage stays on the desk while the wall lightbox
   and X-ray rail sit above it; the microscope DISPLAY is a resizable panel
   to the left of the desk; four group trays run along the bottom. Motion is
   drag feedback + short settle transitions only, and fully collapses
   under prefers-reduced-motion (bottom of this file).

   Skeuomorphic textures: game.js probes each known filename in
   assets/textures/ directly (no manifest) and, per file that loads,
   sets --tex-* custom properties + `textured` classes. Absent textures
   = the CSS-drawn look below, untouched. */

:root {
  --ink: #1c1a2e;          /* hematoxylin-black */
  --ink-soft: #524f6b;
  --ink-faint: #8a87a0;
  --paper: #f3f2f7;        /* slide glass */
  --paper-2: #e7e5ef;
  --paper-grain-a: rgba(75, 63, 176, 0.035);
  --paper-grain-b: rgba(214, 69, 122, 0.025);
  --panel: #fbfbfd;
  --panel-edge: rgba(28, 26, 46, 0.13);
  --rule: rgba(28, 26, 46, 0.08);
  --accent: #4b3fb0;       /* hematoxylin */
  --accent-hover: #4034a0;
  --accent-ink: #ffffff;
  --accent-soft: #e8e5f8;
  --eosin: #d6457a;        /* eosin: sparing highlight */
  --eosin-soft: #fbe3ec;
  --eosin-ink: #ffffff;

  /* Tier colors, easiest to hardest, named for stains. */
  --tier-1: #e9b829;   /* Saffron (HPS) */
  --tier-1-ink: #3a2a00;
  --tier-2: #3d8f62;   /* Light Green (Pap) */
  --tier-2-ink: #13121c;   /* white on this green is 3.96:1, below AA */
  --tier-3: #2e5aa8;   /* Prussian Blue */
  --tier-3-ink: #ffffff;
  --tier-4: #a8306f;   /* PAS magenta */
  --tier-4-ink: #ffffff;

  --ok: #2f7d55;
  --danger: #c0392f;
  --scrim: rgba(16, 14, 30, 0.5);
  --shadow: rgba(28, 26, 46, 0.14);
  --serif: "Iowan Old Style", "Palatino Linotype", Georgia, "Times New Roman", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --hand: "Bradley Hand", "Noteworthy", "Marker Felt", "Segoe Print", cursive;
  --mono: "SF Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 0.15s;
  --dur: 0.22s;

  /* one radius system: small = interactive, mid = panels, large = surfaces */
  --r-s: 6px;
  --r-m: 10px;
  --r-l: 14px;

  /* themed surfaces the components read (dark overrides below) */
  --card: #ffffff;
  --field-bg: #ffffff;
  --toast-bg: #1c1a2e;
  --toast-ink: #f3f2f7;
  /* slate lab bench */
  --desk-hi: #4a5060;
  --desk-mid: #3a3f4c;
  --desk-lo: #424857;
  --desk-edge: rgba(16, 18, 26, 0.5);
  --bench-label: rgba(233, 236, 244, 0.85);
  /* wall above the bench: pale lab-tile gray */
  --wall-a: #dfe1e8;
  --wall-b: #cdd0da;
  --wall-ink: rgba(28, 26, 46, 0.55);
  --lightbox-a: #fbfcff;
  --lightbox-b: #e9ecf5;
  --lightbox-c: #cfd4e2;
  --lightbox-glow: rgba(236, 240, 252, 0.7);
  --machine-shell-a: #eceef3;
  --machine-shell-b: #cfd3dd;
  --machine-dark-a: #4a4f5c;   /* metal: scope stage, bezels, rails */
  --machine-dark-b: #33363f;
  --control-bg: #eef0f5;
  /* microscope screen; ui-play.js reads the --scope-* values at draw time */
  --scope-screen: #eef0f6;
  --scope-bed-a: #f4f5fa;
  --scope-bed-b: #d6d9e4;
  --scope-ring: rgba(58, 63, 76, 0.25);
  --scope-busy: rgba(75, 63, 176, 0.35);
  --stage-glass-a: rgba(252, 252, 255, 0.95);
  --stage-glass-b: rgba(232, 234, 246, 0.75);
  --stage-glass-c: rgba(170, 176, 200, 0.5);
  --stage-glass-glow: rgba(236, 240, 255, 0.5);
  --slot-bg: rgba(255, 255, 255, 0.45);
  --slot-well: none;
  --slot-bg-locked: rgba(255, 255, 255, 0.5);

  color-scheme: light;
}

/* Dark stain room: the room dims; pieces keep their daylight faces. */
:root[data-theme="dark"] {
  --ink: #eceaf6;
  --ink-soft: #a9a6c0;
  --ink-faint: #7b7894;
  --paper: #13121c;
  --paper-2: #1c1a29;
  --paper-grain-a: rgba(157, 147, 240, 0.04);
  --paper-grain-b: rgba(240, 123, 163, 0.025);
  --panel: #1b1a27;
  --panel-edge: rgba(236, 234, 246, 0.13);
  --rule: rgba(236, 234, 246, 0.07);
  --accent: #9d93f0;
  --accent-hover: #b0a8f4;
  --accent-ink: #13121c;
  --accent-soft: rgba(75, 63, 176, 0.3);
  --eosin: #f07ba3;
  --eosin-soft: rgba(214, 69, 122, 0.22);
  --eosin-ink: #13121c;
  --tier-1: #eabb33;
  --tier-2: #4fa877;
  --tier-2-ink: #13121c;
  --tier-3: #4472c4;   /* mockup #4b7bd0 nudged darker so white ink clears AA */
  --tier-3-ink: #ffffff;
  --tier-4: #c04588;   /* mockup #c4498a nudged, same reason */
  --tier-4-ink: #ffffff;
  --ok: #6cc495;
  --danger: #ef7a6e;
  --scrim: rgba(0, 0, 0, 0.6);
  --shadow: rgba(0, 0, 0, 0.4);
  --card: #222031;
  --field-bg: #171622;
  --toast-bg: #eceaf6;
  --toast-ink: #13121c;
  --desk-hi: #2f3340;
  --desk-mid: #252833;
  --desk-lo: #2a2e39;
  --desk-edge: rgba(0, 0, 0, 0.55);
  --bench-label: rgba(222, 226, 238, 0.78);
  --wall-a: #262835;
  --wall-b: #1e202b;
  --wall-ink: rgba(222, 226, 238, 0.55);
  --lightbox-a: #a7adbf;   /* softly lit, not white */
  --lightbox-b: #868c9f;
  --lightbox-c: #646a7c;
  --lightbox-glow: rgba(160, 170, 200, 0.14);
  --machine-shell-a: #2e303c;
  --machine-shell-b: #23252f;
  --machine-dark-a: #3a3e4a;
  --machine-dark-b: #262932;
  --control-bg: #2a2c38;
  --scope-screen: #15171e;
  --scope-bed-a: #1d2029;
  --scope-bed-b: #111319;
  --scope-ring: rgba(200, 206, 224, 0.16);
  --scope-busy: rgba(157, 147, 240, 0.4);
  --stage-glass-a: rgba(176, 182, 200, 0.7);
  --stage-glass-b: rgba(120, 126, 146, 0.55);
  --stage-glass-c: rgba(70, 76, 94, 0.5);
  --stage-glass-glow: rgba(160, 170, 200, 0.18);
  --slot-bg: rgba(0, 0, 0, 0.22);
  --slot-well: inset 0 1px 3px rgba(0, 0, 0, 0.35);
  --slot-bg-locked: rgba(0, 0, 0, 0.18);
  color-scheme: dark;
}

/* the photo desk dims with the room (machines on it dim too; pieces
   live on a sibling layer and keep their daylight faces) */
:root[data-theme="dark"] .desk-surface.textured {
  filter: brightness(0.6) saturate(0.85);
}

* { box-sizing: border-box; }

/* The overlays and error screen set their own display (flex), which would
   otherwise beat the UA stylesheet's [hidden] rule — so re-assert it with
   top priority. game.js shows elements by CLEARING `hidden`, never by
   styling over it. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
}

body {
  background-image:
    radial-gradient(circle at 15% 20%, var(--paper-grain-a) 0, transparent 45%),
    radial-gradient(circle at 85% 75%, var(--paper-grain-b) 0, transparent 50%);
  background-attachment: fixed;
}

h1, h2, h3 {
  font-family: var(--serif);
  color: var(--ink);
  margin: 0 0 0.4em;
}

p { margin: 0 0 0.6em; }

button { font-family: inherit; cursor: pointer; }

img { max-width: 100%; display: block; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ── Buttons ─────────────────────────────────────────────────────── */

.btn {
  font-family: var(--sans);
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0.55em 1.1em;
  border-radius: var(--r-s);
  border: 1px solid var(--panel-edge);
  background: var(--panel);
  color: var(--ink);
  transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
}
.btn:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-ghost { background: transparent; }

/* ══════════════════════ SCREENS ══════════════════════ */

.screen {
  min-height: 100vh;
  padding: 24px 20px 60px;
}

/* ── Menu (home screen) ──────────────────────────────────────────── */
/* Layout follows the Desk-Puzzle-Platform mockup's Browse page, CMSRU only. */

.screen-menu {
  padding: 0;
  display: flex;
  flex-direction: column;
  /* Desk props for the mini-desk thumbnails: physical objects, same in both themes. */
  --mini-note: #f7e27a;
  --mini-sheet: #fdfcf8;
  --mini-rx: #eef4f0;
  --mini-rx-band: #3d8f62;
  --mini-photo-a: #d4a888;
  --mini-photo-b: #8a6150;
  --mini-slide-glass: #f1f0f4;
  --mini-he: #f0b9d0;
  --mini-film-a: #15181c;
  --mini-film-b: #4a525a;
  /* Darker eosin for white-on-pink in light mode (5.7:1; the base eosin is 4.2:1). */
  --menu-tag-bg: #b8335f;
  --menu-tag-ink: #ffffff;
}
:root[data-theme="dark"] .screen-menu {
  --menu-tag-bg: var(--eosin);
  --menu-tag-ink: var(--eosin-ink);
}

.menu-wrap { width: 100%; max-width: 1180px; margin: 0 auto; padding-inline: 20px; }
.screen-menu > main { flex: 1 0 auto; }

/* Sticky header bar */
.site-head {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 20;
  background: var(--panel);
  border-bottom: 1px solid var(--panel-edge);
}
.site-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px 18px;
  padding-block: 12px;
}
.site-head-actions { display: flex; align-items: center; gap: 4px; flex: none; }
.site-head-actions .btn { white-space: nowrap; }

/* Brand: four tier-colored squares on a slate tile, beside the wordmark. */
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); min-width: 0; }
.brand-mark {
  position: relative;
  flex: none;
  width: 34px; height: 34px;
  border-radius: 7px;
  background: linear-gradient(160deg, var(--desk-hi), var(--desk-mid));
  box-shadow: 0 1px 2px var(--shadow);
}
.brand-mark i { position: absolute; width: 11px; height: 11px; border-radius: 2px; }
.brand-mark i:nth-child(1) { left: 5px; top: 5px; background: var(--tier-1); }
.brand-mark i:nth-child(2) { right: 5px; top: 5px; background: var(--tier-2); }
.brand-mark i:nth-child(3) { left: 5px; bottom: 5px; background: var(--tier-3); }
.brand-mark i:nth-child(4) { right: 5px; bottom: 5px; background: var(--tier-4); }
.brand-name { font-family: var(--serif); font-size: 1.25rem; font-weight: 600; line-height: 1; }
.brand-name small {
  display: block;
  margin-top: 3px;
  font-family: var(--sans);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Button sizes used on the menu (links styled as buttons too). */
a.btn.btn-small, a.btn.btn-big { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
.btn-small { font-size: 0.85rem; padding: 0.45em 0.8em; }
.btn-big { font-size: 1rem; padding: 0.8em 1.3em; }
.screen-menu .btn-ghost { border-color: transparent; }
.btn-icon { display: inline-flex; align-items: center; justify-content: center; padding: 0.45em 0.55em; }
.btn-icon .ico-sun { display: none; }
:root[data-theme="dark"] .btn-icon .ico-sun { display: inline; }
:root[data-theme="dark"] .btn-icon .ico-moon { display: none; }

/* Hero */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 34px;
  align-items: center;
  padding-block: 44px 30px;
}
.hero-copy { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.eyebrow {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.hero-title {
  margin: 0;
  font-size: clamp(1.9rem, 4.5vw, 2.8rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.lede { margin: 0; font-size: 1.08rem; color: var(--ink-soft); max-width: 52ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.menu-stats {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  font-size: 0.85rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.menu-stats b { color: var(--ink); font-weight: 600; }

/* Mini desk thumbnail (generated, seeded by puzzle id) */
.mini {
  display: block;
  position: relative;
  overflow: hidden;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-m);
  background: linear-gradient(160deg, var(--desk-hi), var(--desk-mid) 60%, var(--desk-lo));
}
.mini::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(95deg, rgba(0, 0, 0, 0.04) 0 3px, transparent 3px 11px);
}
.mini span { position: absolute; border-radius: 2px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25); }
.mini .k-note { background: var(--mini-note); }
.mini .k-sheet { background: var(--mini-sheet); }
.mini .k-slide { background: linear-gradient(90deg, var(--mini-slide-glass) 0 22%, var(--mini-he) 22%); }
.mini .k-film { background: radial-gradient(ellipse at 50% 45%, var(--mini-film-b), var(--mini-film-a)); }
.mini .k-rx { background: var(--mini-rx); border-top: 3px solid var(--mini-rx-band); }
.mini .k-photo { background: var(--card); padding: 2px; }
.mini .k-photo::before {
  content: "";
  display: block;
  width: 100%; height: 100%;
  background: linear-gradient(135deg, var(--mini-photo-a), var(--mini-photo-b));
}

/* Real thumbnail (tools/make_thumbnails.mjs): transparent around the clue
   tiles, so the bench and stripes above show through in both themes. The
   generated props stay hidden while it loads and return if it fails. */
.mini .mini-thumb {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}
.mini.thumb-pending > span,
.mini.has-thumb > span { display: none; }

/* Puzzle cards (featured + grid); real buttons, styled as cards */
.pcard {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  min-width: 0;
  padding: 12px 12px 14px;
  font: inherit;
  text-align: left;
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-l);
  cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur-fast);
}
.pcard:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 8px 22px var(--shadow); border-color: var(--accent); }
.pcard:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.pcard:disabled { cursor: progress; opacity: 0.8; }
.pcard-text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pcard-title { font-family: var(--serif); font-size: 1.12rem; font-weight: 600; line-height: 1.2; overflow-wrap: anywhere; }
.pcard-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 0.82rem; color: var(--ink-soft); }

.feature { position: relative; padding: 14px; }
.feature .feature-title { font-size: 1.35rem; }
.feature-tag {
  position: absolute;
  top: -12px; left: 18px;
  z-index: 2;
  padding: 3px 12px;
  font-family: var(--hand);
  font-size: 1.05rem;
  font-weight: 600;
  background: var(--menu-tag-bg);
  color: var(--menu-tag-ink);
  transform: rotate(-2deg);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
  background: var(--paper-2);
  color: var(--ink-soft);
}
.badge-ok { color: var(--ok); box-shadow: inset 0 0 0 1px currentColor; background: transparent; }
.badge-acc { background: var(--accent-soft); color: var(--accent); }
.badge-eosin { background: var(--menu-tag-bg); color: var(--menu-tag-ink); }

/* All puzzles */
.menu-rule { border: 0; border-top: 1px solid var(--rule); margin: 0; }
.menu-all { padding-block: 26px 10px; }
.section-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 18px; }
.section-head h2 { margin: 0; font-size: 1.5rem; }
.puzzle-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.puzzle-grid > li { display: flex; min-width: 0; }
.archive-empty { color: var(--ink-soft); font-style: italic; }

/* Footer */
.site-foot {
  margin-top: 40px;
  border-top: 1px solid var(--panel-edge);
  padding-block: 22px calc(22px + env(safe-area-inset-bottom, 0px));
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.site-foot-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 28px; }
.site-foot p { margin: 0; max-width: 70ch; }
.site-foot a { color: var(--ink-soft); }
.site-foot a:hover { color: var(--accent); }

@media (max-width: 860px) {
  .hero { grid-template-columns: minmax(0, 1fr); padding-top: 30px; }
  .hero .feature { margin-top: 8px; }
}
@media (max-width: 560px) {
  .menu-wrap { padding-inline: 16px; }
  .site-head-actions a.head-submit { display: none; } /* still in the hero and the footer */
  .brand-name small { white-space: normal; letter-spacing: 0.08em; }
  .site-head-row { gap: 10px; }
  .hero-actions .btn { flex: 1 1 100%; }
  .puzzle-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .pcard, .pcard:hover:not(:disabled) { transition: none; transform: none; }
}

/* Shared panel-open animation (used by the hints and settings panels). */
@keyframes puzzle-select-in {
  from { opacity: 0; transform: scaleY(0.93) translateY(-4px); }
  to   { opacity: 1; transform: scaleY(1) translateY(0); }
}

.toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.96rem;
  cursor: pointer;
}
.toggle-row input { width: 18px; height: 18px; accent-color: var(--accent); }

/* ── Play screen chrome ──────────────────────────────────────────── */

.screen-play {
  height: 100dvh;
  max-width: 1720px;
  margin: 0 auto;
  padding-top: 10px;
  padding-right: max(16px, env(safe-area-inset-right));
  padding-bottom: calc(12px + env(safe-area-inset-bottom));
  padding-left: max(16px, env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* The desk fills the play area; the microscope viewer overlays its left edge
   on wide screens so it does not consume tabletop width. */
.play-main {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  gap: 14px;
  position: relative;
  z-index: 2;
}

/* full-width tray HUD bar pinned at the bottom of the play column */
.tray-hud {
  flex: 0 0 auto;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 2px solid var(--panel-edge);
  position: relative;
  /* z-index 1 is intentionally below .play-main (z-index 2); staged pieces
     are sized by --slot-scale so they stay inside their slot and never
     visually reach the Lock In button. Dragging pieces (z ≥ 10) still paint
     above all tray content as expected. */
  z-index: 1;
}

.play-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding: calc(4px + env(safe-area-inset-top)) 4px 10px;
  border-bottom: 1px solid var(--panel-edge);
  margin-bottom: 12px;
}
.play-header-title h1 { font-size: 1.3rem; margin: 0; }
.play-header-title p { margin: 0; color: var(--ink-soft); font-size: 0.85rem; }

.mistake-tracker {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.mistake-tracker .pips { display: flex; gap: 7px; }
.pip {
  width: 13px; height: 13px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  background: var(--accent);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.pip.used { background: transparent; transform: scale(0.9); }

.play-actions { display: flex; gap: 8px; }
.play-actions .btn { padding: 0.5em 0.9em; font-size: 0.88rem; }

/* ══════════ MICROSCOPE VIEWER (permanent, wide, left) ════════════ */

.scope-panel {
  position: absolute;
  top: 0;
  left: 4%;
  z-index: 90 !important;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-l);
  padding: 10px;
  min-width: 0;
}

.scope-display-wrap {
  position: relative;
  flex: 0 0 auto;
  /* dimensions set by game.js sizeViewer(); CSS handles <900px */
  border-radius: var(--r-s);
  overflow: hidden;
  border: 3px solid var(--machine-dark-a);
  background: var(--scope-screen);
  box-shadow: inset 0 0 14px rgba(28, 30, 50, 0.25);
}
.scope-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: default;
  touch-action: auto;
}

/* ══════════════════════ THE DESK (top-down) ══════════════════════ */

.play-area {
  position: relative;
  /* Nothing on the desk is prose — dragging across machine labels, tray
     titles, or Lock In buttons must never start a text selection. */
  -webkit-user-select: none;
  user-select: none;
}

.play-area {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  /* Pieces can be deliberately dragged down toward the tray HUD. Let the
     piece layer paint into that gap instead of clipping at the desk edge. */
  overflow: visible;
  width: 100%;
}
.wall-area {
  position: relative;
  flex: 0 0 clamp(260px, 34vh, 320px);
  min-height: 260px;
  overflow: hidden;
  border: 1px solid var(--panel-edge);
  border-radius: 16px 16px 8px 8px;
  background:
    repeating-linear-gradient(0deg, rgba(28, 26, 46, 0.03) 0 2px, transparent 2px 7px),
    linear-gradient(180deg, var(--wall-a), var(--wall-b));
  box-shadow: inset 0 -6px 14px rgba(28, 26, 46, 0.1), 0 2px 7px var(--shadow);
}
.wall-title {
  position: absolute;
  left: 16px;
  top: 12px;
  color: var(--wall-ink);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.xray-rack {
  position: absolute;
  left: 48%;
  right: 6%;
  top: 20px;
  /* The film center is the rack center. The rack's top edge is therefore
     exactly the top edge of every hanging film. */
  height: 148px;
  z-index: 1;
}
.xray-rack::before,
.xray-rack::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 5px;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--machine-dark-a), var(--machine-dark-b));
  box-shadow: 0 2px 3px rgba(16, 18, 26, 0.25);
}
.xray-rack::before { top: 0; }
.xray-rack::after { top: 7px; height: 2px; opacity: 0.75; }
.xray-rack-label {
  position: absolute;
  left: 5px;
  top: -17px;
  color: var(--wall-ink);
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.xray-rail {
  position: absolute;
  inset: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  border-bottom: 1px solid rgba(28, 26, 46, 0.16);
}
.desk-surface {
  position: relative;
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
  border-radius: 16px;
  border: 1px solid var(--desk-edge);
  /* Slate lab bench: faint stone streaks + a cool overhead light pool. */
  background-image:
    radial-gradient(ellipse at 50% 30%, rgba(230, 236, 255, 0.10) 0, transparent 60%),
    repeating-linear-gradient(94deg,
      rgba(0, 0, 0, 0.035) 0 3px, transparent 3px 13px),
    linear-gradient(160deg, var(--desk-hi), var(--desk-mid) 55%, var(--desk-lo));
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.15),
    inset 0 2px 6px rgba(255, 255, 255, 0.08),
    0 10px 30px var(--shadow);
}
/* Photo desk texture (assets/textures/desk.webp). Inert since the stain-room
   restyle: textures.js skips desk.webp so the slate bench above shows. */
.desk-surface.textured {
  background-image: var(--tex-desk);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* ── Machines and wall furniture ────────────────────────────────── */

.machine {
  position: absolute;
  top: 14px;
  z-index: 1;
}
.machine-label {
  position: absolute;
  left: 0; right: 0;
  bottom: -20px;
  margin: 0;
  text-align: center;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  font-weight: 700;
  color: var(--bench-label);
  text-shadow: 0 1px 2px rgba(10, 12, 20, 0.5);
  white-space: nowrap;
}
.machine-caption {
  position: absolute;
  bottom: 4px;
  left: 0; right: 0;
  text-align: center;
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--bench-label);
}

/* Microscope stage (drop target; the display lives in the left panel). */
.machine-scope { left: 0; }
.scope-stage {
  position: relative;
  width: 116px;
  height: 116px;
  border-radius: 14px;
  background: linear-gradient(160deg, var(--machine-dark-a), var(--machine-dark-b));
  border: 2px solid rgba(235, 238, 248, 0.22);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4), 0 3px 8px rgba(10, 12, 20, 0.3);
}
.scope-stage-glass {
  position: absolute;
  top: 50%; left: 50%;
  width: 78px; height: 78px;
  transform: translate(-50%, -54%);
  border-radius: 50%;
  background: radial-gradient(circle at 45% 40%, var(--stage-glass-a), var(--stage-glass-b) 55%, var(--stage-glass-c));
  box-shadow: 0 0 14px var(--stage-glass-glow), inset 0 0 8px rgba(60, 66, 96, 0.3);
}
.scope-stage.drop-hot { outline: 3px dashed var(--accent-soft); outline-offset: 3px; }

/* Wall lightbox: fixed above the desk. Films reveal their content only
   where they physically overlap it (clip-path on .film-lit). */
.machine-lightbox {
  top: 20px;
  right: 5%;
  z-index: 2;
}
.lightbox-screen {
  position: relative;
  width: 220px;
  height: 240px;
  border-radius: 10px;
  border: 7px solid var(--machine-dark-a);
  /* Cool daylight-white viewer glow. */
  background: radial-gradient(ellipse at 50% 40%, var(--lightbox-a), var(--lightbox-b) 70%, var(--lightbox-c));
  box-shadow:
    0 0 22px var(--lightbox-glow),
    0 4px 0 var(--machine-dark-b),
    0 7px 10px rgba(10, 12, 20, 0.35),
    inset 0 0 10px rgba(60, 66, 96, 0.25);
}
.lightbox-screen::before {
  content: "";
  position: absolute;
  inset: 7px;
  border: 1px solid rgba(60, 66, 96, 0.35);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25);
  pointer-events: none;
}
.lightbox-screen::after {
  content: "•   •";
  position: absolute;
  right: 9px;
  bottom: -22px;
  color: var(--machine-dark-b);
  font: 700 11px/1 var(--mono);
  letter-spacing: 0.25em;
  pointer-events: none;
}
/* .label-chip removed in v15 — printer label counter chips are retired. */
.machine-printer.drop-hot .printer-body { outline: 3px dashed var(--accent-soft); outline-offset: 3px; }

/* ── Group trays ─────────────────────────────────────────────────── */

.trays {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 14px;
}

.tray {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  padding: 10px;
  box-shadow: 0 1px 0 var(--panel-edge);
  min-width: 0; /* grid items default to min-width:auto (content-sized) —
    without this a tray's own 2x2 slot grid (each slot floored by
    aspect-ratio + min-height) refuses to shrink below its natural size
    and overflows the 2-column .trays grid on narrow phones. */
  transition: background var(--dur) var(--ease), box-shadow var(--dur);
}
.tray.drop-hot { box-shadow: 0 0 0 3px var(--accent); }
.tray.is-locked { background: var(--group-color, var(--accent-soft)); border-color: transparent; }

.tray-header {
  text-align: center;
  font-family: var(--sans);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--ink-soft);
  padding: 4px 4px 8px;
}
.tray.is-locked .tray-header {
  color: var(--group-ink, var(--ink));
  font-family: var(--serif);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  text-transform: none;
}

.tray-slots {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  min-width: 0;
}
.tray-slot {
  aspect-ratio: 5 / 3;
  min-height: 48px;
  min-width: 0;
  border: 1.5px dashed var(--panel-edge);
  border-radius: 8px;
  background: var(--slot-bg);
  box-shadow: var(--slot-well);
  transition: border-color var(--dur-fast);
}
.tray.is-locked .tray-slot {
  border-color: transparent;
  background: var(--slot-bg-locked);
}
.tray-slot.wrong-shake { animation: shake 0.35s var(--ease); }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
}

/* ── One-away tray pulse ─────────────────────────────────────────── */
.tray.is-one-away { animation: tray-one-away 1.2s var(--ease); }
@keyframes tray-one-away {
  0%   { box-shadow: none; }
  15%  { box-shadow: 0 0 0 4px var(--eosin); }
  70%  { box-shadow: 0 0 0 4px var(--eosin); }
  100% { box-shadow: none; }
}

/* ── Wrong-submit tray flash + piece shake ───────────────────────── */
.tray.is-wrong { animation: tray-wrong 0.4s var(--ease); }
@keyframes tray-wrong {
  0%   { box-shadow: none; }
  30%  { box-shadow: 0 0 0 2px var(--danger); }
  70%  { box-shadow: 0 0 0 2px var(--danger); }
  100% { box-shadow: none; }
}
.piece.is-shake { animation: piece-shake 0.4s var(--ease); }
@keyframes piece-shake {
  0%, 100% { translate: 0; }
  20%      { translate: -5px 0; }
  40%      { translate: 5px 0; }
  60%      { translate: -4px 0; }
  80%      { translate: 4px 0; }
}

.btn-lock { width: 100%; margin-top: 8px; }

/* ══════════════════════ PIECES ══════════════════════ */

.piece-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 40;
}
.piece-layer.no-anim .piece { transition: none !important; }

.piece {
  all: unset;
  box-sizing: border-box;
  position: absolute;
  left: 0; top: 0;
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  --responsive-scale: 1;
  max-width: calc(100% - 12px);
  transform: translate(-50%, -50%) rotate(var(--rot, 0deg)) scale(calc(var(--pc-scale, 1) * var(--type-scale, 1) * var(--responsive-scale) * var(--slot-scale, 1)));
  transition:
    left var(--dur) var(--ease),
    top var(--dur) var(--ease),
    transform var(--dur) var(--ease),
    box-shadow var(--dur-fast),
    opacity var(--dur);
  /* Prefer normal word wrapping; only break inside a word when it has no
     other way to fit (overflow-wrap), rather than the more aggressive
     word-break: break-word, which could split short words even when a
     plain line break would have worked — a source of the "ugly" breaks
     the auto-fit sizing below is meant to clean up. */
  overflow-wrap: break-word;
  word-break: normal;
}
.piece:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.piece.is-dragging {
  transition: none;
  cursor: grabbing;
  --pc-scale: 1.07;
  filter: drop-shadow(0 8px 14px rgba(36, 31, 20, 0.35));
}
.piece.is-locked { cursor: default; }
.piece.in-tray { --pc-scale: 0.82; }
.piece.on-machine { --pc-scale: 0.9; }

/* Clue-label auto-fit (game.js fitPieceLabels()): shrinks long labels down
   toward a readable floor so they wrap onto a tidy number of lines instead
   of overflowing the piece. --fit-scale is written per-piece by JS after
   measuring; it defaults to 1 (no-op) so puzzles with no long labels, and
   any piece before the first fit pass runs, render unchanged. Balanced
   wrapping keeps the last line from reading as a lonely short word, where
   the browser supports it. */
.piece-label,
.rx-line,
.photo-caption {
  font-size: calc(1em * var(--fit-scale, 1));
  text-wrap: balance;
}

/* Handwritten clue labels — applied only when the texture pass is live,
   so the plain-CSS build looks exactly as it did before. */
body.has-textures .piece-label {
  font-family: var(--hand);
  color: #2b2b33;
  display: block;
  width: 100%;
  max-width: 100%;
  transform: rotate(var(--ink-rot, 0deg));
  font-size: calc(1em * var(--ink-size, 1) * var(--fit-scale, 1));
}

/* Written clues are flex children inside their paper faces. Give the text a
   real containing width; otherwise an inline/handwritten label can size
   itself to its longest line and paint outside the card. */
.piece .piece-label,
.piece .rx-line {
  display: block;
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
  hyphens: auto;
  text-align: center;
}

/* Generated object textures include transparent padding and irregular edges.
   Keep the complete cutout visible rather than cropping it into the CSS box,
   and let the shadow follow the cutout's alpha instead of the box. */
body.has-textures .piece.textured {
  background-color: transparent;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  border-color: transparent;
  box-shadow: none;
  filter: drop-shadow(0 3px 5px rgba(36, 31, 20, 0.32));
}
body.has-textures .piece.textured.is-dragging {
  filter: drop-shadow(0 8px 14px rgba(36, 31, 20, 0.35));
}

/* Sticky note (corkboard items). */
.piece-sticky {
  --type-scale: var(--scale-sticky, 1);
  width: 96px;
  min-height: 88px;
  padding: 10px;
  background: var(--pc-color, #f6e58d);
  box-shadow: 0 3px 7px rgba(36, 31, 20, 0.28), inset 0 0 0 1px rgba(36, 31, 20, 0.06);
  font-size: 1.02rem;
  line-height: 1.24;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
}
.piece-sticky::after {
  content: "";
  position: absolute;
  top: 3px; right: 5px;
  width: 22px; height: 12px;
  background: rgba(255, 255, 255, 0.4);
  transform: rotate(-4deg);
}
.piece-sticky.textured::after { content: none; }
.piece-sticky .piece-skin { background-size: 100% 100%; }

/* Paper sheet (folder items). */
.piece-paper {
  --type-scale: var(--scale-paper, 1);
  width: 80px;
  min-height: 100px;
  padding: 10px 8px;
  background: #fbf6e9;
  border: 1px solid rgba(36, 31, 20, 0.18);
  box-shadow: 0 3px 7px rgba(36, 31, 20, 0.25);
  font-size: 0.92rem;
  line-height: 1.24;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  background-image: repeating-linear-gradient(180deg, transparent 0 14px, rgba(36, 31, 20, 0.07) 14px 15px);
}
/* The ruled-line placeholder is CSS-drawn paper; once a real paper texture
   loads it renders on the .piece-skin child instead, so the ruled lines
   must not keep bleeding through underneath it. */
.piece-paper.textured { background-image: none; }

/* Index card (deskCards items). */
.piece-card {
  --type-scale: var(--scale-card, 1);
  width: 98px;
  min-height: 62px;
  padding: 8px;
  background: #f8f2e0;
  border: 1px solid rgba(36, 31, 20, 0.18);
  box-shadow: 0 3px 7px rgba(36, 31, 20, 0.25);
  font-size: 0.94rem;
  line-height: 1.24;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  background-image: linear-gradient(rgba(178, 58, 47, 0.35) 0 1.5px, transparent 1.5px);
  background-size: 100% 15px;
  background-position: 0 9px;
}

/* Microscope slide (rack items) — NOT legible on the piece. */
.piece-slide {
  --type-scale: var(--scale-slide, 1);
  width: 96px;
  height: 44px;
  border-radius: 3px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.2)),
    radial-gradient(ellipse at 62% 55%, rgba(214, 120, 150, 0.5), rgba(214, 120, 150, 0.08) 65%),
    #eef1ec;
  border: 1px solid rgba(36, 31, 20, 0.25);
  box-shadow: 0 2px 5px rgba(36, 31, 20, 0.22);
  display: flex;
  align-items: center;
}
.piece-slide.textured { background-image: var(--tex-slide); }
/* The photo slide brings its own frosted end — keep the band transparent
   so only the slide letter shows over it. */
.piece-slide.textured .piece-frost {
  background: transparent;
  border-left: none;
}
/* The frosted (writing) end is where the letter belongs — slide.webp draws
   it on the right, so push the band there with margin-left:auto instead of
   leaving it as the first (left) flex child, which sat over the clear glass. */
.piece-slide .piece-frost {
  width: 26px;
  align-self: stretch;
  margin-left: auto;
  background: rgba(255, 255, 255, 0.75);
  border-left: 1px solid rgba(36, 31, 20, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.piece-etch {
  font-size: 6px;
  color: rgba(60, 50, 30, 0.6);
  filter: blur(1.3px);
  transform: rotate(-90deg);
  white-space: nowrap;
  pointer-events: none;
}

/* X-ray film (tubes items) — dark; its content lights up ONLY where the
   film overlaps the light box (clip-path set by game.js). Films never
   rotate so the rect intersection stays exact. */
.piece-film {
  --type-scale: var(--scale-film, 1);
  width: 118px;
  height: 148px;
  border-radius: 4px;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(232, 236, 244, 0.10) 0 18%, transparent 55%),
    linear-gradient(160deg, #2a2e36, #1a1d22);
  border: 2px solid rgba(232, 236, 244, 0.14);
  box-shadow: 0 3px 7px rgba(8, 10, 16, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 4px;
}
/* film-lit fills the same box as .piece-film and needs its own corner
   rounding + edge clip now that overflow:hidden moved off the piece
   itself, so the light-through layer can clip cleanly to the overlap. */
.film-lit { border-radius: 4px; overflow: hidden; }
.piece-film.textured { background-image: var(--tex-film); }
/* Light must only shine through the actual film cutout, not the box
   corners around it — mask the lit layer with the film texture's alpha,
   sized to match the contain-fitted background underneath. (The old baked
   border this piece once had is gone now that textures are alpha-trimmed
   at load — game.js's updateFilmLighting() clips the lit layer to the plain
   geometric intersection of the film element's rect with the light box, so
   no manual inset belongs here; a 7%/8% pad used to live on this rule and
   caused the light to land off the film's true edges.) The CSS etch hides —
   it would sit on the photo. */
.piece-film.textured .film-lit {
  -webkit-mask-image: var(--tex-film);
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-image: var(--tex-film);
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
}
.piece-film.textured > .piece-etch { display: none; }
.piece-film.is-dragging { --pc-scale: 1; } /* keep rect math exact while lit */
.piece-film .piece-etch {
  transform: none;
  color: rgba(232, 236, 244, 0.4);
  filter: blur(1.2px);
  font-size: 6px;
}
.film-lit {
  position: absolute;
  inset: 0;
  clip-path: inset(100%);
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse at 50% 45%, rgba(240, 244, 255, 0.30) 0 30%, transparent 70%),
    linear-gradient(165deg, #3f4452, #2e323d);
  background-size: cover;
  background-position: center;
}
.film-lit-label {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #f1f3fa;
  text-shadow:
    0 0 6px rgba(241, 243, 250, 0.9),
    0 0 16px rgba(200, 210, 240, 0.7);
  text-align: center;
  padding: 0 6px;
  position: relative;
  z-index: 1;
}
/* faint ribs behind the lit label */
.film-lit::before {
  content: "";
  position: absolute;
  top: 18px; left: 50%;
  width: 4px; height: 78px;
  margin-left: -2px;
  background: rgba(241, 243, 250, 0.28);
  border-radius: 2px;
  box-shadow:
    -14px 12px 0 -1px rgba(241, 243, 250, 0.18),
    14px 12px 0 -1px rgba(241, 243, 250, 0.18),
    -11px 30px 0 -1px rgba(241, 243, 250, 0.15),
    11px 30px 0 -1px rgba(241, 243, 250, 0.15),
    -8px 48px 0 -1px rgba(241, 243, 250, 0.12),
    8px 48px 0 -1px rgba(241, 243, 250, 0.12);
}
.film-lit.has-image::before { display: none; }

/* ── Seeded per-piece variety (paper family) ─────────────────────── */

.piece-skin {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--skin-tex, none);
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  transform: scaleX(var(--skin-flip, 1)) skew(var(--skin-skew, 0deg));
  filter: var(--skin-filter, none);
  pointer-events: none;
}
.piece .piece-label { position: relative; z-index: 1; }
body.has-textures .piece.textured .piece-skin ~ .piece-label { text-shadow: 0 1px 1px rgba(255,255,255,0.35); }
/* when the skin carries the texture, the piece box itself goes bare */
body.has-textures .piece.textured .piece-skin[style*="--skin-tex"] { opacity: 1; }

/* ── Photograph (photo) — the image is the clue ──────────────────── */

.piece-photo {
  --type-scale: var(--scale-photo, 1);
  width: 94px;
  height: 110px;
  background: #fdfcf6;
  border: 1px solid rgba(36, 31, 20, 0.2);
  box-shadow: 0 3px 7px rgba(36, 31, 20, 0.28);
  color: var(--ink);
  font-size: 0.72rem;
}
.photo-window {
  position: absolute;
  top: 3px; left: 3px; right: 3px; bottom: 3px;
  background: linear-gradient(150deg, #b7b1a3, #a49e8f);
  background-size: cover;
  background-position: center;
  border-radius: 2px;
  overflow: hidden;
  z-index: 1;
}
.photo-caption {
  position: absolute;
  left: 5px; right: 5px; bottom: 5px;
  width: auto;
  max-width: calc(100% - 10px);
  padding: 3px 4px;
  background: rgba(253, 252, 246, 0.86);
  border-radius: 2px;
  text-align: center;
  z-index: 1;
}

/* ── Prescription script (rx) ────────────────────────────────────── */

.piece-rx {
  --type-scale: var(--scale-rx, 1);
  width: 86px;
  min-height: 106px;
  height: auto;
  background: #fcfaf2;
  border: 1px solid rgba(36, 31, 20, 0.22);
  border-top: 4px solid rgba(75, 63, 176, 0.45);
  box-shadow: 0 3px 7px rgba(36, 31, 20, 0.26);
  color: var(--ink);
  font-size: 0.92rem;
  line-height: 1.24;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px 8px 8px;
}
.rx-glyph {
  position: absolute;
  top: 4px; left: 7px;
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 700;
  color: rgba(75, 63, 176, 0.75);
  z-index: 1;
}
.rx-line { position: relative; z-index: 1; }
/* When the rx texture is present it already carries a printed Rx, so the
   CSS/DOM ℞ glyph would double it up — hide the glyph in that case only.
   Texture absent (no .textured class) keeps the drawn glyph. */
.piece-rx.textured .rx-glyph { display: none; }

/* ── Slide letters (A, B, C… — identifiers, not clue text) ──────── */

.slide-letter {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: rgba(28, 26, 46, 0.75);
  z-index: 1;
}

.scope-slide-title {
  position: absolute;
  top: 8px; left: 10px;
  z-index: 2;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  border: 1px solid var(--panel-edge);
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.scope-slide-title:empty { display: none; }

/* ── Guesses left (the redesigned mistake tracker) ───────────────── */

.guesses {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  padding: 7px 14px;
}
.guesses-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--ink-soft);
}
.guesses .pips { display: flex; gap: 8px; }
.guesses .pip {
  width: 16px; height: 16px;
  border: 2.5px solid var(--ink-soft);
  background: var(--ink-soft);   /* tier-agnostic neutral */
}
.guesses .pip.used {
  background: transparent;
  border-style: dashed;
  transform: scale(0.85) rotate(24deg);
}
.guesses .pip.just-broke { animation: pip-break 0.5s var(--ease); }
@keyframes pip-break {
  0% { transform: scale(1.3); border-style: solid; }
  55% { transform: scale(0.75) rotate(32deg); }
  100% { transform: scale(0.85) rotate(24deg); }
}
.guesses-count {
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--ink);
  min-width: 1.1ch;
  text-align: center;
}
.guesses.wrong-feedback { animation: guess-shake 0.45s var(--ease); }
@keyframes guess-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) {
  /* animations collapse globally — hold a static flash instead */
  .guesses.wrong-feedback { outline: 3px solid var(--danger); outline-offset: 2px; }
}

/* ── Toast ───────────────────────────────────────────────────────── */

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  background: var(--toast-bg);
  color: var(--toast-ink);
  padding: 10px 20px;
  border-radius: var(--r-m);
  font-size: 0.9rem;
  font-weight: 600;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
  z-index: 150;
  opacity: 0;
  transition: opacity var(--dur), transform var(--dur) var(--ease);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }

/* ── Viewport health tip ─────────────────────────────────────────── */

.viewport-tip {
  position: fixed;
  top: 72px;
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  padding: 10px 12px 10px 14px;
  width: max-content;
  max-width: min(340px, calc(100vw - 32px));
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  z-index: 60;
  display: flex;
  gap: 10px;
  align-items: flex-start;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  pointer-events: none;
}
.viewport-tip.tip-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.viewport-tip-body { flex: 1 1 auto; min-width: 0; }
.viewport-tip-title {
  font-family: var(--serif);
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 3px;
}
.viewport-tip-text {
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin: 0;
  line-height: 1.4;
}
.viewport-tip-dismiss {
  all: unset;
  box-sizing: border-box;
  flex: 0 0 auto;
  padding: 2px 4px;
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1;
  border-radius: var(--r-s);
  transition: color var(--dur-fast), background var(--dur-fast);
  min-width: 24px;
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.viewport-tip-dismiss:hover { color: var(--ink); background: var(--accent-soft); }
.viewport-tip-dismiss:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* ── Overlays ────────────────────────────────────────────────────── */

.overlay {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}
.overlay-card {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  padding: 26px 28px;
  max-width: 560px;
  width: 100%;
  min-width: 0; /* flex item of .overlay — don't let content push it wider */
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
  animation: overlay-in var(--dur) var(--ease);
}
@keyframes overlay-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.overlay-actions { display: flex; justify-content: flex-end; margin-top: 16px; }

/* ── Start-of-game clue guide ────────────────────────────────────── */
.clue-guide-card { max-width: min(790px, 100%); }
.clue-guide-kicker {
  margin: 0 0 4px;
  color: var(--accent);
  font: 800 0.7rem/1 var(--sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.clue-guide-card h2 { margin-bottom: 16px; }
.clue-guide-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.clue-guide-step {
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  background: var(--card);
}
.clue-guide-visual {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: 9px;
  border-radius: 7px;
  background: color-mix(in srgb, var(--accent-soft) 72%, var(--panel));
}
.guide-prop-demo {
  height: 120px;
  display: grid;
  place-items: center;
  overflow: visible;
}
.guide-demo-stage {
  width: 106px;
  height: 106px;
}
.guide-demo-stage .scope-stage-glass { width: 70px; height: 70px; }
.guide-slide-asset {
  position: absolute;
  z-index: 2;
  top: 39px;
  left: 8px;
  width: 90px;
  height: 29px;
  border-radius: 2px;
  background: url("assets/textures/slide.webp") center / 100% 100% no-repeat;
  box-shadow: 0 2px 4px rgba(20, 14, 6, 0.35);
  transform: rotate(-2deg);
}
.guide-demo-lightbox {
  width: 132px;
  height: 108px;
  border-width: 4px;
}
.guide-demo-lightbox::before { inset: 4px; }
.guide-demo-lightbox::after { display: none; }
.guide-film-asset {
  position: absolute;
  z-index: 2;
  top: -8px;
  left: calc(50% - 34px);
  width: 68px;
  height: 116px;
  border-radius: 3px;
  background: url("assets/textures/film.webp") center / 100% 100% no-repeat;
  box-shadow: 0 3px 6px rgba(20, 14, 6, 0.38);
}
.clue-guide-step h3 {
  margin: 0 0 4px;
  font: 700 0.92rem/1.2 var(--sans);
}
.clue-guide-step p {
  margin: 0;
  color: var(--ink-soft);
  font: 0.84rem/1.35 var(--sans);
}

.results-card {
  max-width: min(980px, 94vw);
  max-height: 90vh;
  padding: 22px 24px 26px;
}

/* ── Results hero: the closed case file ── */
.results-hero {
  position: relative;
  background: var(--card);
  border: 1px solid var(--panel-edge);
  border-radius: 16px;
  padding: 22px 24px 20px;
  overflow: hidden;
}
.results-hero::before {
  content: "";
  position: absolute;
  left: 24px; top: 0;
  width: 120px; height: 5px;
  /* the four stains, easiest to hardest */
  background: linear-gradient(90deg, var(--tier-1) 0 25%, var(--tier-2) 25% 50%, var(--tier-3) 50% 75%, var(--tier-4) 75%);
  border-radius: 0 0 6px 6px;
}
.results-eyebrow,
.results-stat-k {
  font: 600 0.68rem/1 var(--mono);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}
.results-hero h2 {
  font: 600 1.95rem/1.1 var(--serif);
  margin: 8px 0 6px;
  padding-right: 150px;
}
#results-sub { color: var(--ink-soft); margin: 0; }
.results-credit { font: 600 0.8rem/1.3 var(--mono); letter-spacing: 0.04em; color: var(--ink-soft); margin: 0 0 6px; }
.results-stamp {
  position: absolute;
  right: 22px; top: 22px;
  font: 800 0.9rem/1 var(--mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--danger);
  border: 3px solid var(--danger);
  border-radius: 6px;
  padding: 8px 11px;
  transform: rotate(-8deg);
  opacity: 0.85;
}
.results-stamp.is-stamped { animation: results-stamp 0.5s 0.35s cubic-bezier(.3, 1.6, .5, 1) both; }
@keyframes results-stamp {
  from { opacity: 0; transform: rotate(-8deg) scale(2.2); }
  to { opacity: 0.85; transform: rotate(-8deg) scale(1); }
}
.results-stats { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.results-stat {
  flex: 0 1 170px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 12px;
  padding: 11px 13px;
  min-width: 0;
}
.results-stat-hints { flex: 1 1 280px; }
.results-stat-v { font: 600 1.35rem/1.2 var(--serif); margin-top: 7px; }
.results-hint-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.results-hint-chip {
  font: 500 0.76rem/1 var(--sans);
  border: 1px solid var(--panel-edge);
  border-radius: 99px;
  padding: 5px 9px;
  color: var(--ink);
  white-space: nowrap;
}
.results-hint-chip.is-off { opacity: 0.4; text-decoration: line-through; }
.results-path-wrap {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px 24px;
  align-items: center;
  margin-top: 16px;
}
.results-path { display: grid; gap: 5px; margin-top: 10px; }
.results-path-row { display: flex; align-items: center; gap: 5px; animation: results-rise 0.4s var(--ease) both; }
.results-sq { width: 21px; height: 21px; border-radius: 5px; }
.results-path-note { font: 500 0.7rem/1 var(--mono); color: var(--ink-soft); margin-left: 8px; white-space: nowrap; }
.results-path-note.is-bad { color: var(--danger); }
.results-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.results-actions .btn { min-height: 44px; }
.results-actions #btn-share { grid-column: 1 / -1; }
.results-section-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin: 24px 2px 10px;
}
.results-section-head h3 { font: 600 1.2rem/1.2 var(--serif); margin: 0; }
.results-section-head p { margin: 0; color: var(--ink-soft); font-size: 0.8rem; }

/* ── Group rows: stacked full-width strips ── */
.results-groups { display: flex; flex-direction: column; gap: 10px; }
.result-placard {
  background: var(--card);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  overflow: hidden;
  animation: results-rise 0.45s var(--ease) both;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.result-placard:hover,
.result-placard[aria-expanded="true"] {
  border-color: color-mix(in srgb, var(--group-color) 60%, transparent);
}
.result-placard[aria-expanded="true"] { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); }
.result-placard-head {
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr) auto;
  align-items: stretch;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
div.result-placard-head { cursor: default; }
.result-placard-band {
  background: var(--group-color);
  color: var(--group-ink);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 12px 14px;
}
.result-placard-name {
  font: 700 0.72rem/1 var(--mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.result-placard-by { font: 600 0.7rem/1 var(--mono); opacity: 0.8; }
.result-placard-text { display: flex; flex-direction: column; justify-content: center; gap: 4px; padding: 12px 16px; min-width: 0; }
.result-placard h3 { font: 600 1.1rem/1.25 var(--serif); margin: 0; }
.result-placard-explanation { font-size: 0.85rem; color: var(--ink-soft); margin: 0; }
.result-placard-credit { font-size: 0.72rem; color: var(--ink-soft); opacity: 0.85; margin: 0; }
.result-placard-more { font: 600 0.75rem/1 var(--sans); color: color-mix(in srgb, var(--group-color) 45%, var(--ink)); margin-top: 4px; }
.result-placard-more::before { content: "Open notes \2192"; }
.result-placard[aria-expanded="true"] .result-placard-more::before { content: "Close notes \2191"; }
.result-placard-objects {
  display: grid;
  grid-template-columns: repeat(4, 70px);
  gap: 10px;
  padding: 12px 16px 10px 4px;
  align-items: end;
}
.result-obj { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; }
.result-obj-label { font-size: 0.68rem; line-height: 1.15; text-align: center; color: var(--ink-soft); hyphens: manual; }

/* Clue thumbnails drawn as their desk objects */
.rthumb { width: 100%; aspect-ratio: 4 / 5; position: relative; border-radius: 3px; flex: none; }
.rthumb-photo {
  background: #f7f2e6;
  padding: 4px 4px 11px;
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  transform: rotate(var(--r, -2deg));
}
.rthumb-photo span { display: block; width: 100%; height: 100%; background: center / cover no-repeat; }
.rthumb-film {
  background: #0b0d10 center / cover no-repeat;
  border: 3px solid #1b1f25;
  box-shadow: 0 0 0 1px rgba(160, 200, 255, 0.15), 0 0 14px rgba(160, 200, 255, 0.2);
}
.rthumb-scope {
  aspect-ratio: 1;
  border-radius: 50%;
  background: #000 center / 150% no-repeat;
  border: 3px solid #2e2e30;
  box-shadow: inset 0 0 12px rgba(0, 0, 0, 0.8), 0 3px 7px rgba(0, 0, 0, 0.3);
}
.rthumb-sticky {
  aspect-ratio: 1;
  background: #f5dc6a;
  color: #3b3110;
  border-radius: 2px;
  font: 600 0.66rem/1.12 var(--hand);
  padding: 6px 4px;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  hyphens: manual;
  overflow: hidden;
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.28);
  transform: rotate(var(--r, 2deg));
}
.rthumb-rx {
  background: #fbfaf5;
  color: #1d2b3a;
  padding: 5px;
  display: flex; flex-direction: column; gap: 2px;
  overflow: hidden;
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.28);
  background-image: repeating-linear-gradient(transparent 0 13px, rgba(30, 80, 160, 0.12) 13px 14px);
}
.rthumb-rx b { font: 700 1rem/1 var(--serif); color: #2b4a8a; }
.rthumb-rx i { font: 600 0.66rem/1.12 var(--hand); font-style: normal; overflow-wrap: anywhere; }

/* Expanded teaching notes */
.result-teach { display: none; padding: 4px 18px 14px; border-top: 1px solid var(--panel-edge); }
.result-placard[aria-expanded="true"] .result-teach { display: block; }
.result-teach-row {
  display: grid;
  grid-template-columns: 60px 1fr;
  gap: 16px;
  align-items: center;
  padding: 12px 0;
  border-top: 1px dashed var(--panel-edge);
  animation: results-rise 0.3s var(--ease) both;
}
.result-teach-row:first-child { border-top: 0; }
.result-teach-row h4 { margin: 0 0 3px; font: 600 0.98rem/1.25 var(--serif); }
.result-teach-row h4 small {
  font: 500 0.66rem/1 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-left: 7px;
}
.result-teach-row p { margin: 0; font-size: 0.88rem; color: var(--ink-soft); }
.result-anki-chip { margin: 6px 0 0; font: 600 0.7rem/1 var(--mono); color: var(--ink-soft); text-align: right; }
.result-placard .result-article { padding: 0 18px 14px; }
.result-placard .results-preview-hint { padding: 8px 14px 0; }

@keyframes results-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .results-stamp.is-stamped, .results-path-row, .result-placard, .result-teach-row { animation: none; }
}

@media (max-width: 720px) {
  .results-card { padding: 14px 12px 18px; }
  .results-hero { padding: 20px 16px 16px; }
  .results-hero h2 { font-size: 1.55rem; padding-right: 0; margin-top: 46px; }
  .results-stamp { right: 14px; top: 16px; font-size: 0.72rem; padding: 6px 8px; }
  .results-path-wrap { grid-template-columns: 1fr; }
  .results-section-head { flex-direction: column; gap: 2px; }
  .result-placard-head { grid-template-columns: 1fr; }
  .result-placard-band { flex-direction: row; justify-content: space-between; padding: 9px 14px; }
  .result-placard-objects { grid-template-columns: repeat(4, 1fr); padding: 0 14px 12px; }
  .result-teach { padding: 4px 14px 12px; }
  .result-teach-row { grid-template-columns: 52px 1fr; gap: 12px; }
}

/* ── Article body (result-placard's optional long-form explanation) ──
   Web-article typography: serif headings, sans body, a readable measure
   so paragraphs don't stretch edge-to-edge of the near-full-screen card. */
.result-article {
  max-width: 65ch;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--panel-edge);
}
.result-article-heading {
  font-family: var(--serif);
  font-size: 1.05rem;
  margin: 14px 0 6px;
}
.result-article-heading:first-child { margin-top: 0; }
.result-article-text {
  font-family: var(--sans);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 10px;
  white-space: pre-wrap;
}
.result-article-figure {
  margin: 10px 0;
}
.result-article-figure img {
  max-width: 100%;
  border-radius: 8px;
  border: 1px solid var(--panel-edge);
}
.result-article-caption {
  font-family: var(--sans);
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin: 4px 0 0;
  text-align: center;
}

.share-fallback {
  width: 100%;
  margin-top: 12px;
  min-height: 90px;
  font-family: var(--mono);
  font-size: 0.85rem;
  padding: 10px;
  border-radius: 8px;
  border: 1px solid var(--panel-edge);
}

/* ── Error screen ────────────────────────────────────────────────── */

.screen-error {
  display: flex;
  align-items: center;
  justify-content: center;
}
.error-card {
  max-width: 520px;
  background: var(--panel);
  border: 1px solid var(--danger);
  border-radius: 12px;
  padding: 26px 28px;
  text-align: center;
}
.error-message {
  white-space: pre-wrap;
  text-align: left;
  background: rgba(178, 58, 47, 0.08);
  border-radius: 8px;
  padding: 12px;
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--danger);
}

/* ══════════════════════ DEV: LAYOUT MODE (?layout) ══════════════════════ */

.layout-panel {
  position: fixed;
  top: 12px;
  right: 12px;
  width: 270px;
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  background: var(--panel);
  border: 2px solid var(--accent);
  border-radius: 12px;
  padding: 14px 16px;
  z-index: 200;
  font-size: 0.85rem;
}
.layout-panel h2 { font-size: 1rem; margin-bottom: 2px; }
.layout-panel .lp-note { color: var(--ink-soft); font-size: 0.78rem; }
.layout-panel label { display: block; margin: 8px 0 2px; font-weight: 600; font-size: 0.78rem; }
.layout-panel input[type="range"] { width: 100%; accent-color: var(--accent); }
.layout-panel .lp-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.layout-panel .btn { font-size: 0.8rem; padding: 0.4em 0.8em; }
body.layout-mode .machine { cursor: move; outline: 2px dashed rgba(75, 63, 176, 0.6); outline-offset: 3px; }

/* ══════════════════════ DEV: PUZZLE CREATOR (?editor) ══════════════════════ */

/* The live game preview is the whole screen, at true game size — the
   authoring form floats over it as a collapsible drawer (same slide-away
   pattern as the ?layout panel: .panel-tab toggles .panel-hidden). */
.screen-editor {
  max-width: none;
  margin: 0;
  padding: 0;
  min-height: 0;
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* The preview iframe renders at a FIXED logical size (captured once when
   the editor boots) and is scaled down with a CSS transform to fit
   whatever region is left beside the drawer — same trick a game engine
   uses to decouple its render resolution from the window it's shown in.
   .editor-preview-stage is the fit region + dark letterbox surround; the
   iframe's own width/height/transform are set by layoutPreviewStage(). */
.editor-preview-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #17130d;
  overflow: hidden;
}
.editor-preview-stage iframe {
  display: block;
  position: absolute;
  border: none;
  box-shadow: 0 0 40px rgba(0, 0, 0, 0.4);
  transition: transform var(--dur) var(--ease), left var(--dur) var(--ease), top var(--dur) var(--ease);
}
.editor-preview-stage.no-anim iframe { transition: none; }

.editor-drawer {
  position: fixed;
  top: 12px;
  right: 12px;
  width: var(--drawer-w, 400px);
  max-width: calc(100vw - 24px);
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  background: var(--panel);
  border: 2px solid var(--accent);
  border-radius: 12px;
  padding: 14px 16px;
  z-index: 200;
  transition: transform var(--dur) var(--ease);
}
.editor-drawer.panel-hidden { transform: translateX(calc(100% + 20px)); }

.drawer-resize-handle {
  position: absolute;
  top: 0;
  left: -8px;
  width: 14px;
  height: 100%;
  cursor: ew-resize;
  touch-action: none;
  z-index: 5;
  background: transparent;
}
.drawer-resize-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 4px;
  height: 40px;
  border-radius: 3px;
  background: var(--panel-edge);
}
.drawer-resize-handle:hover::after,
.drawer-resize-handle.is-dragging::after {
  background: var(--accent);
}
.editor-drawer h1 { font-size: 1.2rem; margin-bottom: 2px; }
.editor-drawer .editor-sub { color: var(--ink-soft); font-size: 0.78rem; margin-bottom: 12px; }

.editor-topbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
  border: 1px solid var(--panel-edge);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 12px;
}
.status-chip {
  padding: 7px 14px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.85rem;
  align-self: center;
}
.status-chip.ok { background: rgba(79, 107, 69, 0.16); color: #33482c; }
.status-chip.bad { background: rgba(178, 58, 47, 0.13); color: var(--danger); }

.editor-meta { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.editor-meta label { font-size: 0.72rem; font-weight: 700; color: var(--ink-soft); }
.screen-editor input[type="text"], .screen-editor input[type="date"],
.screen-editor select, .screen-editor textarea {
  font-family: inherit;
  font-size: 0.85rem;
  padding: 5px 8px;
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  background: var(--field-bg);
  color: var(--ink);
}
.screen-editor input[type="color"] {
  width: 32px; height: 27px;
  padding: 1px;
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-s);
  background: var(--field-bg);
}

.machine-toggles { display: flex; gap: 14px; flex-wrap: wrap; }
.machine-toggle { font-size: 0.82rem; }
.machine-toggle label { display: flex; gap: 6px; align-items: center; cursor: pointer; font-weight: 600; }
.machine-toggle input { accent-color: var(--accent); width: 16px; height: 16px; }
.machine-warn {
  display: block;
  color: var(--danger);
  font-size: 0.7rem;
  max-width: 190px;
  margin-top: 2px;
}

.editor-actions { display: flex; gap: 8px; flex-wrap: wrap; align-self: center; margin-left: auto; }
.editor-actions .btn { font-size: 0.8rem; padding: 0.45em 0.9em; }

.editor-groups {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.group-card {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-left: 6px solid var(--gc, var(--accent));
  border-radius: 12px;
  padding: 12px 14px;
}
.group-card .gc-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.group-card .gc-row { display: flex; gap: 8px; margin-bottom: 6px; }
.group-card .gc-row input[data-gfield="name"] { flex: 1; font-weight: 700; }
.group-card .gc-row select { width: 88px; }
.group-card input[data-gfield="explanation"] { width: 100%; margin-bottom: 4px; }

.item-editor {
  border: 1px solid var(--panel-edge);
  border-radius: 8px;
  padding: 8px 10px;
  margin-top: 8px;
  background: var(--slot-bg);
}
.item-editor .item-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.item-editor input[data-ifield="label"] { flex: 1; min-width: 110px; }
.item-editor .item-note { display: block; width: 100%; box-sizing: border-box; margin-top: 6px; }
.kind-chips { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
.kind-chip {
  border: 1px solid var(--panel-edge);
  background: var(--control-bg);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 0.7rem;
  cursor: pointer;
  color: var(--ink-soft);
}
.kind-chip.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}
.item-editor details { margin-top: 6px; font-size: 0.75rem; color: var(--ink-soft); }
.item-editor details summary { cursor: pointer; }
.item-editor details .adv-row { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; align-items: center; }
.item-file { font-size: 0.7rem; max-width: 170px; }
.label-scale-row input[type="range"] { flex: 1 1 100px; min-width: 80px; }
.label-scale-readout { font-size: 0.72rem; color: var(--ink-soft); min-width: 32px; text-align: right; }
.label-scale-row .btn { padding: 0.15em 0.6em; font-size: 0.7rem; }
.field-feedback { color: var(--danger); font-size: 0.72rem; margin: 3px 0 0; }

/* ── Article authoring (group-card's collapsible "Article" section) ── */
.article-section {
  margin-top: 10px;
  border: 1px dashed var(--panel-edge);
  border-radius: 8px;
  padding: 8px 10px;
}
.article-section > summary {
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-soft);
}
.article-blocks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.article-block {
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  padding: 6px 8px;
  background: var(--slot-bg);
}
.article-block-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 4px;
}
.article-block-type {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}
.article-block-controls { display: flex; gap: 4px; }
.article-move, .article-remove {
  border: 1px solid var(--panel-edge);
  background: var(--control-bg);
  border-radius: 4px;
  font-size: 0.72rem;
  line-height: 1;
  padding: 3px 6px;
  cursor: pointer;
  color: var(--ink-soft);
}
.article-move:disabled { opacity: 0.35; cursor: default; }
.article-remove { color: var(--danger); }
.article-block input[type="text"],
.article-block textarea {
  width: 100%;
  box-sizing: border-box;
  margin-top: 2px;
}
.article-block textarea { resize: vertical; font-family: inherit; }

/* ── Rich text toolbar + contenteditable (article heading/text) ─────
   Storage is always the sanitizer's restricted-HTML subset — see
   sanitizeRichHtml() in game.js — these are just the authoring chrome. */
.rich-toolbar { display: flex; gap: 4px; margin-bottom: 4px; }
.rich-btn {
  border: 1px solid var(--panel-edge);
  background: var(--control-bg);
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  padding: 4px 9px;
  min-width: 26px;
  cursor: pointer;
  color: var(--ink-soft);
}
.rich-btn:hover { background: var(--accent-soft); border-color: var(--accent); }
.rich-btn-clear { font-weight: 400; font-size: 0.68rem; }
.rich-editable {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  padding: 6px 8px;
  background: var(--field-bg);
  color: var(--ink);
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1.4;
  outline: none;
}
.rich-editable:focus { border-color: var(--accent); }
.rich-editable-text { min-height: 60px; }
.rich-editable-heading { min-height: 22px; font-weight: 700; }
.rich-editable:empty::before {
  content: attr(data-placeholder);
  color: var(--ink-soft);
  opacity: 0.7;
}
.article-add-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.article-add-btn { font-size: 0.72rem; padding: 4px 9px; }

.editor-drawer .preview-note { font-size: 0.72rem; color: var(--ink-soft); margin: 10px 0 0; }

/* ── Image upload crop modal ─────────────────────────────────────── */
.crop-overlay { z-index: 260; } /* above the layout/editor panels (z:200-210) */
.crop-card { max-width: 420px; }
.crop-frame {
  display: flex;
  justify-content: center;
  margin: 10px 0;
}
.crop-canvas {
  width: 100%;
  max-width: 340px;
  aspect-ratio: 4 / 3;
  height: auto;
  border-radius: 8px;
  border: 1px solid var(--panel-edge);
  background: var(--control-bg);
  cursor: grab;
  touch-action: none;
}
.crop-canvas:active { cursor: grabbing; }
.crop-controls { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.crop-controls label { display: flex; align-items: center; gap: 8px; width: 100%; font-size: 0.85rem; color: var(--ink-soft); }
.crop-controls input[type="range"] { flex: 1; }
.crop-instructions { font-size: 0.78rem; color: var(--ink-soft); margin: 0 0 4px; }

/* the game embedded as a live preview strips its chrome */
body.preview-mode .play-actions,
body.preview-mode .play-header-title p { display: none; }

@media (max-width: 640px) {
  .editor-drawer { width: calc(100vw - 24px); }
}

/* ── Settings dropdown panel ─────────────────────────────────────── */

.settings-wrap { position: relative; }
.settings-panel {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  left: auto;
  min-width: 260px;
  max-width: min(320px, 90vw);
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
  z-index: 200;
  padding: 12px;
  animation: puzzle-select-in var(--dur) var(--ease);
}
.settings-panel .settings-group { margin-bottom: 10px; }
.settings-panel .settings-group:last-of-type { margin-bottom: 0; }
.settings-panel .toggle-row { min-height: 44px; }
.settings-panel .overlay-actions { margin-top: 10px; }

/* ── Settings content (shared by dropdown panel) ─────────────────── */

.settings-group {
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  padding: 12px 14px;
  margin: 0 0 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.settings-group legend {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--ink-soft);
  padding: 0 6px;
}
.settings-dev { border-style: dashed; }
.settings-dev-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--ink-soft);
  margin: 0;
}

/* ── Dev panel: collapsible sections + slide-away (both editors) ─── */

.layout-panel { border-radius: var(--r-l); transition: transform var(--dur) var(--ease); }
.layout-panel.panel-hidden { transform: translateX(calc(100% + 20px)); }
.panel-tab {
  position: fixed;
  top: 16px;
  right: 12px;
  z-index: 210;
  writing-mode: vertical-rl;
  padding: 10px 4px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--accent-ink);
  border: none;
  border-radius: var(--r-s);
  cursor: pointer;
}
.dev-section { border-top: 1px solid var(--panel-edge); margin-top: 10px; padding-top: 4px; }
.dev-section > summary {
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
  padding: 6px 0;
  list-style: none;
}
.dev-section > summary::before { content: "▸ "; }
.dev-section[open] > summary::before { content: "▾ "; }
.dev-section .cue-row { display: flex; align-items: center; gap: 6px; }
.dev-section .cue-row .btn { padding: 0.15em 0.5em; font-size: 0.7rem; }
.dev-section .cue-row input[type="range"] { flex: 1; }
.dev-section .cue-row .cue-name { font-size: 0.72rem; width: 86px; color: var(--ink-soft); }

.group-card > summary {
  cursor: pointer;
  list-style: none;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.group-card > summary::before { content: "▸ "; }
.group-card[open] > summary::before { content: "▾ "; }

/* ══════════════════════ HINTS SYSTEM (v15) ══════════════════════ */

/* Hints button wrapper — relative so the panel can anchor to it.
   Sits in the play header, immediately left of the mistake tracker.
   margin-left: auto absorbs flex slack, pushing hints+mistakes to the
   right cluster while the title/date occupy the left. */
.hints-wrap { position: relative; margin-left: auto; }
.hints-wrap #btn-hints {
  min-width: 110px;
  padding: 0.5em 1.2em;
  font-size: 0.88rem;
}

/* Hints dropdown panel — anchors to right edge of the button so it
   stays inside the viewport now that the button lives at the right. */
.hints-panel {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  left: auto;
  min-width: 280px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
  z-index: 200;
  padding: 8px;
  animation: puzzle-select-in var(--dur) var(--ease);
}

.hint-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 6px;
  border-radius: var(--r-s);
  transition: background var(--dur-fast);
}
.hint-row + .hint-row { border-top: 1px solid var(--panel-edge); }
.hint-row-used { opacity: 0.55; }
.hint-row-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.hint-row-name {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.3;
}
.hint-row-desc {
  font-size: 0.8rem;
  color: var(--ink-soft);
  line-height: 1.4;
}
.hint-row-reason {
  font-size: 0.75rem;
  color: var(--ink-soft);
  font-style: italic;
  margin-top: 2px;
}
.hint-row-btn {
  flex-shrink: 0;
  font-size: 0.8rem;
  padding: 0.3em 0.75em;
  min-width: 46px;
  align-self: center;
}
.hint-row-btn:disabled { opacity: 0.45; cursor: default; }

/* ── H1: ID tags on image pieces ─────────────────────────────── */

/* Machine-stamp look: slightly different tint from .hint-label
   so clue-labels (warm cream) and id-tags (cool grey-blue) read differently. */
.id-tag {
  position: absolute;
  left: 50%;
  top: -8px;
  transform: translateX(-50%) rotate(1deg);
  background: #e8edf2;
  border: 1px solid rgba(60, 80, 110, 0.38);
  border-radius: 2px;
  padding: 1px 5px;
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #253648;
  box-shadow: 0 1px 3px rgba(36, 31, 20, 0.28);
  pointer-events: none;
  white-space: nowrap;
  z-index: 6;
}
:root[data-theme="dark"] .id-tag {
  background: #2e3843;
  border-color: rgba(140, 170, 210, 0.35);
  color: #b8cde0;
}

/* ── H2: Pin marker on staged pieces ─────────────────────────── */

.pin-marker {
  position: absolute;
  top: -6px;
  right: -3px;
  width: 11px;
  height: 11px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  background: var(--accent);
  border: 1.5px solid var(--accent-ink);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  z-index: 7;
}

/* ── Peek-viewable pinned pieces (rack / tubes only) ─────────── */

/* zoom-in cursor signals that tapping/pressing V opens a viewer */
.piece-peekable { cursor: zoom-in; }

/* Small loupe badge — sits at bottom-right, mirrors pin-marker style */
.peek-loupe {
  position: absolute;
  bottom: -5px;
  right: -3px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  border: 1.5px solid var(--accent-ink);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  z-index: 7;
  display: flex;
  align-items: center;
  justify-content: center;
}
.peek-loupe::after {
  content: "\29BF"; /* ⦿ small circle/dot — loupe feel */
  color: var(--accent-ink);
  font-size: 7px;
  line-height: 1;
}

/* ── Peek overlay (read-only viewer for pinned slides / films) ── */

.peek-card { max-width: 460px; width: 100%; }

.peek-viewer-wrap { margin-bottom: 12px; }

/* Scope-style viewer — same border + background as .scope-display-wrap */
.peek-scope-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-s);
  overflow: hidden;
  border: 3px solid var(--machine-dark-a);
  background: var(--scope-screen);
  box-shadow: inset 0 0 14px rgba(28, 30, 50, 0.25);
}
.peek-scope-wrap .peek-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Film lightbox viewer — same dark slab + lit overlay as .film-lit */
.peek-film-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 300px;
  border-radius: 4px;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(232, 236, 244, 0.10) 0 18%, transparent 55%),
    linear-gradient(160deg, #2a2e36, #1a1d22);
  border: 2px solid rgba(232, 236, 244, 0.14);
  box-shadow: 0 3px 7px rgba(8, 10, 16, 0.45);
}
/* The lit layer — same as .film-lit but always fully revealed */
.peek-film-lit {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse at 50% 45%, rgba(240, 244, 255, 0.30) 0 30%, transparent 70%),
    linear-gradient(165deg, #3f4452, #2e323d);
  background-size: cover;
  background-position: center;
}
.peek-film-lit::before {
  content: "";
  position: absolute;
  top: 18px; left: 50%;
  width: 4px; height: 78px;
  margin-left: -2px;
  background: rgba(241, 243, 250, 0.28);
  border-radius: 2px;
  box-shadow:
    -14px 12px 0 -1px rgba(241, 243, 250, 0.18),
    14px 12px 0 -1px rgba(241, 243, 250, 0.18),
    -11px 30px 0 -1px rgba(241, 243, 250, 0.15),
    11px 30px 0 -1px rgba(241, 243, 250, 0.15),
    -8px 48px 0 -1px rgba(241, 243, 250, 0.12),
    8px 48px 0 -1px rgba(241, 243, 250, 0.12);
}
.peek-film-lit.has-image::before { display: none; }

.peek-caption {
  margin: 0 0 4px;
  font-family: var(--serif);
  font-size: 0.92rem;
  font-weight: 600;
  text-align: center;
  color: var(--ink-soft);
}

/* ── H3: Reveal note sticky ──────────────────────────────────── */

.reveal-note {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%) rotate(-1.5deg);
  background: #fefce8;
  border: 1px solid rgba(36, 31, 20, 0.22);
  border-radius: var(--r-s);
  padding: 7px 14px;
  font-family: var(--hand);
  font-size: 0.92rem;
  color: #2b2b33;
  box-shadow: 2px 3px 10px rgba(36, 31, 20, 0.22);
  pointer-events: none;
  z-index: 50;
  white-space: nowrap;
  max-width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.reveal-note-label { color: var(--ink-soft); font-size: 0.8rem; }
.reveal-note-check { color: var(--tier-2); font-weight: 700; }
.reveal-note.reveal-note-solved {
  opacity: 0.5;
  text-decoration: line-through;
  text-decoration-color: var(--ink-soft);
}
:root[data-theme="dark"] .reveal-note {
  background: #2f2c1a;
  border-color: rgba(236, 228, 210, 0.2);
  color: var(--ink);
}

/* ══════════════════════ RESPONSIVE ══════════════════════ */

@media (max-width: 900px) {
  /* stack: smaller viewer square above the desk; page may scroll */
  .screen-play { height: auto; overflow: visible; }
  .play-main { flex-direction: column; }
  .scope-panel {
    position: relative;
    top: auto;
    left: auto;
    width: 100%;
    z-index: auto !important;
  }
  .scope-display-wrap { flex: 0 0 auto; aspect-ratio: auto; height: 34vh; max-height: 320px; }
  .play-area { min-height: 46vh; overflow: visible; }
  .wall-area { flex-basis: 230px; min-height: 224px; }
  .xray-rack { left: 3%; right: 3%; top: 18px; height: 132px; }
  .machine-lightbox { top: 18px; }
  .lightbox-screen { width: 180px; height: 210px; }
}

@media (max-width: 760px) {
  .clue-guide-grid { grid-template-columns: 1fr; }
  .clue-guide-step {
    display: grid;
    grid-template-columns: minmax(118px, 0.8fr) 1.2fr;
    column-gap: 12px;
    align-items: center;
  }
  .clue-guide-visual { grid-row: span 2; margin: 0; }
  .hints-wrap #btn-hints { min-height: 44px; }
  .hints-panel { min-width: 240px; }
  .trays { grid-template-columns: repeat(2, 1fr); }
  .scope-stage { width: 92px; height: 92px; }
  .scope-stage-glass { width: 62px; height: 62px; }
  .lightbox-screen { width: 140px; height: 180px; }
  .wall-area { flex-basis: 190px; min-height: 184px; }
  .xray-rack { top: 16px; height: 112px; }
  .xray-rack { left: 3%; right: 3%; }
  .machine-lightbox { top: 16px; right: 3%; }
  .piece { --responsive-scale: clamp(0.72, calc(100vw / 760px), 1); }
  .play-header { gap: 10px; }
  .hints-wrap { margin-left: 0; }
  .mistake-tracker { order: 3; width: 100%; }
  /* Toolbar (Shuffle/Reset/Help/Settings/Menu): wrap onto a second row
     rather than force the page wider — only actually wraps once the row
     no longer fits (harmless no-op above ~420px). Touch targets grow to
     the ~44px guideline instead of the desktop-sized compact padding. */
  .play-actions { flex-wrap: wrap; row-gap: 8px; }
  .play-actions .btn { min-height: 44px; padding: 0.6em 0.9em; }
}

@media (max-width: 480px) {
  .screen-play { padding: 8px 10px 10px; }
  .play-header-title h1 { font-size: 1.1rem; }
  /* Two-up so six buttons read as tidy rows instead of a ragged wrap. */
  .play-actions { justify-content: flex-start; gap: 8px; }
  .play-actions .btn { flex: 1 1 calc(50% - 8px); text-align: center; }
  .hints-wrap #btn-hints { min-height: 44px; min-width: 100px; }
  .hints-panel { min-width: 200px; }
  .zoom-control { max-width: none; }
  .printer-count { font-size: 0.72rem; }
  .trays { gap: 8px; }
  .tray { padding: 8px; }
  .tray-slot { min-height: 44px; }
  .lightbox-screen { width: 124px; height: 160px; }
  .wall-area { flex-basis: 170px; min-height: 164px; }
  .xray-rack { top: 14px; }
  .machine-lightbox { top: 14px; }
}

/* ══════════════════════ REDUCED MOTION ══════════════════════ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  /* Phase 6 solve-loop — static fallbacks for animated feedback classes */
  .tray.is-one-away { box-shadow: 0 0 0 3px var(--accent) !important; }
  .tray.is-wrong    { box-shadow: 0 0 0 2px var(--danger) !important; }
  .piece.is-shake   { translate: 0 !important; }
}

/* ══════════════════════ v23 ADDITIONS ══════════════════════ */

/* ── Crop preset buttons + zoom readout (Feature A) ─────────────── */
.crop-preset-btns {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.crop-preset-btns button { flex: 1; font-size: 0.8rem; padding: 4px 0; }
.crop-zoom-pct {
  font-size: 0.82rem;
  color: var(--ink-soft);
  min-width: 44px;
  text-align: right;
  flex-shrink: 0;
}
.crop-canvas:focus { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Editor right-click context menu (Feature B) ───────────────── */
#editor-ctx-menu {
  position: fixed;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-m);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  z-index: 270;
  min-width: 190px;
  padding: 4px 0;
  display: flex;
  flex-direction: column;
}
#editor-ctx-menu .ctx-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 7px 14px;
  font-size: 0.88rem;
  color: var(--ink);
  cursor: pointer;
  border-radius: 0;
}
#editor-ctx-menu .ctx-item:hover:not(:disabled) { background: var(--accent-soft); color: var(--ink); }
#editor-ctx-menu .ctx-item:disabled { color: var(--ink-soft); cursor: default; }
#editor-ctx-menu .ctx-sep {
  border: none;
  border-top: 1px solid var(--panel-edge);
  margin: 3px 0;
}
#editor-ctx-menu .ctx-type-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px 14px 8px;
}
#editor-ctx-menu .ctx-type-label {
  font-size: 0.75rem;
  color: var(--ink-soft);
  width: 100%;
  margin-bottom: 2px;
}
#editor-ctx-menu .kind-chip { font-size: 0.72rem; padding: 2px 7px; }

/* ── Inline results editing (Feature C, preview mode only) ─────── */
.results-editable {
  outline: none;
  border-radius: 3px;
  cursor: text;
  transition: outline var(--dur-fast);
}
.results-editable:hover { outline: 2px dashed rgba(75, 63, 176, 0.35); }
.results-editable:focus { outline: 2px dashed var(--accent); background: var(--accent-soft); }
.results-preview-hint {
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin: 0 0 6px;
  font-style: italic;
}

/* ── My stats (this browser only) + share-stats notice ───────────── */
.stats-card { max-width: 440px; }
.stats-card h2, .stats-settings-card h2 { margin: 0 0 14px; }
.stats-settings-card { max-width: 420px; }
.stats-nums {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 10px;
  margin-bottom: 20px;
  text-align: center;
}
.stats-num-v { font: 700 1.9rem/1.1 var(--serif); color: var(--ink); font-variant-numeric: tabular-nums; }
.stats-num-k { margin-top: 3px; font-size: 0.78rem; color: var(--ink-soft); line-height: 1.25; }
.stats-chart-title {
  margin: 0 0 10px;
  font: 800 0.7rem/1 var(--sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.stats-chart { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.stats-row { display: grid; grid-template-columns: 5.6em minmax(0, 1fr); align-items: center; gap: 8px; }
.stats-row-k { font-size: 0.85rem; color: var(--ink-soft); text-align: right; font-variant-numeric: tabular-nums; }
.stats-row-track { display: block; min-width: 0; }
.stats-bar {
  display: block;
  min-width: 1.9em;
  padding: 3px 8px;
  border-radius: var(--r-s);
  background: var(--tier-3);
  color: var(--tier-3-ink);
  font: 700 0.85rem/1.3 var(--sans);
  text-align: right;
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
}
.stats-row.is-lost .stats-bar { background: var(--control-bg); color: var(--ink-soft); }
.stats-row.is-you .stats-bar { background: var(--eosin); color: var(--eosin-ink); }
.stats-row.is-you .stats-row-k { color: var(--ink); font-weight: 700; }
.stats-note { margin: 16px 0 0; font-size: 0.82rem; color: var(--ink-soft); line-height: 1.45; }
.stats-settings-card .toggle-row { margin-top: 4px; }

.site-foot .stats-notice { margin: 12px 0 0; font-size: 0.8rem; color: var(--ink-soft); }
.btn-stats { display: inline-flex; align-items: center; gap: 6px; }
.btn-stats svg { flex: none; }
.link-btn {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink-soft);
  text-decoration: underline;
  cursor: pointer;
}
.link-btn:hover { color: var(--accent); }
@media (max-width: 560px) {
  /* Phones: icon-only My stats so the brand keeps its line. */
  .btn-stats { padding: 0.45em 0.55em; }
  .btn-stats-label { display: none; }
}
@media (max-width: 420px) {
  .stats-num-v { font-size: 1.6rem; }
}

/* ── Class stats: results block, rating row, menu line, privacy text ── */
.results-class {
  margin-top: 16px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  padding: 14px 16px 16px;
}
.results-class-title {
  margin: 0 0 4px;
  font: 800 0.7rem/1 var(--sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.results-class-line { margin: 8px 0 12px; font: 600 1.05rem/1.3 var(--serif); color: var(--ink); font-variant-numeric: tabular-nums; }
.results-class-wait { margin: 8px 0 4px; color: var(--ink-soft); font-size: 0.88rem; }
.results-class-chart .stats-row { grid-template-columns: 6.2em minmax(0, 1fr); }
.results-class-hints { margin: 10px 0 0; font-size: 0.85rem; color: var(--ink-soft); }
#results-class-everyone + .results-rate { border-top: 1px dashed var(--panel-edge); margin-top: 14px; padding-top: 12px; }
.results-rate-q { margin: 0 0 8px; font: 600 0.95rem/1.3 var(--serif); color: var(--ink); }
.results-rate-btns { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.rate-btn {
  min-height: 40px;
  min-width: 0;
  padding: 6px 2px;
  border: 1px solid var(--panel-edge);
  border-radius: var(--r-s);
  background: transparent;
  color: var(--ink);
  font: 600 0.82rem/1.1 var(--sans);
  cursor: pointer;
}
.rate-btn:hover { border-color: var(--accent); }
.rate-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rate-btn[aria-pressed="true"] { background: var(--eosin); border-color: var(--eosin); color: var(--eosin-ink); }
.results-rate-skip { margin-top: 8px; font-size: 0.8rem; }
.results-rated { margin-top: 12px; }
.results-rated-line { margin: 0; font-size: 0.92rem; color: var(--ink); }
.results-rated-line.is-wait { color: var(--ink-soft); font-size: 0.85rem; }
.rate-dist {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
  max-width: 320px;
}
.rate-dist-col { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 58px; gap: 3px; }
.rate-dist-bar { display: block; width: 70%; max-width: 30px; background: var(--tier-3); border-radius: 3px 3px 0 0; }
.rate-dist-k { font: 500 0.66rem/1 var(--mono); color: var(--ink-soft); }
.pcard-class { display: block; margin-top: 4px; font-size: 0.78rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.privacy-text { font-size: 0.88rem; line-height: 1.5; color: var(--ink); }
.privacy-text p { margin: 0 0 10px; }
.privacy-text ul { margin: 0 0 10px; padding-left: 1.2em; }
.privacy-text li { margin: 2px 0; }
.stats-settings-card { max-height: calc(100dvh - 32px); overflow-y: auto; }
.settings-share-note { margin: 2px 0 0 1.9em; font-size: 0.78rem; line-height: 1.4; color: var(--ink-soft); }
@media (max-width: 420px) {
  .results-class { padding: 12px; }
  .rate-btn { font-size: 0.74rem; }
}
