/* =========================================================================
   SPHERE LAB — design system
   Split conceptually into: tokens → reset → layout → components → overlay
   ========================================================================= */

/* Self-hosted (SIL OFL 1.1, see fonts/LICENSE-OFL-*.txt) so the page needs no
   third-party font origin. Relative URLs resolve from source and from the build. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2');
}

:root {
  /* color — dark palette with cool undertones */
  --bg-0: #070910;
  --bg-1: #0d111b;
  --bg-2: #141a27;
  --bg-3: #1c2435;

  --stroke-a: rgba(255, 255, 255, 0.04);
  --stroke-b: rgba(255, 255, 255, 0.08);
  --stroke-c: rgba(255, 255, 255, 0.14);

  --text-0: #edf1f7;
  --text-1: #b4bdd0;
  --text-2: #818ba2;
  --text-3: #858b9c;

  /* semantic colors */
  --accent:       #ffaa33;
  --accent-soft:  rgba(255, 170, 51, 0.18);
  --accent-ghost: rgba(255, 170, 51, 0.08);
  --info:         #6fb9ff;
  --info-soft:    rgba(111, 185, 255, 0.18);
  --ok:           #4bde9a;
  --warn:         #ff5f7a;
  --magenta:      #ff6fa5;
  --violet:       #b285ff;

  /* spacing */
  --s-1: 2px;
  --s-2: 4px;
  --s-3: 6px;
  --s-4: 8px;
  --s-5: 12px;
  --s-6: 16px;
  --s-7: 20px;
  --s-8: 24px;

  /* radius */
  --r-1: 3px;
  --r-2: 5px;
  --r-3: 8px;
  --r-4: 12px;

  /* typography */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.55);

  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* ===================== reset ===================== */

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

.svg-defs { position: absolute; }

/* Visually hidden but still read by screen readers (live status, labels). */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Keyboard focus ring only — :focus-visible stays quiet for mouse clicks. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

html, body {
  width: 100%;
  height: 100%;
  background: var(--bg-0);
  color: var(--text-0);
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.4;
  overflow: hidden;
  user-select: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#canvas {
  display: block;
  cursor: crosshair;
  touch-action: none;
  image-rendering: auto;
}

/* scrollbars */
::-webkit-scrollbar       { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--stroke-c); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }

/* ===================== layout ===================== */

/* top bar — title + scene tabs + help, a single compact row */
.topbar {
  position: fixed;
  top: var(--s-5);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--s-5);
  padding: var(--s-2) var(--s-5);
  background: rgba(13, 17, 27, 0.82);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-3);
  backdrop-filter: blur(20px) saturate(130%);
  -webkit-backdrop-filter: blur(20px) saturate(130%);
  box-shadow: var(--shadow-md);
  max-width: calc(100vw - var(--s-8));
  overflow-x: auto;
  z-index: 3;
}

/* Desktop only: JS never sets these on the touch layout, which has its own mask. */
.topbar.fade-r {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
}
.topbar.fade-l {
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent);
}
.topbar.fade-l.fade-r {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
}

.topbar .brand {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--text-2);
  padding-right: var(--s-5);
  border-right: 1px solid var(--stroke-b);
  white-space: nowrap;
}

.topbar .brand b { color: var(--accent); font-weight: 600; letter-spacing: 0.28em; }

.scene-tabs {
  display: flex;
  gap: var(--s-1);
}

/* side panels share these base styles */
.panel {
  position: fixed;
  background: rgba(13, 17, 27, 0.85);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-3);
  backdrop-filter: blur(20px) saturate(130%);
  -webkit-backdrop-filter: blur(20px) saturate(130%);
  box-shadow: var(--shadow-md);
  z-index: 2;
}

.panel-left, .panel-right {
  top: 68px;
  bottom: var(--s-5);
  width: 248px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}

.panel-left  { left: var(--s-5); }
/* Ends above the Help pill: 12 px edge + 24 px pill + 12 px gap. */
.panel-right { right: var(--s-5); bottom: 48px; }

/* Collapsed = slide the panel off-screen + fade. pointer-events off so it
 * doesn't swallow clicks on canvas while hidden. */
.panel-left.collapsed  { transform: translateX(calc(-100% - var(--s-5) - 2px)); opacity: 0; pointer-events: none; }
.panel-right.collapsed { transform: translateX(calc( 100% + var(--s-5) + 2px)); opacity: 0; pointer-events: none; }

/* Close "×" button in the top corner of each panel. Sits above scroll content. */
.panel-close {
  position: absolute;
  top: 6px;
  width: 22px; height: 22px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 26, 39, 0.75);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-1);
  color: var(--text-2);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.panel-left  .panel-close { right: 6px; }
.panel-right .panel-close { right: 6px; }
.panel-close:hover {
  background: var(--bg-3);
  color: var(--text-0);
  border-color: var(--stroke-c);
}

/* Edge handle that appears when a panel is collapsed. Reasonably chunky
 * so it's easy to spot + click at the edge of the viewport. Uses the
 * accent color to stand out, and a soft pulse on first appearance so the
 * eye is drawn to it when a panel collapses. */
.panel-open {
  position: fixed;
  top: 50%;
  width: 30px;
  height: 80px;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(13, 17, 27, 0.92);
  border: 1px solid var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-sans);
  font-size: 20px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-md), 0 0 16px var(--accent-ghost);
  z-index: 30;
  padding: 0;
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s var(--ease);
}
.panel-open:hover {
  background: var(--bg-3);
  color: var(--text-0);
  border-color: var(--accent);
  box-shadow: var(--shadow-md), 0 0 22px var(--accent-soft);
}
.panel-open-left:hover  { transform: translate(4px, -50%); }
.panel-open-right:hover { transform: translate(-4px, -50%); }
.panel-open.show        { display: flex; animation: panel-open-pulse 1.4s var(--ease) 2; }
.panel-open-left        { left: 0;  border-left: none;  border-radius: 0 var(--r-3) var(--r-3) 0; }
.panel-open-right       { right: 0; border-right: none; border-radius: var(--r-3) 0 0 var(--r-3); }

@keyframes panel-open-pulse {
  0%, 100% { box-shadow: var(--shadow-md), 0 0 16px var(--accent-ghost); }
  50%      { box-shadow: var(--shadow-md), 0 0 28px var(--accent-soft); }
}

.panel-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

/* bottom bar — mode indicator + help button */
.mode-pill {
  position: fixed;
  bottom: var(--s-5);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-5);
  background: rgba(13, 17, 27, 0.82);
  border: 1px solid var(--info-soft);
  border-radius: 999px;
  color: var(--info);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.24em;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: var(--shadow-sm), 0 0 20px var(--info-soft);
  pointer-events: none;
  z-index: 3;
}

.mode-pill .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--info);
  box-shadow: 0 0 8px var(--info);
  animation: pulse 2s var(--ease) infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

#help-btn {
  position: fixed;
  bottom: var(--s-5);
  right: var(--s-5);
  z-index: 3;
}
.help-btn-icon { margin-right: 4px; }

/* Embed mode (?embed=1): an iframe gets the canvas only — every control
   surface is hidden, input still works, and one link opens the full app. */
body.embed .panel,
body.embed .panel-open,
body.embed #help-btn,
body.embed .mode-pill,
body.embed .topbar,
body.embed #mobile-scene-btn,
body.embed #mobile-settings-btn,
body.embed #mobile-share-btn,
body.embed #mobile-sheet-backdrop { display: none; }

/* Status toast (share / export / import feedback). Not chrome: embed mode keeps
   it, and it sits above the panel reopen tabs (z-index 30). */
#toast {
  position: fixed;
  left: 50%;
  bottom: var(--s-8);
  transform: translateX(-50%);
  max-width: min(420px, calc(100vw - 2 * var(--s-6)));
  padding: var(--s-4) var(--s-6);
  border: 1px solid var(--accent-soft);
  border-radius: var(--r-3);
  background: rgba(13, 17, 27, 0.94);
  box-shadow: var(--shadow-md);
  color: var(--text-0);
  font: 500 12px/1.4 var(--font-sans);
  text-align: center;
  pointer-events: none;
  z-index: 40;
  animation: toast-in 0.18s var(--ease);
}
#toast[hidden] { display: none; }
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, var(--s-4)); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* First-run coach: bottom-centre, stacked above the toast so a share or
   error toast and the coach can both be read. Only the card takes pointer
   events — the canvas around it stays live. */
.coach {
  position: fixed;
  left: 50%;
  bottom: calc(var(--s-8) + 56px);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--s-5);
  max-width: min(520px, calc(100vw - 2 * var(--s-6)));
  padding: var(--s-4) var(--s-4) var(--s-4) var(--s-6);
  border: 1px solid var(--accent-soft);
  border-radius: var(--r-3);
  background: rgba(13, 17, 27, 0.94);
  box-shadow: var(--shadow-md);
  color: var(--text-0);
  font: 500 12px/1.4 var(--font-sans);
  z-index: 40;
  animation: toast-in 0.18s var(--ease);
}
.coach[hidden] { display: none; }
.coach-count { color: var(--accent); font-family: var(--font-mono); font-size: 10px; white-space: nowrap; }
.coach-text { flex: 1; }
.coach-actions { display: flex; gap: var(--s-2); }
.scene-tabs.coach-focus {
  border-radius: var(--r-3);
  box-shadow: 0 0 0 1px var(--accent), 0 0 18px var(--accent-soft);
}
body.embed .coach { display: none; }
/* The experiment card: Galton's counts and readout sit at the bottom of the board, so on a
   desktop this card sits at the top, just below the top bar (≈ 41 px). The words and the close
   button share the first row; the live numbers and the buttons wrap below. */
#experiment-card {
  top: calc(41px + var(--s-3));
  bottom: auto;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
}
#exp-text { flex: 1 1 calc(100% - 48px); }
#exp-numbers { flex: 1 1 auto; color: var(--text-1); font: 500 11px/1.4 var(--font-mono); }
#exp-numbers:empty { display: none; }
#exp-actions { flex-wrap: wrap; }
#btn-experiment[hidden] { display: none; }

#embed-open { display: none; }
body.embed #embed-open {
  display: block;
  position: fixed;
  bottom: var(--s-5);
  right: var(--s-5);
  z-index: 3;
  padding: var(--s-3) var(--s-5);
  background: rgba(13, 17, 27, 0.82);
  border: 1px solid var(--accent-soft);
  border-radius: var(--r-3);
  color: var(--accent);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-md);
}
body.embed #embed-open:hover,
body.embed #embed-open:focus-visible { border-color: var(--accent); color: var(--text-0); }

/* ===================== components ===================== */

/* section — titled block inside a panel */
.section {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.section-header {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--text-2);
  text-transform: uppercase;
  padding: 0 var(--s-2);
}

/* generic button */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-2);
  color: var(--text-1);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: all 0.12s var(--ease);
  white-space: nowrap;
  user-select: none;
}

.btn:hover {
  background: var(--bg-3);
  border-color: var(--stroke-c);
  color: var(--text-0);
}

.btn:active { transform: translateY(0.5px); }

.btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-0);
  box-shadow: 0 0 18px var(--accent-soft);
}

.btn-block { width: 100%; }

.btn-sm { padding: var(--s-2) var(--s-4); font-size: 11px; }

.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--bg-2); color: var(--text-0); border-color: var(--stroke-b); }

.btn-pill { border-radius: 999px; padding: var(--s-2) var(--s-5); font-size: 11px; }

/* scene tab (inside the top bar) */
.tab {
  padding: var(--s-2) var(--s-4);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-2);
  color: var(--text-2);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: all 0.12s var(--ease);
  white-space: nowrap;
}
.tab:hover { background: var(--bg-2); color: var(--text-0); }
.tab.active {
  background: var(--accent-ghost);
  color: var(--accent);
  border-color: var(--accent-soft);
}

/* tool button — icon + label, 3×3 grid to fit 9 tools */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
}

.tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-2);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-2);
  color: var(--text-2);
  cursor: pointer;
  transition: all 0.12s var(--ease);
}

.tool:hover { background: var(--bg-3); color: var(--text-0); border-color: var(--stroke-c); }

.tool.active {
  background: var(--info-soft);
  color: var(--info);
  border-color: var(--info);
  box-shadow: inset 0 0 0 1px rgba(111,185,255,0.15);
}

.tool svg { width: 16px; height: 16px; }
.tool .tool-label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* material palette row */
.mat-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.mat {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-2);
  color: var(--text-1);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: all 0.12s var(--ease);
}

.mat:hover { background: var(--bg-3); color: var(--text-0); }

.mat.active {
  background: var(--bg-3);
  border-color: var(--text-1);
  color: var(--text-0);
}

.mat-swatch {
  width: 14px; height: 14px;
  border-radius: 50%;
  flex-shrink: 0;
  position: relative;
}
.mat-swatch::after {
  content: '';
  position: absolute;
  inset: 2px 4px auto auto;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: rgba(255,255,255,0.7);
  mix-blend-mode: screen;
}

.mat-hotkey {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
}

.mat.active .mat-hotkey { color: var(--text-2); }

/* sliders */
.slider-row {
  display: grid;
  grid-template-columns: 64px 1fr 44px;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-2);
}

.slider-label {
  font-size: 11px;
  color: var(--text-2);
  letter-spacing: 0.04em;
}

.slider-value {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

input[type=range] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 16px;
  background: transparent;
  cursor: pointer;
}
input[type=range]:focus:not(:focus-visible) { outline: none; }

/* track (both browsers) */
input[type=range]::-webkit-slider-runnable-track {
  height: 3px;
  background: var(--stroke-b);
  border-radius: 2px;
}
input[type=range]::-moz-range-track {
  height: 3px;
  background: var(--stroke-b);
  border-radius: 2px;
}

/* thumb */
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px;
  margin-top: -4.5px;  /* center on 3px track */
  background: var(--accent);
  border: 2px solid var(--bg-0);
  border-radius: 50%;
  box-shadow: 0 0 10px var(--accent-soft);
  cursor: grab;
  transition: transform 0.12s var(--ease);
}
input[type=range]::-moz-range-thumb {
  width: 12px; height: 12px;
  background: var(--accent);
  border: 2px solid var(--bg-0);
  border-radius: 50%;
  box-shadow: 0 0 10px var(--accent-soft);
  cursor: grab;
}

input[type=range]:hover::-webkit-slider-thumb { transform: scale(1.15); }
input[type=range]:active::-webkit-slider-thumb { cursor: grabbing; transform: scale(1.25); }

/* toggle grid — 3 columns of compact toggle pills */
.toggle-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
}

.toggle {
  padding: var(--s-2) var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-1);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.12s var(--ease);
}

.toggle:hover { background: var(--bg-3); color: var(--text-1); }

.toggle.active {
  background: var(--ok);
  color: var(--bg-0);
  border-color: var(--ok);
  box-shadow: 0 0 12px rgba(75, 222, 154, 0.25);
}

/* actions — vertical stack of full-width buttons */
.actions {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.action-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-3) var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-2);
  color: var(--text-1);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: all 0.12s var(--ease);
}

.action-btn:hover { background: var(--bg-3); color: var(--text-0); border-color: var(--stroke-c); }

.action-btn.active {
  background: var(--accent-ghost);
  color: var(--accent);
  border-color: var(--accent-soft);
}

.action-btn .kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
  padding: 1px 6px;
  background: var(--bg-0);
  border: 1px solid var(--stroke-b);
  border-radius: var(--r-1);
}

.action-btn.active .kbd { color: var(--accent); border-color: var(--accent-soft); }

/* stats grid + live graphs */
.stat-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  color: var(--text-2);
}
.stat-row .v {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}
.stat-row .v.accent { color: var(--accent); }
.stat-row .v.ok     { color: var(--ok); }
.stat-row .v.info   { color: var(--info); }

.graph-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3);
  background: rgba(7, 9, 16, 0.65);
  border: 1px solid var(--stroke-a);
  border-radius: var(--r-2);
}
.graph-head {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--text-2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.graph-head .v {
  font-family: var(--font-mono);
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
  text-transform: none;
  letter-spacing: 0;
}
.graph-card canvas {
  display: block;
  width: 100%;
  height: 36px;
}

/* inline kbd */
.kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-1);
  background: var(--bg-2);
  border: 1px solid var(--stroke-b);
  padding: 1px 6px;
  border-radius: var(--r-1);
  white-space: nowrap;
}

/* ===================== help overlay ===================== */

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(4, 6, 12, 0.78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 20;
  animation: fade-in 0.18s var(--ease);
}

.overlay.show { display: flex; }

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

.help-box {
  max-width: 780px;
  max-height: 82vh;
  overflow-y: auto;
  padding: var(--s-8);
  background: linear-gradient(180deg, rgba(20, 26, 39, 0.96), rgba(10, 13, 20, 0.96));
  border: 1px solid var(--stroke-c);
  border-radius: var(--r-4);
  box-shadow: var(--shadow-lg), 0 0 60px var(--accent-ghost);
  animation: slide-up 0.25s var(--ease);
}

@keyframes slide-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.help-box h1 {
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: 0.32em;
  color: var(--accent);
  margin-bottom: var(--s-1);
}

.help-box .help-sub {
  font-size: 12px;
  color: var(--text-2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: var(--s-7);
}

.help-box h4 {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--ok);
  margin-top: var(--s-7);
  margin-bottom: var(--s-4);
  text-transform: uppercase;
}

.help-grid {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--s-3) var(--s-6);
  font-size: 13px;
  color: var(--text-1);
  line-height: 1.55;
}

.help-prose {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-1);
}

.help-prose code {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
  background: var(--bg-0);
  padding: 1px 4px;
  border-radius: var(--r-1);
}

.help-footer {
  margin-top: var(--s-7);
  text-align: right;
}

/* small utilities */
.divider {
  height: 1px;
  background: var(--stroke-b);
  margin: var(--s-2) 0;
}

/* responsive: hide side panels on narrow screens */
/* Mobile entry points (Scenes ▾, ⚙ settings, sheet close, backdrop) exist
   only for the phone layout below; desktop never shows them. */
#mobile-scene-btn,
#mobile-settings-btn,
#mobile-share-btn,
#mobile-sheet-close,
#mobile-sheet-backdrop { display: none; }

/* Phones, small tablets, and any touch-first screen up to 1400 px (a big phone
   held sideways, a tablet): the side panels can't fit beside the canvas or only
   cover it with no mouse to use them, so the left panel becomes a bottom dock
   (tools + material chips) and the right panel a bottom sheet. Every control
   stays reachable; nothing is cloned. Same rule as SHELL_MEDIA in ui/shell.js. */
@media (max-width: 900px), (hover: none) and (pointer: coarse) and (max-width: 1400px) {
  :root {
    --dock-h: 100px;
    --safe-b: env(safe-area-inset-bottom, 0px);
    --safe-t: env(safe-area-inset-top, 0px);
  }

  /* ---- bottom tool dock ---- */
  .panel-left {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    border-radius: var(--r-3) var(--r-3) 0 0;
    border-bottom: none;
    padding-bottom: var(--safe-b);
    z-index: 4;
  }
  /* A saved "closed" pref or the `,` key must never hide the dock. */
  .panel-left.collapsed { transform: none; opacity: 1; pointer-events: auto; }

  .panel-left .panel-body {
    flex-direction: column-reverse;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
    overflow: visible;
  }
  .panel-left .section { gap: 0; min-width: 0; }
  .panel-left .section-header { display: none; }
  /* Actions live in the settings sheet on phones (moved there by script). */
  .panel-left #actions-section { display: none; }

  #tool-row {
    display: flex;
    gap: var(--s-2);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  #tool-row::-webkit-scrollbar { display: none; }
  #tool-row .tool {
    flex: 0 0 auto;
    min-width: 48px;
    min-height: 48px;
    padding: 0 var(--s-3);
    scroll-snap-align: start;
  }
  #tool-row .tool svg { width: 20px; height: 20px; }
  /* Icon-only, but the label stays as the button's accessible name. */
  #tool-row .tool-label {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  /* ---- material chip strip, directly above the tools ---- */
  #ball-types {
    flex-direction: row;
    gap: var(--s-2);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  #ball-types::-webkit-scrollbar { display: none; }
  #ball-types .mat {
    flex: 0 0 auto;
    min-height: 36px;
    padding: 0 var(--s-4);
    gap: var(--s-3);
    border-radius: 999px;
    white-space: nowrap;
  }
  #ball-types .mat-hotkey { display: none; }

  /* ---- settings bottom sheet ---- */
  .panel-right {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-height: 70vh;
    border-radius: var(--r-3) var(--r-3) 0 0;
    border-bottom: none;
    padding-bottom: var(--safe-b);
    z-index: 22;
    transform: translateY(100%);
    visibility: hidden;
    transition: transform 0.22s var(--ease), visibility 0s linear 0.22s;
  }
  /* Same never-hide-by-pref override as the dock: the sheet's own state is
     .sheet-open, so .collapsed must not fade it or swallow its taps. */
  .panel-right.collapsed { transform: translateY(100%); opacity: 1; pointer-events: auto; }
  .panel-right.sheet-open,
  .panel-right.collapsed.sheet-open {
    transform: none;
    visibility: visible;
    transition: transform 0.22s var(--ease), visibility 0s;
  }
  .panel-right .panel-body { padding-top: 44px; }

  #mobile-sheet-close {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: var(--s-3);
    right: var(--s-3);
    width: 44px; height: 44px;
    padding: 0;
    background: var(--bg-2);
    border: 1px solid var(--stroke-b);
    border-radius: var(--r-2);
    color: var(--text-1);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
  }

  #mobile-sheet-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(4, 6, 12, 0.55);
    z-index: 21;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s var(--ease), visibility 0s linear 0.22s;
  }
  .panel-right.sheet-open ~ #mobile-sheet-backdrop,
  .topbar.scenes-open ~ #mobile-sheet-backdrop,
  #mobile-sheet-backdrop.show {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.22s var(--ease), visibility 0s;
  }

  /* ---- top bar + Scenes ▾ menu (tabs never leave #top) ---- */
  .topbar {
    top: calc(var(--s-3) + var(--safe-t));
    left: var(--s-3);
    right: calc(var(--s-3) * 2 + 76px);
    transform: none;
    max-width: none;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-3);
    -webkit-mask-image: linear-gradient(to right, #000 85%, transparent);
            mask-image: linear-gradient(to right, #000 85%, transparent);
    scrollbar-width: none;
  }
  .topbar::-webkit-scrollbar { display: none; }
  .topbar .brand { padding-right: var(--s-3); }
  .topbar .tab { min-height: 36px; }

  .topbar.scenes-open {
    align-items: stretch;
    flex-direction: column;
    max-height: calc(70vh - var(--safe-t));
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-mask-image: none;
            mask-image: none;
    z-index: 23;
  }
  .topbar.scenes-open .brand { border-right: none; padding: var(--s-2); }
  .topbar.scenes-open .scene-tabs { flex-wrap: wrap; }
  .topbar.scenes-open .tab {
    flex: 1 1 96px;
    min-height: 44px;
  }

  #mobile-scene-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: calc(var(--s-3) + var(--safe-t));
    right: var(--s-3);
    width: 76px;
    height: 44px;
    padding: 0 var(--s-3);
    border-radius: var(--r-3);
    background: rgba(13, 17, 27, 0.9);
    z-index: 24;
  }
  .topbar.scenes-open ~ #mobile-scene-btn {
    background: var(--accent-ghost);
    border-color: var(--accent-soft);
    color: var(--accent);
  }

  /* ---- floating controls above the dock ---- */
  #mobile-settings-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    left: var(--s-3);
    bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-3));
    width: 44px; height: 44px;
    padding: 0;
    border-radius: 50%;
    background: rgba(13, 17, 27, 0.9);
    font-size: 20px;
    z-index: 3;
  }
  /* One tap to share: beside ⚙, same row, so the dock band it measures is unchanged. */
  #mobile-share-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    left: calc(var(--s-3) * 2 + 44px);
    bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-3));
    width: 44px; height: 44px;
    padding: 0;
    border-radius: 50%;
    background: rgba(13, 17, 27, 0.9);
    z-index: 3;
  }
  .mode-pill { bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-5)); }
  /* Clear of the dock and the 44 px floating buttons; the base z-index 40
     already stacks it over the sheets (≤ 24). */
  #toast { bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-8) + 44px); }
  /* A card is chrome on touch screens: it sits on the ⚙ row between Share and Help (the mode
     pill steps aside while it is open) and grows upward when it wraps; mobile.js frames the
     scene above whatever it still covers. Opacity-only animation, so the rect mobile.js reads
     on open is already the final one. */
  .coach {
    left: calc(var(--s-3) * 3 + 88px);
    right: auto;
    width: max-content;
    max-width: calc(100vw - var(--s-3) * 5 - 160px);
    bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-3));
    transform: none;
    flex-wrap: wrap;
    animation-name: fade-in;
  }
  /* The desktop id rule puts the experiment card at the top; on touch screens it is a bottom
     card like the others, so both edges are restored. */
  #experiment-card { top: auto; bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-3)); }
  body.card-open .mode-pill { visibility: hidden; }
  /* A wrapped card on a portrait phone reaches above the ⚙ row; the toast moves under the top
     bar so the two never overlap. */
  body.card-open:not(.scene-pinball) #toast { top: calc(var(--safe-t) + 56px + var(--s-3)); bottom: auto; }
  #help-btn {
    right: var(--s-3);
    bottom: calc(var(--dock-h) + var(--safe-b) + var(--s-3));
    min-height: 44px;
  }

  /* ---- a phone held sideways: no floating row ----
     The height above the dock is the scene's, so ⚙, Share and Help sit at the right end of the
     dock's material line (dock padding + the 42 px tool line + 2 px of the gap below it) and the
     mode pill on the tool line's empty right end. The shorter tool line and top bar give the
     scene band the pixels a 390 px tall screen is short of. The material row ends left of ⚙
     (a margin, not padding: padding on a scroller only adds blank space after the last chip, and
     the chips still ran under the buttons). Pinball and an open card keep winning by specificity. */
  @media (orientation: landscape) and (max-height: 500px) {
    #tool-row .tool { min-height: 42px; }
    .topbar { padding-block: 2px; }
    #mobile-settings-btn, #mobile-share-btn, #help-btn { bottom: calc(var(--safe-b) + var(--s-2) + 44px); z-index: 5; }
    #mobile-settings-btn { left: auto; right: calc(var(--s-3) * 3 + 44px + 72px); }
    #mobile-share-btn { left: auto; right: calc(var(--s-3) * 2 + 72px); }
    #ball-types { margin-right: calc(var(--s-3) * 3 + 88px + 72px); }
    .mode-pill { left: auto; right: var(--s-3); transform: none; bottom: calc(var(--safe-b) + var(--s-2) + 12px); z-index: 5; }
    .coach { left: var(--s-3); max-width: calc(100vw - var(--s-3) * 2); }
    /* The experiment card docks right of the Galton board instead of a strip under it, so the
       board keeps its home zoom and its counts stay readable. Galton's bins span 444 of the
       720 px frame, at most ≈ 31vh each side of the centre on screen; the card starts right of
       32vh (panelFit.js::openCardTop skips a card beside the bins). */
    #experiment-card {
      left: auto;
      right: var(--s-3);
      width: max-content;
      max-width: calc(50vw - 32vh - var(--s-3) * 2);
    }
    /* A short strip beside the board: the result line (word, percentage, noise band) without the
       echo and the explanation, and once a prediction is in, the numbers get a row of their own
       above Run again. A zero basis with no minimum let the max-content card shrink them to a
       one-word column beside the × that ran off the screen edge. */
    #experiment-card .exp-more { display: none; }
    #experiment-card[data-step="measure"] #exp-numbers { flex: 1 1 100%; }
  }

  /* ---- pinball: both lower corners are flipper zones ----
     The dock slides away (never display:none — it comes straight back on the
     next scene) and the floating controls stack under the Scenes button, so
     every tap in the lower half reaches the canvas. mobile.js fits the table
     below the top bar. */
  body.scene-pinball { --dock-h: 0px; }
  body.scene-pinball .panel-left,
  body.scene-pinball .panel-left.collapsed {
    transform: translateY(100%);
    visibility: hidden;
    pointer-events: none;
  }
  body.scene-pinball #mobile-settings-btn,
  body.scene-pinball #help-btn {
    left: auto;
    right: var(--s-3);
    bottom: auto;
  }
  body.scene-pinball #mobile-settings-btn { top: calc(var(--safe-t) + var(--s-3) * 2 + 44px); }
  body.scene-pinball #help-btn { top: calc(var(--safe-t) + var(--s-3) * 3 + 88px); }
  /* Beside ⚙ on its row: a slot below Help would reach the flipper zone (y ≥ W.ch / 2) in landscape. */
  body.scene-pinball #mobile-share-btn {
    left: auto;
    right: calc(var(--s-3) * 2 + 44px);
    bottom: auto;
    top: calc(var(--safe-t) + var(--s-3) * 2 + 44px);
  }
  body.scene-pinball .mode-pill { visibility: hidden; }
  /* No ⚙ row in pinball: the card is centred at the screen bottom and mobile.js fits the table above it. */
  body.scene-pinball .coach { left: 50%; right: auto; width: auto; transform: translateX(-50%); max-width: min(520px, calc(100vw - 2 * var(--s-6))); }

  /* No hover on touch; panels are fixed in place on phones. */
  #inspector,
  #inspector.show,
  #panel-left-close,
  #panel-right-close,
  #panel-left-open,
  #panel-right-open,
  .panel-open.show { display: none; }
}

/* =========================================================================
   THEME PRESETS — swap the accent + info tokens at the :root level so every
   downstream color (buttons, graphs, tooltips, lens-flare sources) follows.
   ========================================================================= */

html[data-theme="cyan"] {
  --accent:       #56d4ff;
  --accent-soft:  rgba(86, 212, 255, 0.18);
  --accent-ghost: rgba(86, 212, 255, 0.08);
  --info:         #b285ff;
  --info-soft:    rgba(178, 133, 255, 0.18);
}

html[data-theme="violet"] {
  --accent:       #c878ff;
  --accent-soft:  rgba(200, 120, 255, 0.18);
  --accent-ghost: rgba(200, 120, 255, 0.08);
  --info:         #ff6fa5;
  --info-soft:    rgba(255, 111, 165, 0.18);
}

html[data-theme="forest"] {
  --accent:       #7ae09e;
  --accent-soft:  rgba(122, 224, 158, 0.18);
  --accent-ghost: rgba(122, 224, 158, 0.08);
  --info:         #ffd07a;
  --info-soft:    rgba(255, 208, 122, 0.18);
}

/* ---- theme swatches in Settings section ---- */
.theme-row {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-2);
}
.theme-dot {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  flex: none;
  padding: 0;
  width: 22px; height: 22px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
  transition: transform 0.12s var(--ease), border-color 0.12s var(--ease);
}
.theme-dot:hover { transform: scale(1.12); }
.theme-dot.active { border-color: var(--text-0); box-shadow: 0 0 14px currentColor; }
.theme-dot[data-theme="amber"]  { background: #ffaa33; color: #ffaa33; }
.theme-dot[data-theme="cyan"]   { background: #56d4ff; color: #56d4ff; }
.theme-dot[data-theme="violet"] { background: #c878ff; color: #c878ff; }
.theme-dot[data-theme="forest"] { background: #7ae09e; color: #7ae09e; }

/* =========================================================================
   TOOLTIPS — any element with [data-tip] shows a small pill on hover.
   The anchor below has zero specificity so a control's own position rule
   (the fixed reopen tabs, the absolute panel ×) always wins over it.
   ========================================================================= */

:where([data-tip]) { position: relative; }

[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 4px 9px;
  background: var(--bg-0);
  color: var(--text-0);
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.03em;
  border: 1px solid var(--stroke-c);
  border-radius: var(--r-2);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s var(--ease), transform 0.12s var(--ease);
  box-shadow: var(--shadow-sm);
  z-index: 5;
}

[data-tip]:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

[data-tip-side="right"]::after {
  bottom: 50%;
  left: calc(100% + 6px);
  transform: translateY(50%) translateX(-4px);
}
[data-tip-side="right"]:hover::after {
  transform: translateY(50%) translateX(0);
}

[data-tip-side="bottom"]::after {
  top: calc(100% + 6px);
  bottom: auto;
  transform: translateX(-50%) translateY(-4px);
}
[data-tip-side="bottom"]:hover::after {
  transform: translateX(-50%) translateY(0);
}

/* =========================================================================
   SCENE TITLE OVERLAY — big center title that fades in when a scene loads.
   ========================================================================= */

.scene-title {
  position: fixed;
  left: 50%;
  top: 40%;
  transform: translate(-50%, -50%);
  text-align: center;
  pointer-events: none;
  z-index: 4;
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.scene-title.show {
  /* animation-fill-mode: forwards retains the animation's final frame
     (opacity: 0) so the title actually disappears. Without it the base
     transition would fade the title *back* to opacity: 1 after the
     animation ended, leaving the text permanently on screen. */
  animation: scene-pulse 2s var(--ease) forwards;
}

.scene-title .st-title {
  font-family: var(--font-mono);
  font-size: 44px;
  font-weight: 600;
  letter-spacing: 0.32em;
  color: var(--accent);
  text-shadow: 0 0 30px var(--accent-soft);
  text-transform: uppercase;
}
.scene-title .st-sub {
  margin-top: var(--s-3);
  font-size: 13px;
  color: var(--text-1);
  letter-spacing: 0.12em;
}

@keyframes scene-pulse {
  0%   { opacity: 0;   transform: translate(-50%, -40%); }
  15%  { opacity: 1;   transform: translate(-50%, -50%); }
  70%  { opacity: 1;   transform: translate(-50%, -50%); }
  100% { opacity: 0;   transform: translate(-50%, -58%); }
}

/* =========================================================================
   BALL INSPECTOR — floating card that follows cursor when over a ball.
   ========================================================================= */

.inspector {
  position: fixed;
  pointer-events: none;
  display: none;
  padding: var(--s-4);
  min-width: 180px;
  background: rgba(13, 17, 27, 0.95);
  border: 1px solid var(--stroke-c);
  border-radius: var(--r-3);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: var(--shadow-md);
  z-index: 6;
  font-family: var(--font-sans);
  font-size: 11px;
  transition: opacity 0.1s var(--ease);
}
.inspector.show { display: block; }

.inspector .ins-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--stroke-b);
  margin-bottom: var(--s-3);
}
.inspector .ins-swatch {
  width: 14px; height: 14px;
  border-radius: 50%;
}
.inspector .ins-name {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--text-0);
  text-transform: uppercase;
}
.inspector .ins-id {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
}
.inspector .ins-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 12px;
}
.inspector .ins-grid .k { color: var(--text-2); }
.inspector .ins-grid .v {
  text-align: right;
  color: var(--text-0);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.inspector .ins-heat-bar {
  margin-top: var(--s-3);
  height: 4px;
  background: var(--bg-0);
  border-radius: 2px;
  overflow: hidden;
}
.inspector .ins-heat-bar .fill {
  width: 0%;
  height: 100%;
  background: linear-gradient(90deg, #ffaa33, #ff4020);
  transition: width 0.12s var(--ease);
}

/* ========================================================================= */
/* narrow action-btn variant — used for the Settings row of small buttons */
.action-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--s-2);
}
.action-row .action-btn {
  padding: var(--s-2) var(--s-3);
  font-size: 11px;
  justify-content: center;
}

/* "My creations" — the saved list under the Settings action row */
.creations {
  margin-top: var(--s-3);
}
.creations-title {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--text-2);
  text-transform: uppercase;
  padding: 0 var(--s-2) var(--s-2);
}
.creations-empty {
  margin: 0;
  padding: 0 var(--s-2);
  font-size: 11px;
  color: var(--text-3);
}
.creations-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-2);
}
.creation {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: var(--s-2);
}
.creation .action-btn {
  padding: var(--s-2) var(--s-3);
  font-size: 11px;
}
.creation .creation-open {
  display: block;             /* a flex button's children cannot ellipsize */
  text-align: left;
  min-width: 0;
  line-height: 1.35;
}
.creation .creation-name,
.creation .creation-meta {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.creation .creation-meta {
  font-size: 10px;
  color: var(--text-3);
}

/* =========================================================================
   SCENE FADE OVERLAY — covers the screen in the background color on scene load
   and fades back in ~350 ms. Hides the first-frame jump when geometry rebuilds.
   ========================================================================= */

.scene-fade {
  position: fixed;
  inset: 0;
  background: var(--bg-0);
  pointer-events: none;
  opacity: 0;
  z-index: 10;
}
.scene-fade.fading {
  animation: scene-fade 0.35s ease;
}
@keyframes scene-fade {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* =========================================================================
   REDUCED MOTION — honour the OS setting: no looping pulses, no slides or
   drifts. Fades stay (opacity only) and keep `forwards` so the scene title
   still ends hidden.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .mode-pill .dot,
  .panel-open.show { animation: none; }
  .scene-title.show { animation: scene-pulse-still 2s var(--ease) forwards; }
  .scene-fade.fading { animation: scene-fade 0.35s ease forwards; }
  #toast,
  .coach,
  .help-box { animation: fade-in 0.18s var(--ease); }
  .theme-dot,
  .panel-open-left,
  .panel-open-right { transition: none; }
  .theme-dot:hover { transform: none; }
  .panel-open-left:hover,
  .panel-open-right:hover { transform: translateY(-50%); }
}
@keyframes scene-pulse-still {
  0%   { opacity: 0; }
  15%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}
