/* ============================================================
   Diagramium — app chrome
   Brand system: "Midnight iris" — near-black blue-tinted surfaces and
   hairline borders do the work; a single electric iris signal marks the
   one thing that matters. The white diagram sheet is the star.
   Dark-first; light chrome is a manual toggle ([data-ui-theme="light"]).
   ============================================================ */

/* Typography rides the system stack in --sans (SF Pro / Segoe UI Variable /
   Inter where installed) — no font file ships, so nothing is fetched. */

/* TOKENS BEGIN — single source of truth. scripts/build_pages.py copies this
   block into the generated pages/(generated).html at build time; edit only here. */
:root {
  /* ---- Brand tokens (dark ground, the default chrome) ---- */
  --ink: #ffffff;
  --ink-2: #e8e8e8;
  --paper: #0f0f0f;
  --panel: #1c1c1c;
  --panel-2: #262626;
  /* THE signal: marigold marker — the favicon amber, and since the Drafting
     Desk redesign (Aug 2026) the site's ONE accent. The theme toggle and the
     accent picker are gone (operator decision): these values are the brand,
     not a default. Amber is light enough that WHITE fails on it (2.15:1), so
     --on-signal flips to near-black — same fix the old amber palette used. */
  /* STUDIO-MONOCHROME signal (Aug 2026): the editor's accent is WHITE — the
     way YouTube Studio's controls are white/grey while only its logo carries
     colour. Filled-accent controls become white with near-black labels;
     accent-soft becomes the translucent white row-highlight. The BRAND stays
     orange through --mark (logo/wordmark), and the marketing pages pin their
     own marigold accent — this ramp is the EDITOR's. */
  --iris: #f1f1f1;
  --iris-bright: #ffffff;
  --iris-deep: #d6d6d6;
  --iris-ink: #f1f1f1;   /* accent used as text on the dark chrome */
  --iris-soft: rgba(255, 255, 255, 0.10);
  --on-signal: #0f0f0f;
  --slate: #c4c4c4;
  --slate-2: #a8a8a8;
  --edge: #2e2e2e;
  --dot: #2a2a2a;
  --faint: #9e9e9e;

  /* ---- Scales ---- */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px;
  --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;
  --r-1: 6px; --r-2: 10px; --r-3: 14px; --r-4: 20px; --r-full: 999px;
  --radius: var(--r-2);
  --radius-lg: 16px;
  --shadow: 0 1px 2px rgba(2, 3, 10, .5), 0 18px 48px -14px rgba(2, 3, 10, .7);
  --shadow-sm: 0 1px 2px rgba(2, 3, 10, .5), 0 6px 18px -8px rgba(2, 3, 10, .55);
  --shadow-lg: 0 1px 3px rgba(2, 3, 10, .55), 0 32px 80px -20px rgba(2, 3, 10, .8);
  --glow-accent: 0 0 0 1px color-mix(in srgb, var(--iris) 38%, transparent),
                 0 8px 32px -8px color-mix(in srgb, var(--iris) 45%, transparent);
  /* Glass recipe — pair --glass-bg with backdrop-filter: var(--glass-blur)
     and a hairline var(--edge) border. Used by .lp-top, modals, floating UI. */
  --glass-bg: color-mix(in srgb, var(--panel) 72%, transparent);
  --glass-blur: blur(14px) saturate(1.4);
  /* Motion — one vocabulary: quick hovers (--dur-1), component moves
     (--dur-2), entrances (--dur-3). */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.3, .5, 1);
  --dur-1: 120ms; --dur-2: 200ms; --dur-3: 320ms;

  --sans: "InterVariable", "Inter", "SF Pro Display", "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, "Liberation Mono", monospace;
  /* Product diagram spectrum — semantic node colors, never brand accents. */
  --d-indigo: #6d7cff; --d-sky: #0ea5e9; --d-green: #10b981; --d-amber: #f59e0b;
  --d-coral: #ef4444; --d-violet: #8b5cf6; --d-pink: #ec4899;
  /* Legacy warm accent (favicon amber) — a few editor rules still read it. */
  --marigold: #f2a31c; --marigold-deep: #d98a0e;
  /* The MARK's own colour — crisp vivid orange, ONE value on every surface
     (logo dot, wordmark "ium", favicons via build_brand_assets.py). Inside
     the TOKENS block so the generated pages inherit it. Not accent-driven:
     the logo must not change when the accent does. */
  --mark: #f97316;

  /* ---- Legacy aliases: the app's existing rules read these names.
     Mapping them onto the brand tokens re-skins the whole app at once. ---- */
  --chrome: var(--paper);
  --chrome-2: var(--panel);
  --chrome-3: var(--panel-2);
  --border: var(--edge);
  --border-soft: #262626;
  --text: var(--ink);
  --muted: #bdbdbd;
  --accent: var(--iris);
  --accent-ink: var(--iris-ink);
  --on-accent: var(--on-signal);
  --wordmark: #ffffff; /* brand wordmark — max-bright on the dark chrome */
  --accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
  --accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
  --danger: #f0546a;
  --canvas-bg: #d9dcea;
  --font: var(--sans);
}

/* App-chrome light mode — a manual toggle (js/app.js), separate from the
   per-diagram canvas themes (Classic/Ocean/.../Midnight) in js/render.js,
   which only color the rendered SVG and are unaffected by this. */
[data-ui-theme="light"] {
  --ink: #111320;
  --ink-2: #2a2d40;
  --paper: #f5f6fa;
  --panel: #ffffff;
  --panel-2: #eceef5;
  /* Light half of Sapphire: mature blue with a darker text ramp. */
  --iris: #1d4ed8;
  --iris-bright: #315efb;
  --iris-deep: #1e3a8a;
  --iris-ink: #1e40af;
  --iris-soft: #dbeafe;
  --on-signal: #ffffff;
  --slate: #4b5270;
  --slate-2: #6b7290;
  --edge: #e2e4f0;
  --dot: #d5d9e8;
  --faint: #676d86;
  --shadow: 0 1px 2px rgba(17, 19, 32, .05), 0 12px 32px -12px rgba(17, 19, 32, .14);
  --shadow-sm: 0 1px 2px rgba(17, 19, 32, .06), 0 4px 12px -6px rgba(17, 19, 32, .1);
  --shadow-lg: 0 1px 3px rgba(17, 19, 32, .07), 0 28px 64px -18px rgba(17, 19, 32, .2);

  --wordmark: #14161c; /* strong ink on the light chrome */
  --muted: #5d6480;
  --border-soft: #e8eaf4;
  --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
  --accent-ring: color-mix(in srgb, var(--accent) 26%, transparent);
  --danger: #d8324a;
  --canvas-bg: #e7e9f2;
}

/* ---- ACCENT PALETTES ---------------------------------------------------
   Inside the TOKENS block ON PURPOSE: scripts/build_pages.py copies only this
   region into the generated marketing pages, which inline their own CSS
   rather than linking styles.css. Defined below the block (where they started
   out) the app went orange and /pages/about.html stayed iris — the site split
   in two the moment anyone picked a colour. */

/* ---- dark ground (default chrome) ---- */
:root[data-accent="orange"] { --iris:#e8590c; --iris-bright:#ff8a3d; --iris-deep:#c2410c; --iris-ink:#ff9d5c; --iris-soft:#2a1a0f; }
:root[data-accent="blue"]   { --iris:#2563eb; --iris-bright:#60a5fa; --iris-deep:#1d4ed8; --iris-ink:#7cb3ff; --iris-soft:#0f1b33; }
:root[data-accent="teal"]   { --iris:#0d9488; --iris-bright:#2dd4bf; --iris-deep:#0f766e; --iris-ink:#5eead4; --iris-soft:#0c2321; }
:root[data-accent="rose"]   { --iris:#e11d48; --iris-bright:#fb7185; --iris-deep:#be123c; --iris-ink:#ff8da1; --iris-soft:#2b1018; }
:root[data-accent="amber"]  { --iris:#f59e0b; --iris-bright:#fbbf24; --iris-deep:#d97706; --iris-ink:#fcd34d; --iris-soft:#2a1f08;
  /* Amber is the one accent light enough that WHITE fails on it — #fff on
     #f59e0b is 2.15:1, unreadable on a button. Every other palette keeps the
     white default (iris itself is 3.92, the bar this site already sets for
     large/UI text). Flipping the label to near-black instead of darkening the
     amber is what keeps it amber. */
  --on-signal: #1a1205; }
/* Same problem as amber: #fff on lime is 2.7:1. Dark label, keep the hue. */
:root[data-accent="lime"] { --on-signal: #101705; }
:root[data-accent="green"]  { --iris:#16a34a; --iris-bright:#4ade80; --iris-deep:#15803d; --iris-ink:#6ee7a0; --iris-soft:#0d2417; }
:root[data-accent="violet"] { --iris:#7c3aed; --iris-bright:#a78bfa; --iris-deep:#6d28d9; --iris-ink:#c4b5fd; --iris-soft:#1e1633; }
:root[data-accent="magenta"]{ --iris:#c026d3; --iris-bright:#e879f9; --iris-deep:#a21caf; --iris-ink:#f0abfc; --iris-soft:#280a2c; }
:root[data-accent="cyan"]   { --iris:#0891b2; --iris-bright:#22d3ee; --iris-deep:#0e7490; --iris-ink:#67e8f9; --iris-soft:#082530; }
:root[data-accent="indigo"] { --iris:#4f46e5; --iris-bright:#818cf8; --iris-deep:#4338ca; --iris-ink:#a5b4fc; --iris-soft:#141733; }
:root[data-accent="lime"]   { --iris:#65a30d; --iris-bright:#a3e635; --iris-deep:#4d7c0f; --iris-ink:#bef264; --iris-soft:#182210; }
:root[data-accent="slate"]  { --iris:#64748b; --iris-bright:#94a3b8; --iris-deep:#475569; --iris-ink:#cbd5e1; --iris-soft:#161a24; }
/* Midnight Indigo is 1.74:1 on the near-black chrome — as a base it would be a
   smudge, so the DARK ramp runs a step brighter and keeps #312E81 for the
   pressed state, where deep is the point. Its light ramp uses the named hex
   directly (10.58:1 there). Midnight Slate #0F172A is its tint: unusable as an
   accent, exactly right as a surface. */
:root[data-accent="midnight"] { --iris:#4338ca; --iris-bright:#6366f1; --iris-deep:#312e81; --iris-ink:#a5b4fc; --iris-soft:#0f172a; }
:root[data-accent="sky"]      { --iris:#0ea5e9; --iris-bright:#38bdf8; --iris-deep:#0284c7; --iris-ink:#7dd3fc; --iris-soft:#07202e;
  /* White on #0ea5e9 is 2.77:1 — same problem as amber and lime. */
  --on-signal: #04121c; }
:root[data-accent="emerald"]  { --iris:#10b981; --iris-bright:#34d399; --iris-deep:#059669; --iris-ink:#6ee7b7; --iris-soft:#062a20;
  /* White on #10b981 is 2.54:1. */
  --on-signal: #04180f; }
:root[data-accent="coral"]    { --iris:#f43f5e; --iris-bright:#fb7185; --iris-deep:#e11d48; --iris-ink:#fda4af; --iris-soft:#2c0f16; }

/* ---- light ground: deeper bases so the accent stays readable AS TEXT ---- */
[data-ui-theme="light"][data-accent="orange"] { --iris:#c2410c; --iris-bright:#e8590c; --iris-deep:#9a3412; --iris-ink:#9a3412; --iris-soft:#ffedd5; }
[data-ui-theme="light"][data-accent="blue"]   { --iris:#1d4ed8; --iris-bright:#2563eb; --iris-deep:#1e40af; --iris-ink:#1e40af; --iris-soft:#dbeafe; }
[data-ui-theme="light"][data-accent="teal"]   { --iris:#0f766e; --iris-bright:#0d9488; --iris-deep:#115e59; --iris-ink:#115e59; --iris-soft:#ccfbf1; }
[data-ui-theme="light"][data-accent="rose"]   { --iris:#be123c; --iris-bright:#e11d48; --iris-deep:#9f1239; --iris-ink:#9f1239; --iris-soft:#ffe4e6; }
/* Amber is the one that cannot keep its own hue on white — #f59e0b is 2.1:1
   there. The light ramp drops to bronze so the text stays legible. */
[data-ui-theme="light"][data-accent="amber"]  { --iris:#b45309; --iris-bright:#d97706; --iris-deep:#92400e; --iris-ink:#92400e; --iris-soft:#fef3c7; }
[data-ui-theme="light"][data-accent="green"]  { --iris:#15803d; --iris-bright:#16a34a; --iris-deep:#166534; --iris-ink:#166534; --iris-soft:#dcfce7; }
[data-ui-theme="light"][data-accent="violet"] { --iris:#7c3aed; --iris-bright:#8b5cf6; --iris-deep:#6d28d9; --iris-ink:#6d28d9; --iris-soft:#ede9fe; }
[data-ui-theme="light"][data-accent="magenta"]{ --iris:#a21caf; --iris-bright:#c026d3; --iris-deep:#86198f; --iris-ink:#86198f; --iris-soft:#fae8ff; }
[data-ui-theme="light"][data-accent="cyan"]   { --iris:#0e7490; --iris-bright:#0891b2; --iris-deep:#155e75; --iris-ink:#155e75; --iris-soft:#cffafe; }
[data-ui-theme="light"][data-accent="indigo"] { --iris:#4338ca; --iris-bright:#4f46e5; --iris-deep:#3730a3; --iris-ink:#3730a3; --iris-soft:#f5f3ff; }
/* Lime, like amber, is far too light to be text on white — #65a30d is 3.3:1
   there. The light ramp drops to olive so labels stay legible. */
[data-ui-theme="light"][data-accent="lime"]   { --iris:#4d7c0f; --iris-bright:#65a30d; --iris-deep:#3f6212; --iris-ink:#3f6212; --iris-soft:#ecfccb; }
[data-ui-theme="light"][data-accent="slate"]  { --iris:#475569; --iris-bright:#64748b; --iris-deep:#334155; --iris-ink:#334155; --iris-soft:#e2e8f0; }
/* Lavender Mist #F5F3FF is 1.02:1 on the light ground — invisible as an
   accent, and a perfect tint. It is the soft fill for both indigo families. */
[data-ui-theme="light"][data-accent="midnight"] { --iris:#312e81; --iris-bright:#4338ca; --iris-deep:#1e1b4b; --iris-ink:#1e1b4b; --iris-soft:#f5f3ff; }
[data-ui-theme="light"][data-accent="sky"]      { --iris:#0369a1; --iris-bright:#0284c7; --iris-deep:#075985; --iris-ink:#075985; --iris-soft:#e0f2fe; --on-signal:#ffffff; }
[data-ui-theme="light"][data-accent="emerald"]  { --iris:#047857; --iris-bright:#059669; --iris-deep:#065f46; --iris-ink:#065f46; --iris-soft:#d1fae5; --on-signal:#ffffff; }
[data-ui-theme="light"][data-accent="coral"]    { --iris:#be123c; --iris-bright:#e11d48; --iris-deep:#9f1239; --iris-ink:#9f1239; --iris-soft:#ffe4e6; }

/* TOKENS END */
/* A few spots use hand-picked colors instead of the variables above (tuned
   for the dark chrome specifically) and need their own light-mode override. */
[data-ui-theme="light"] .toast { background: #ffffff; box-shadow: 0 10px 30px rgba(20, 24, 40, 0.16); }
[data-ui-theme="light"] .modal-backdrop { background: rgba(60, 66, 90, 0.35); }
[data-ui-theme="light"] ::-webkit-scrollbar-thumb { background: rgba(60, 66, 90, 0.22); }
[data-ui-theme="light"] ::-webkit-scrollbar-thumb:hover { background-color: rgba(60, 66, 90, 0.35); }
[data-ui-theme="light"] #canvasWrap::-webkit-scrollbar-thumb { background-color: rgba(60, 66, 90, 0.18); }

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

/* Pre-paint routing — the inline script in index.html's <head> sets these on
   <html> based on the URL, and boot() removes them. They stop the editor chrome
   from flashing before boot() runs on window 'load': on the home route the
   static #homePage overlay is shown right away (it covers the editor); on
   home/explore the editor chrome is kept invisible until the overlay is ready.
   More specific than [hidden]{display:none} so it wins for #homePage. */
.preboot-overlay #topbar,
.preboot-overlay #main { visibility: hidden; }
.preboot-home #homePage { display: flex !important; }
/* Same trick for /search: show its (fixed, full-page) view before the first
   paint so the editor underneath is never seen. js/search.js takes over at
   DOMContentLoaded and boot() clears the class. */
.preboot-search #searchPage { display: flex !important; }
html, body { height: 100%; }
/* Mobile browsers used to report the largest possible viewport for `100vh`,
   even while their address bar or on-screen keyboard covered part of the
   app.  The editor and Present stage are full-height flex layouts, so that
   stale measurement translated directly into cropped controls / a diagram
   fitted for pixels the viewer could not see.  Modern dynamic viewport units
   track the actually visible window; the preceding 100% remains the portable
   fallback for older offline browsers. */
@supports (height: 100dvh) {
  html, body { height: 100dvh; }
}
body {
  font-family: var(--font);
  font-size: 13px;
  color: var(--text);
  background: var(--chrome);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
/* Presentation type is captured and compressed again for video. Let the
   platform retain its native stem weight instead of thinning every glyph. */
body.presenting { -webkit-font-smoothing: auto; }

button { font-family: inherit; font-size: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input, textarea, select { font-family: inherit; font-size: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ============ Top bar ============ */
#topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  padding: 0 14px;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  -webkit-backdrop-filter: saturate(1.2) blur(10px);
  backdrop-filter: saturate(1.2) blur(10px);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.02) inset, var(--shadow-sm);
  flex: none;
  z-index: 20;
}
.brand {
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 8px 4px 4px;
  border-radius: 8px;
  transition: background .12s;
}
button.brand:hover { background: var(--chrome-2); }
.tool-chip {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border: 1px solid var(--accent-ring);
  padding: 3px 8px;
  border-radius: 6px;
  white-space: nowrap;
}
.brand {
  font-family: var(--sans);
}
/* Editor topbar wordmark — the artifact lockup, sized down for the dense bar. */
.brand .wordmark { font-family: 'Diagramium Wordmark', var(--sans); font-size: 17px; font-weight: 700; letter-spacing: -0.02em; color: var(--wordmark); }
.brand .wordmark .um { color: var(--mark); }
.brand:hover .wordmark { color: var(--wordmark); }
.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  color: var(--slate);
}
.brand-mark svg { width: 40px; height: 40px; display: block; }
#docTitle {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  padding: 6px 10px;
  width: clamp(120px, 16vw, 240px); /* yields space before bar buttons wrap */
  min-width: 0;
  font-size: 13px;
  color: var(--text);
  transition: border-color .15s, background .15s;
}
#docTitle:hover { background: var(--chrome-2); }
#docTitle:focus { background: var(--chrome-2); border-color: var(--border); outline: none; }
#docTitle::placeholder { color: var(--muted); }

.tb-group {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--chrome-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 2px;
}
.tb-btn {
  padding: 5px 9px;
  border-radius: 6px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap; /* Inter runs wider than SF Pro — never wrap bar labels */
  transition: background .12s, color .12s;
}
.tb-btn:hover:not(:disabled) { background: var(--chrome-3); color: var(--text); }
.tb-btn:disabled { opacity: .35; cursor: default; }
/* Save button: an iris dot appears while the doc has unsaved changes */
#btnSaveDoc { position: relative; }
#btnSaveDoc.dirty::after {
  content: "";
  position: absolute; top: 3px; right: 3px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--iris-bright);
}
/* Save-to-file status chip (same treatment as the kids app): amber while the
   work only lives in this browser, green once it's safely in a file. */
.save-state {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font-size: 11.5px; font-weight: 650; white-space: nowrap;
  padding: 4px 10px; border-radius: 999px; border: 1px solid var(--edge);
  color: var(--muted);
  margin-right: 2px;
}
.save-state[hidden] { display: none !important; }
.save-state .ss-dot { width: 8px; height: 8px; border-radius: 999px; background: currentColor; flex: none; }
/* The saved file's name: shown, never allowed to push the bar apart. */
.save-state .ss-file { max-width: 180px; overflow: hidden; text-overflow: ellipsis; font-weight: 500; opacity: .85; }
.save-state .ss-file::before { content: "·"; margin-right: 5px; opacity: .6; }
@media (max-width: 1180px) { .save-state .ss-file { max-width: 110px; } }
@media (max-width: 900px) { .save-state .ss-file { display: none; } }
/* Studio-monochrome save states: attention = white, settled = quiet grey. */
.save-state.is-dirty { color: #ffffff; border-color: rgba(255, 255, 255, 0.35); background: rgba(255, 255, 255, 0.08); }
.save-state.is-saved { color: #a8a8a8; border-color: var(--edge); background: rgba(255, 255, 255, 0.04); }
[data-ui-theme="light"] .save-state.is-dirty { color: #92400e; }
[data-ui-theme="light"] .save-state.is-saved { color: #15803d; }
.tb-autosave {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 6px;
  color: var(--muted); font-size: 12px; white-space: nowrap;
  cursor: pointer; user-select: none;
}
.tb-autosave input { accent-color: var(--iris); margin: 0; }
.tb-btn.wide { padding: 6px 12px; }
.tb-btn.on { background: var(--accent-soft); color: var(--accent-ink); }
/* Labeled "◑ Theme" toggle in the editor topbar — matches the home/explore pill. */
.tb-btn .glyph { font-family: var(--mono); font-size: 13px; line-height: 1; margin-right: 1px; }
.zoom-label { min-width: 48px; text-align: center; font-variant-numeric: tabular-nums; }
.spacer { flex: 1; }

.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 640;
  padding: 7px 16px;
  border-radius: 9px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .25) inset, 0 8px 20px -10px var(--accent);
  transition: filter .12s, transform .12s, box-shadow .2s;
}
.btn-primary:hover { filter: brightness(1.06); transform: translateY(-1px); box-shadow: 0 1px 0 rgba(255, 255, 255, .3) inset, 0 12px 26px -10px var(--accent); }
.btn-primary:active { transform: none; }
.btn-ghost {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 12px;
  color: var(--text);
  transition: background .12s, border-color .12s;
}
.btn-ghost:hover { background: var(--chrome-3); border-color: var(--accent); }
.btn-danger {
  border: 1px solid rgba(240, 84, 106, .4);
  color: var(--danger);
  border-radius: 8px;
  padding: 6px 12px;
  width: 100%;
  transition: background .12s;
}
.btn-danger:hover { background: rgba(240, 84, 106, .12); }

/* ============ Main layout ============ */
#main { flex: 1; display: flex; min-height: 0; }

/* ---- Palette (left) ---- */
#palette {
  width: 212px;
  flex: none;
  background: var(--chrome);
  border-right: 1px solid var(--border);
  padding: 14px 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pal-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-top: 6px;
}
.pal-title:first-child { margin-top: 0; }
.pal-hint { font-size: 11px; color: var(--muted); opacity: .75; margin-top: -4px; }
.pal-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}

/* collapsible shape groups */
#palGroups { display: flex; flex-direction: column; gap: 4px; }
.pal-group { border-bottom: 1px solid var(--border-soft); padding-bottom: 8px; }
.pal-group:last-child { border-bottom: none; padding-bottom: 0; }
.pal-group > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 2px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  user-select: none;
  -webkit-user-select: none;
}
.pal-group > summary::-webkit-details-marker { display: none; }
.pal-group > summary:hover { color: var(--text); }
.pal-group > summary .pal-chevron {
  display: inline-flex;
  transition: transform .15s ease;
  font-size: 9px;
  color: var(--muted);
}
.pal-group[open] > summary .pal-chevron { transform: rotate(90deg); }
.pal-group > summary .pal-count {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  color: var(--muted);
  opacity: .7;
  letter-spacing: 0;
  text-transform: none;
}
.pal-group-body { padding-top: 2px; display: flex; flex-direction: column; gap: 7px; }
.pal-group-hint { font-size: 11px; color: var(--muted); opacity: .75; }
.pal-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 10px 4px 8px;
  background: var(--chrome-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  transition: border-color .12s, background .12s, transform .08s;
  text-align: center;
}
.pal-item:hover { border-color: var(--accent); background: var(--chrome-3); transform: translateY(-1px); }
.pal-item:active { cursor: grabbing; transform: none; }
.pal-glyph { font-size: 19px; line-height: 1; }
.pal-glyph svg { display: block; }
.pal-name { font-size: 11px; color: var(--muted); }
.pal-item:hover .pal-name { color: var(--text); }
.pal-footer {
  margin-top: auto;
  padding-top: 12px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
  opacity: .8;
  border-top: 1px solid var(--border-soft);
}

/* ---- Canvas (center) ---- */
#canvasWrap {
  flex: 1;
  min-width: 0;
  position: relative;
  overflow: auto;
  background: var(--canvas-bg);
  background-image: radial-gradient(rgba(20, 22, 31, 0.10) 1px, transparent 1px);
  background-size: 22px 22px;
}
#zoomLayer {
  position: relative;
  display: inline-block;
  padding: 34px;
  min-width: 100%;
  min-height: 100%;
}
#svgHost { display: inline-block; }
#svgHost svg {
  display: block;
  border-radius: 10px;
  box-shadow: 0 2px 6px rgba(15, 18, 32, 0.14), 0 14px 44px rgba(15, 18, 32, 0.16);
}

/* interactive affordances inside the SVG */
#svgHost [data-hit] { cursor: pointer; }
#svgHost [data-hit="lifeline"] { cursor: crosshair; }
#svgHost [data-hit="lifeline"]:hover { fill: rgba(109, 124, 255, 0.10); }
#svgHost [data-hit="actor"] { cursor: grab; }
#svgHost [data-hit="item"]:hover { fill: rgba(109, 124, 255, 0.08); }
#svgHost [data-sm="port"], #svgHost [data-fc="port"], #svgHost [data-mm="port"], #svgHost [data-sl="port"] { cursor: crosshair; }
#svgHost [data-sm="node"], #svgHost [data-fc="node"], #svgHost [data-mm="node"], #svgHost [data-sl="node"], #svgHost [data-oc="person"], #svgHost [data-oc-note] { cursor: grab; }
#svgHost [data-tl="card"], #svgHost [data-tl="marker"] { cursor: pointer; }
#svgHost [data-tl="cardResize"] { cursor: ew-resize; }
#svgHost [data-jm="stageHeader"], #svgHost [data-jm="rowLabel"], #svgHost [data-jm="cell"] { cursor: pointer; }
#svgHost [data-sm="resize"], #svgHost [data-fc="resize"], #svgHost [data-mm="resize"], #svgHost [data-sl="resize"], #svgHost [data-oc-resize], #svgHost [data-oc-note-resize] { cursor: nwse-resize; }
#svgHost [data-sm="bend"], #svgHost [data-fc="bend"], #svgHost [data-mm="bend"], #svgHost [data-sl="bend"] { cursor: grab; }
#svgHost [data-mm="boundary"] { cursor: pointer; }

/* Free-floating text elements — borderless by default, so give them a
   PowerPoint-style dashed outline on hover to stay discoverable/selectable. */
#svgHost [data-hit="float"], #svgHost [data-fc="text"], #svgHost [data-sm="text"], #svgHost [data-mm="text"], #svgHost [data-sl="text"], #svgHost [data-tl="text"], #svgHost [data-jm="text"], #svgHost [data-oc-text] { cursor: grab; }
#svgHost [data-hit="floatResize"], #svgHost [data-fc="textResize"], #svgHost [data-sm="textResize"], #svgHost [data-mm="textResize"], #svgHost [data-sl="textResize"], #svgHost [data-tl="textResize"], #svgHost [data-jm="textResize"], #svgHost [data-oc-text-resize] { cursor: nwse-resize; }
#svgHost [data-hit="float"]:hover, #svgHost [data-fc="text"]:hover, #svgHost [data-sm="text"]:hover, #svgHost [data-mm="text"]:hover, #svgHost [data-sl="text"]:hover, #svgHost [data-tl="text"]:hover, #svgHost [data-jm="text"]:hover, #svgHost [data-oc-text]:hover {
  stroke: rgba(109, 124, 255, 0.4); stroke-width: 1; stroke-dasharray: 4 3;
}

/* Connection ports stay hidden until you hover the shape or it's selected —
   pure CSS (no per-pointermove JS) since :hover on the group already fires from
   hovering the always-hit-testable shape body. */
#svgHost .fc-node .fc-port, #svgHost .sm-node .sm-port, #svgHost .mm-node .mm-port, #svgHost .sl-node .sl-port { opacity: 0; pointer-events: none; transition: opacity .12s ease; }
/* While a connector is being drawn, EVERY shape shows every magnet, so the
   drop target is visible before the pointer gets there. Hovering one grows
   it, which is the "leave the arrow here" affordance. */
body.dgm-connecting #svgHost :is(.fc-port, .sm-port, .sl-port, .mm-port) {
  opacity: 1; pointer-events: auto;
}
#svgHost :is(.fc-port, .sm-port, .sl-port, .mm-port):hover {
  r: 6.5; filter: drop-shadow(0 0 5px rgba(109, 124, 255, .9));
}
#svgHost .fc-node:hover .fc-port, #svgHost .fc-node.selected .fc-port,
#svgHost .sm-node:hover .sm-port, #svgHost .sm-node.selected .sm-port,
#svgHost .mm-node:hover .mm-port, #svgHost .mm-node.selected .mm-port,
#svgHost .sl-node:hover .sl-port, #svgHost .sl-node.selected .sl-port { opacity: 1; pointer-events: auto; }
/* Connector ENDPOINT handles — the two rings on a selected connector. They
   are the "unplug this end" affordance, so they read as grabbable and grow
   under the pointer the same way a magnet does. Drawn only while the edge is
   selected, so they need no visibility rule of their own. */
#svgHost :is(.fc-endpoint, .sm-endpoint, .sl-endpoint) {
  cursor: grab; transition: r .12s ease, filter .12s ease;
}
#svgHost :is(.fc-endpoint, .sm-endpoint, .sl-endpoint):hover {
  r: 8; filter: drop-shadow(0 0 6px rgba(109, 124, 255, .95));
}
body.dgm-connecting #svgHost :is(.fc-endpoint, .sm-endpoint, .sl-endpoint) { cursor: grabbing; }
#svgHost [data-sl="laneResize"] { cursor: row-resize; }
#svgHost [data-sl="laneHeader"] { cursor: pointer; }

/* Timeline card resize handle stays hidden until the card is hovered or selected. */
#svgHost .tl-card .tl-resize { opacity: 0; pointer-events: none; transition: opacity .12s ease; }
#svgHost .tl-card:hover .tl-resize, #svgHost .tl-card.selected .tl-resize { opacity: 1; pointer-events: auto; }

#inlineEdit {
  position: absolute;
  z-index: 10;
  border: 1.5px solid var(--accent);
  border-radius: 5px;
  padding: 2px 6px;
  background: #fff;
  color: #1f2430;
  box-shadow: 0 4px 14px rgba(15, 18, 32, 0.25);
  text-align: center;
}

#inlineEditMulti {
  position: absolute;
  z-index: 10;
  border: 1.5px solid var(--accent);
  border-radius: 5px;
  padding: 3px 6px;
  background: #fff;
  color: #1f2430;
  box-shadow: 0 4px 14px rgba(15, 18, 32, 0.25);
  text-align: center;
  font-family: inherit;
  line-height: 1.3;
  resize: none;
  overflow-y: auto;
}

#emptyState {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.empty-card {
  pointer-events: auto;
  text-align: center;
  color: #4a5065;
  padding: 30px 40px;
}
.empty-glyph {
  width: 54px; height: 54px;
  margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--marigold), var(--marigold-deep));
  color: var(--on-accent);
  font-size: 26px;
  box-shadow: 0 10px 24px -8px color-mix(in srgb, var(--marigold) 60%, transparent);
}
.empty-card h2 { font-size: 17px; color: #262b3d; margin-bottom: 6px; }
.empty-card p { font-size: 13px; line-height: 1.55; margin-bottom: 16px; }

/* ============================================================
   Present mode — "Stagecraft". Cinema-dark glass chrome that stays
   deliberately theme-constant (film-projector logic: the sheet is the
   screen, the chrome is the theater), floating clusters, tooltips on
   everything, auto-hiding during playback (body.pr-idle), an intro and
   end slide, popovers for narration/music/motion settings, laser & pen
   overlays and a step spotlight. JS contracts preserved: element ids,
   .show/.on/.pos-* / .speak/.pnl-* state classes, inline style hooks on
   #prProgress/#prBrand/#prNarration/#prTitleCard*.
   ============================================================ */
#prBrand { display: none; }
.presenting #prBrand {
  display: flex; align-items: center; gap: 8px;
  position: absolute; bottom: calc(18px + var(--pr-brand-lift, 0px)); left: 18px; z-index: 5;
  pointer-events: none;
  padding: 6px 13px 6px 10px; border-radius: 999px;
  /* Near-solid black: the pill must read as a crisp badge on ANY sheet color —
     at 55% alpha it dissolved into light canvases. */
  background: rgba(6, 7, 11, 0.94);
  -webkit-backdrop-filter: saturate(1.3) blur(12px);
  backdrop-filter: saturate(1.3) blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.75);
  opacity: 0;
  animation: prBrandIn .5s ease .15s forwards;
  transition: opacity .35s ease, bottom .25s ease;
}
#prBrand svg { width: 24px; height: 24px; display: block; color: #c3cbdb; }
.pr-brand-word { font-family: var(--sans); font-weight: 700; font-size: 14.5px; letter-spacing: -0.03em; color: #ffffff; }
.pr-brand-word .um { color: var(--iris-bright); }
@keyframes prBrandIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .presenting #prBrand { animation: none; opacity: 1; } }

/* ---- Branded show frame: a slim iris ring around the whole stage. ----
   Gradient border via the padding + mask-composite trick so the middle stays
   fully transparent; z-index 3 keeps it under the spotlight (4) and every
   control. Deliberately thin — chrome, not furniture. */
#prFrame { display: none; }
.presenting #prFrame {
  display: block;
  position: absolute; inset: 8px; z-index: 3;
  pointer-events: none;
  border-radius: 18px;
  box-shadow: inset 0 0 60px -18px rgba(124, 108, 248, 0.16);
  opacity: 0;
  animation: prBrandIn .5s ease .1s forwards;
}
.presenting #prFrame::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: 18px;
  padding: 1.5px;
  background: linear-gradient(135deg,
    rgba(156, 141, 255, 0.85), rgba(124, 108, 248, 0.35) 30%,
    rgba(124, 108, 248, 0.22) 60%, rgba(156, 141, 255, 0.75));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
@media (prefers-reduced-motion: reduce) { .presenting #prFrame { animation: none; opacity: 1; } }

/* ---- The TV unit ----
   While presenting, #stage itself becomes the branded container: dark bezel
   (real padding, so fitPresent() sizes the diagram into the smaller screen),
   a header row inside the bezel, and the diagram sheet as a rounded "screen"
   card. The notes panel turns into a floating card INSIDE the unit (below,
   overriding its full-height dock). The show is the content; Diagramium is
   the set it plays on. */
body.presenting #stage {
  background: #0b0d14;
  /* --pr-plate is the nameplate's height; the top lane is sized from it. */
  --pr-plate: 36px;
  /* viewport-fit=cover lets the show paint under the cutout and the home
     indicator, so the stage owes the insets on EVERY edge — and it owes them
     at every width, not inside a phone breakpoint: the orientation people
     actually present in is LANDSCAPE, which is precisely when the notch
     moves to a side edge and the 18px gutter stops clearing it. max() keeps
     the original numbers everywhere the insets are 0, which is every desktop
     and every phone without a cutout. */
  padding:
    calc(var(--pr-plate, 36px) + 9px + env(safe-area-inset-top, 0px))
    max(10px, env(safe-area-inset-right, 0px))
    max(10px, env(safe-area-inset-bottom, 0px))
    max(10px, env(safe-area-inset-left, 0px));
}
body.presenting #canvasWrap { background: transparent; }
/* Lanes: a whisper of air under the nameplate, and a reserved band at the
   bottom for the numbered stepper (the old top progress track is hidden
   while presenting — the stepper replaces it). Constant, not toggle-aware,
   so the framing never jumps. */
/* Two reserved lanes, and both reserve their FULL height.
   Top: the stepper, which moved up here from the bottom band.
   Bottom: --pr-band is the measured height the control bar actually occupies
   (its own bottom offset + its height, so a bar that wraps to two rows on a
   narrow canvas reports a taller band). Reserving `band - N` was the old
   behaviour and it meant the bar always sat ON the drawing — 33px of it on a
   wrapped two-row bar. Reserve the whole band plus a gutter so the diagram
   gets a clean lane and the bar docks below it rather than over it. */
body.presenting #canvasWrap {
  /* ONE definition of the show's lane, so everything that has to line up with
     the diagram reads the same two numbers. The notes panel used its own
     hand-tuned offsets and drifted 24px high at the top and 63px short at the
     bottom; now it cannot, because it inherits these. */
  --pr-lane-top: 28px;
  --pr-lane-bottom: calc(var(--pr-band, 66px) + 8px);
  padding-top: var(--pr-lane-top);
  padding-bottom: var(--pr-lane-bottom);
}
body.presenting #prProgress { display: none; }

/* ---- The stepper: numbered, clickable step dots, under the nameplate. ----
   It used to sit at the bottom, floating over the diagram: the canvas is
   centred in the remaining space, so on a tall diagram the dots landed ON the
   drawing. Anchored to the top instead, it sits in the band between the
   nameplate and the canvas, which is chrome either way — nothing to overlap.
   #prStepper is a child of #canvasWrap, whose box already starts just below
   the 45px nameplate, so `top` here is measured from that edge. */
#prStepper { display: none; }
body.presenting #prStepper:not([hidden]) {
  display: flex;
  align-items: center;
  gap: 16px;
  position: absolute;
  left: 30px;
  /* Spans the DIAGRAM column only: JS sets --pr-step-right to the notes
     panel's footprint so the dots never run under it. */
  right: var(--pr-step-right, 30px);
  top: 4px;
  z-index: 6;
}
#prStepDots {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  padding: 4px 0;
}
.pr-step-dot {
  position: relative;
  flex: none;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: rgba(233, 236, 255, 0.55);
  font: 600 11.5px var(--sans);
  cursor: pointer;
  padding: 0;
  transition: background .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.pr-step-dot + .pr-step-dot { margin-left: var(--pr-dot-gap, 26px); }
.pr-step-dot + .pr-step-dot::before {
  content: '';
  position: absolute;
  right: 100%;
  top: 50%;
  width: var(--pr-dot-gap, 26px);
  height: 2px;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.12);
}
/* A step that carries an authored note — the stepper's chapter marker. */
.pr-step-dot.chapter::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -7px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  transform: translateX(-50%);
  background: color-mix(in srgb, var(--iris) 75%, #fff);
}
.pr-step-dot.done {
  background: color-mix(in srgb, var(--iris) 42%, #14162a);
  border-color: color-mix(in srgb, var(--iris) 65%, transparent);
  color: #fff;
}
.pr-step-dot.done::before, .pr-step-dot.now::before { background: color-mix(in srgb, var(--iris) 70%, transparent); }
.pr-step-dot.now {
  background: #10131f;
  border-color: #43e0b0;
  color: #fff;
  box-shadow: 0 0 0 3px rgba(67, 224, 176, 0.22);
}
.pr-step-dot:hover { border-color: rgba(255, 255, 255, 0.45); }
/* Compact mode for long decks: plain dots, tighter run. */
#prStepDots.mini .pr-step-dot { width: 11px; height: 11px; font-size: 0; }
#prStepDots.mini .pr-step-dot + .pr-step-dot::before { height: 1.5px; }
#prStepDots.mini .pr-step-dot.chapter::after { bottom: -6px; }
/* Lives in the nameplate now, immediately before the step arrows.
   The auto margin has to sit on THIS element, and #prTvNav's has to be
   cancelled: with one on each, flexbox splits the free space between them and
   the clock parks in the middle of the header; with it only on the nav, the
   clock stays glued to the title. Collecting the slack here pushes the clock
   and the arrows to the right edge as one group. When the clock is empty the
   nav keeps its own auto margin and still right-aligns on its own. */
#prStepTime { display: none; }
body.presenting #prStepTime:not(:empty) + #prTvNav { margin-left: 0; }
body.presenting #prStepTime:not(:empty) {
  display: block;
  flex: none;
  margin-left: auto;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: rgba(233, 236, 255, 0.55);
  white-space: nowrap;
}
/* The stepper left the bottom band, so the caption and karaoke subtitle can
   drop back down to just above the control bar. */
body.presenting #prCaption, body.presenting #prSubtitle { bottom: calc(var(--pr-band, 66px) + 18px); }

/* ---- Premium notes-panel structure (Present mode only). ---- */
#prNoteStep, #prNoteIcon, #prNoteTitle, #prNoteTakeaway { display: none; }
body.presenting #prNoteStep:not([hidden]) {
  display: block;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--iris-bright);
  margin: 0 0 12px;
}
body.presenting #prNoteIcon:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  background: color-mix(in srgb, var(--iris) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--iris) 36%, transparent);
  color: var(--iris-bright);
  margin: 0 0 10px;
}
#prNoteIcon svg { width: 26px; height: 26px; display: block; }
body.presenting #prNoteTitle:not([hidden]) {
  display: block;
  font-size: calc(19px * var(--pr-text-k, 1));
  font-weight: 750;
  line-height: 1.25;
  color: #fff;
  margin: 0 0 10px;
}
body.presenting #prNoteTakeaway:not([hidden]) {
  display: block;
  flex: none;
  margin-top: 12px;
  padding: 11px 13px;
  border-radius: 12px;
  background: color-mix(in srgb, #43e0b0 9%, transparent);
  border: 1px solid color-mix(in srgb, #43e0b0 28%, transparent);
}
.pr-tk-head {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #43e0b0;
  margin-bottom: 5px;
}
#prNoteTakeawayText { font-size: calc(13.5px * var(--pr-text-k, 1)); line-height: 1.5; color: rgba(233, 236, 255, 0.92); }

/* The stage holds still through a show — only the spotlight glides — for as
   long as the whole drawing is READABLE where it stands. When it is not (see
   the smart camera in app.js) the sheet becomes a window onto the drawing and
   turns like a page between regions, which is the only way a 4:1 diagram of
   13px labels is a presentation rather than a picture of one. */
body.presenting #prSpotlight {
  transition: left .55s cubic-bezier(0.25, 0.65, 0.3, 1), top .55s cubic-bezier(0.25, 0.65, 0.3, 1),
              width .55s cubic-bezier(0.25, 0.65, 0.3, 1), height .55s cubic-bezier(0.25, 0.65, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  body.presenting #prSpotlight { transition: none; }
  body.presenting #prTvHead { animation: none; opacity: 1; }
}

/* ---- Header step navigation: ‹ Step n of m › ---- */
#prTvNav {
  margin-left: auto;
  flex: none;
  display: flex;
  align-items: center;
  gap: 2px;
  pointer-events: auto;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 999px;
  padding: 3px;
}
#prTvNav button {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: rgba(233, 236, 255, 0.75);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
#prTvNav button:hover { background: rgba(255, 255, 255, 0.12); color: #fff; }
#prTvNav button svg { width: 15px; height: 15px; }
/* Notes-panel head + takeaway icons */
.pr-nh-label { display: inline-flex; align-items: center; gap: 6px; }
.pr-nh-label svg, .pr-tk-head svg { width: 13px; height: 13px; flex: none; }
.pr-tk-head { display: flex; align-items: center; gap: 6px; }
#prNarrationHeadBtns svg { width: 15px; height: 15px; display: block; }


/* ---- Deep-dive rows: "Why this matters" / "Technical detail" ---- */
.pr-note-x { display: none; }
body.presenting .pr-note-x:not([hidden]) {
  display: block;
  flex: none;
  margin-top: 10px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.09);
  overflow: hidden;
}
.pr-note-x-h {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 11px 13px;
  background: none;
  border: 0;
  color: rgba(233, 236, 255, 0.9);
  font: 600 13.5px var(--sans);
  cursor: pointer;
  text-align: left;
}
.pr-note-x-h > svg:first-child { width: 16px; height: 16px; flex: none; color: var(--iris-bright); }
.pr-note-x-h span { flex: 1 1 auto; }
.pr-note-x-chev { width: 14px; height: 14px; flex: none; opacity: .6; transition: transform .3s ease; }
.pr-note-x.open .pr-note-x-chev { transform: rotate(180deg); }
.pr-note-x-b {
  display: none;
  padding: 0 13px 12px 38px;
  font-size: 13px;
  line-height: 1.55;
  color: rgba(233, 236, 255, 0.78);
}
.pr-note-x.open .pr-note-x-b { display: block; }

/* ---- Control bar: the play control becomes the glowing centerpiece. ---- */
body.presenting #prPlay {
  border-radius: 999px;
  min-width: 66px;
  font-weight: 750;
  background: linear-gradient(180deg, var(--iris-bright), var(--iris-deep));
  color: #fff;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--iris) 22%, transparent),
              0 10px 26px -10px var(--iris);
}
body.presenting #svgHost {
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 20px 56px -30px rgba(0, 0, 0, 0.72), 0 0 0 1px rgba(255, 255, 255, 0.08);
}
/* Spotlight stage-fill is deliberately a VIEWER choice. The authored card
   still owns its layout and portable JSON; Explain simply removes the outer
   presentation tile and lets the one- or two-card compositor consume the
   measured stage. Text, images and mini-diagrams therefore scale together. */
body.presenting.pr-spot-fill #svgHost {
  background: transparent !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  overflow: hidden;
}
body.presenting.pr-spot-fill #svgHost .spot-card-surface {
  fill: transparent !important;
  fill-opacity: 0 !important;
  stroke: none !important;
}
@keyframes spotWordInkIn {
  from { opacity: 0; filter: blur(1.4px); }
  62% { opacity: 1; filter: blur(0.25px); }
  to { opacity: 1; filter: none; }
}
body.presenting #svgHost .spot-word-ink-in {
  animation: spotWordInkIn .3s cubic-bezier(.22,1,.36,1) both;
}
body.presenting #svgHost .spot-diagram-tracer {
  filter: drop-shadow(0 0 2px currentColor);
  animation: spotDiagramTracerFade .74s linear both;
}
/* The writing hand must never be guillotined at the sheet edge: a composed
   book page holds only its own page's ink, so letting its svg overflow
   costs nothing — the hand simply hangs over the desk when it writes near
   a corner, exactly as a real hand would. Scoped to book pages: filmstrip
   svgs RELY on viewport clipping to hide the neighbouring cards. */
body.presenting #svgHost > svg[data-pr-book-composed="1"] {
  overflow: visible;
}
/* The chapter eyebrow's entrance: the TOPIC kicker tracks in from wide
   letter-spacing (the editorial "title settling into place" idiom) and the
   title rule / accent tab wipes in from the left. The final keyframes match
   the painted attributes, so nothing snaps when the animation releases. */
@keyframes spotKickerIn {
  from { opacity: 0; letter-spacing: 11px; transform: translateY(10px); }
  50% { opacity: 1; }
  to { opacity: 1; letter-spacing: 1.25px; transform: none; }
}
body.presenting #svgHost .spot-kicker-in {
  transform-box: fill-box;
  animation: spotKickerIn .9s cubic-bezier(.22,1,.36,1) both;
}
/* The page's running head settles in with each page turn — same editorial
   tracking idiom as the kicker, quieter and slower. The compositor stamps
   the class on every composed sheet, so a fresh page replays it; exports
   render the same element static. */
@keyframes spotRunheadIn {
  from { opacity: 0; letter-spacing: calc(var(--pr-runhead-track, 3px) + 4px); }
  to { opacity: 1; letter-spacing: var(--pr-runhead-track, 3px); }
}
body.presenting #svgHost .spot-book-runhead {
  animation: spotRunheadIn .9s cubic-bezier(.22,1,.36,1) both;
}
/* The writing hand PRESSES while it writes or traces and LIFTS between jobs
   (SpotCardStory toggles .is-down). The nib sits at the glyph's bottom-left,
   so the lift pivots there: the hand rises and rolls back a few degrees, the
   way a pen comes off paper, and lands flat again for the next word. */
.spot-book-writer .spot-book-writer-arm {
  transform-box: fill-box;
  transform-origin: 0% 100%;
  transform: translate(3px, -9px) rotate(-4deg);
  transition: transform .24s cubic-bezier(.3, .1, .25, 1);
  will-change: transform;
}
.spot-book-writer.is-down .spot-book-writer-arm {
  transform: translate(0, 0) rotate(0deg);
  transition-duration: .13s;
}
@media (prefers-reduced-motion: reduce) {
  .spot-book-writer .spot-book-writer-arm { transition: none; transform: none; }
}
@keyframes spotRuleIn {
  from { transform: scaleX(0); opacity: 0; }
  30% { opacity: 1; }
  to { transform: scaleX(1); opacity: 1; }
}
body.presenting #svgHost .spot-rule-in {
  transform-box: fill-box;
  transform-origin: left center;
  animation: spotRuleIn .85s cubic-bezier(.3,.1,.25,1) .22s both;
}
@keyframes spotDiagramTracerFade {
  0%, 72% { opacity: .9; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting #svgHost .spot-word-ink-in,
  body.presenting #svgHost .spot-kicker-in,
  body.presenting #svgHost .spot-rule-in,
  body.presenting #svgHost .spot-book-runhead,
  body.presenting #svgHost .spot-diagram-tracer { animation: none !important; filter: none; }
}
/* The pre-roll is a clean title/splash surface.  Keep the already-mounted
   editor SVG and guide reservation out of sight until app.js releases the
   first real step; visibility preserves the measured stage geometry. */
body.pr-opening-hold #svgHost,
body.pr-opening-hold #prSheetTitle,
body.pr-opening-hold #prNarration,
body.pr-opening-hold #prCaption,
body.pr-opening-hold #prTvHead,
body.pr-opening-hold #presentBar,
body.pr-opening-hold #prProgress,
body.pr-opening-hold #prStepper {
  visibility: hidden;
}
#prTvHead { display: none; }
/* The unit's nameplate: a tinted label bar hugging the ring's top edge, so
   the whole container reads as one branded appliance. It carries the document
   title, and a title belongs at the head. (Briefly docked to the foot; that
   was a misread of a note about the TITLE SLIDE's logo, not this bar.) */
body.presenting #prTvHead {
  display: flex;
  align-items: center;
  gap: 9px;
  position: absolute;
  top: 5px;
  left: 5px;
  right: 5px;
  height: var(--pr-plate, 36px);
  padding: 0 12px;
  z-index: 5;
  pointer-events: none;
  color: #c3cbdb;
  background: linear-gradient(180deg, rgba(124, 108, 248, 0.20), rgba(124, 108, 248, 0.07) 78%, rgba(124, 108, 248, 0.03));
  border-bottom: 1px solid rgba(156, 141, 255, 0.22);
  border-radius: 11px 11px 0 0;
  opacity: 0;
  animation: prBrandIn .5s ease .12s forwards;
}
body.presenting #prTvHead svg { width: 18px; height: 18px; flex: none; }
#prTvHome {
  appearance: none;
  width: 24px;
  height: 24px;
  padding: 3px;
  border: 0;
  border-radius: 7px;
  color: inherit;
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
}
#prTvHome:hover:not(:disabled) { background: rgba(255, 255, 255, .10); }
#prTvHome:focus-visible { outline: 2px solid var(--iris-bright); outline-offset: 2px; }
#prTvHome:disabled { cursor: default; opacity: .72; }
.pr-tv-word { font-family: var(--sans); font-weight: 700; font-size: 14px; letter-spacing: -0.03em; color: #fff; white-space: nowrap; }
.pr-tv-word .um { color: var(--iris-bright); }
#prTvTitle {
  font-size: 12.5px;
  color: rgba(233, 236, 255, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 0 1 auto;
}
#prTvTitle:not(:empty)::before { content: '·'; margin-right: 9px; color: rgba(233, 236, 255, 0.35); }
/* Lives inside the #prTvNav pill, which supplies the chrome. */
#prTvStep {
  flex: none;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: rgba(233, 236, 255, 0.82);
  padding: 0 9px;
  white-space: nowrap;
}
#prTvNav[hidden] { display: none; }
/* The header carries the brand now — retire the corner pill while presenting.
   NOTE: the present overlays (progress, notes, caption…) live inside
   #canvasWrap, which the stage's bezel padding already pushes below the
   header — their own offsets are bezel-relative. */
body.presenting #prBrand { display: none; }
/* Notes: from full-height dock to a floating card inside the unit. The
   background/color/left/right land inline from positionNotesPanel(), hence
   the !importants — everything else the stylesheet owns. Present chrome is
   dark in both themes (intentional), so the card is too; the note-style
   presets keep styling the inner text card. */
body.presenting #prNarration {
  /* Exactly the diagram's lane — same top, same bottom, same height. The panel
     is a child of #canvasWrap, so it inherits both lane variables and stays
     flush with the sheet whatever the control bar does (a wrapped two-row bar
     moves both edges together). */
  top: var(--pr-lane-top, 34px);
  bottom: var(--pr-lane-bottom, calc(var(--pr-band, 66px) + 12px));
  max-height: none;
  border-radius: 12px;
  min-width: 250px;
  background: rgba(15, 17, 27, 0.92) !important;
  color: #e9ecff !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  box-shadow: 0 22px 60px -24px rgba(0, 0, 0, 0.8) !important;
  -webkit-backdrop-filter: blur(12px) saturate(1.2);
  backdrop-filter: blur(12px) saturate(1.2);
}
body.presenting #prNarration.pos-right { right: 26px !important; left: auto !important; }
body.presenting #prNarration.pos-left { left: 26px !important; right: auto !important; }

/* ---- The control bar: one floating glass pill, clustered. ---- */
#presentBar {
  position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%);
  display: flex; align-items: stretch; gap: 10px;
  max-width: calc(100% - 24px);
  background: rgba(13, 15, 24, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 18px;
  padding: 8px;
  z-index: 7;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .08) inset, 0 18px 48px -16px rgba(0, 0, 0, 0.65);
  -webkit-backdrop-filter: blur(18px) saturate(1.5);
  backdrop-filter: blur(18px) saturate(1.5);
  transition: opacity .35s ease, transform .35s ease;
}
.prc { display: flex; align-items: center; gap: 2px; position: relative; }
.prc + .prc::before {
  content: ""; align-self: center; width: 1px; height: 22px;
  background: rgba(255, 255, 255, 0.12); margin-right: 8px; flex: none;
}
.prc-status { gap: 10px; padding: 0 6px; }
#prCount { font-size: 12.5px; color: rgba(232, 234, 244, .92); font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 600; }
#prTime { font-family: var(--mono); font-size: 11px; color: rgba(232, 234, 244, .82); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pr-btn {
  position: relative;
  padding: 7px 11px; border-radius: 10px;
  color: rgba(232, 234, 244, .9);
  font-size: 13px; white-space: nowrap; cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.pr-btn:hover { background: rgba(255, 255, 255, .1); color: #fff; }
.pr-btn:active { transform: scale(.94); }
.pr-ico { width: 36px; height: 34px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.pr-ico svg { width: 17px; height: 17px; display: block; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.pr-play {
  background: var(--iris); color: #fff; font-weight: 640; min-width: 66px;
  margin: 0 3px; border-radius: 999px; padding: 7px 16px;
  box-shadow: 0 1px 0 rgba(255,255,255,.22) inset, 0 6px 18px -6px color-mix(in srgb, var(--iris) 70%, transparent);
  transition: filter var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-spring);
}
.pr-play:hover { background: var(--iris); filter: brightness(1.1); transform: scale(1.03); }
.pr-btn.on, .pr-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--iris) 30%, transparent); color: #cfc8ff; box-shadow: 0 0 0 1px color-mix(in srgb, var(--iris) 45%, transparent) inset; }
.pr-exit { color: rgba(232, 234, 244, .85); font-weight: 560; }
.pr-exit:hover { color: #fff; background: rgba(240, 84, 106, .22); }
.pr-rec-dot { fill: currentColor; stroke: none; }
#prRecord:hover .pr-rec-dot { fill: #f0546a; }
/* Legacy select kept for app.js's speed contract — visually replaced by the
   pace slider in settings. (Hidden stub wrapper in markup.) */

/* ---- Tooltips: every control explains itself. ---- */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%) translateY(3px);
  background: rgba(10, 12, 20, 0.94); color: #e8eaf4;
  font-size: 11.5px; font-weight: 500; letter-spacing: .01em; line-height: 1.35;
  padding: 6px 10px; border-radius: 8px; border: 1px solid rgba(255,255,255,.1);
  white-space: nowrap; pointer-events: none; opacity: 0; z-index: 30;
  box-shadow: 0 8px 24px -8px rgba(0,0,0,.6);
  transition: opacity .18s ease .3s, transform .18s ease .3s;
}
[data-tip]:hover::after, [data-tip]:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
[data-tip]::after { max-width: min(260px, 60vw); white-space: normal; width: max-content; text-align: center; }
/* Edge buttons anchor their tooltip to the near edge so it can't spill out. */
.prc:first-child > [data-tip]:first-child::after { left: 0; transform: translateX(0) translateY(3px); }
.prc:first-child > [data-tip]:first-child:hover::after,
.prc:first-child > [data-tip]:first-child:focus-visible::after { transform: translateX(0) translateY(0); }
.prc:last-child > [data-tip]:last-child::after { left: auto; right: 0; transform: translateX(0) translateY(3px); }
.prc:last-child > [data-tip]:last-child:hover::after,
.prc:last-child > [data-tip]:last-child:focus-visible::after { transform: translateX(0) translateY(0); }
/* Inside the scrolling popovers a floating tooltip would be clipped by the
   panel and (on flex rows) would become a stray flex item, so it is suppressed
   there — those controls carry visible labels already. Buttons keep theirs. */
.pr-pop .pr-slider-row[data-tip]::after,
.pr-pop .pr-check[data-tip]::after,
.pr-pop .pr-voice-row[data-tip]::after { content: none; }
.pr-pop button[data-tip]::after { max-width: 200px; }

/* ---- Auto-hide during playback (body.pr-idle set by js/present-plus.js).
   The brand lockup deliberately stays: every slide keeps the Diagramium mark. */
body.pr-idle #presentBar, body.pr-idle .pr-pop { opacity: 0; transform: translateX(-50%) translateY(10px); pointer-events: none; }
body.pr-idle #canvasWrap, body.pr-idle #canvasWrap * { cursor: none; }

/* ---- Zen mode (body.pr-zen, set by setPresentZen in js/app.js): a genuine
   full-bleed diagram, not a smaller version of the podium. The frame, brand,
   header, guide and notes all leave; only the existing auto-hidden transport
   dock returns on pointer movement so touch users still have a way out. */
body.pr-zen #prTvHead, body.pr-zen #prStepper,
body.pr-zen #prProgress, body.pr-zen #prCaption, body.pr-zen #prBrand,
body.pr-zen #prFrame, body.pr-zen #prSegBar { display: none !important; }
body.pr-zen:not(.pr-zen-notes) #prNarration { display: none !important; }
/* The karaoke strip STAYS in zen — it is narration, not podium — but it
   cannot ride the collapsed band: every bottom strip stacks off --pr-band,
   which zen pins to 10px so the woken dock may overlay the sheet, and that
   drops the subtitle underneath the dock. --pr-plate-lift is the bar's real
   occupied height, published on #stage by syncBottomBand from LAYOUT metrics
   (so a faded pr-idle bar still reports its slot and the strip never hops). */
body.pr-zen #prSubtitle { bottom: calc(var(--pr-plate-lift, 66px) + 12px); }
body.pr-zen #canvasWrap, body.pr-zen #stage { --pr-band: 10px !important; }
/* Zen is a single continuous sheet, including the title lane — a dark stage
   behind a light diagram makes the title feel like leftover chrome. */
body.pr-zen.presenting #stage { padding: 0; background: var(--pr-sheet, #fff); }
body.pr-zen:not(.pr-zen-notes):not(.pr-zen-title).presenting #canvasWrap {
  --pr-lane-top: 0px;
  --pr-lane-bottom: 0px;
  padding: 0 !important;
  background: var(--pr-sheet, #fff);
}
body.pr-zen #zoomLayer { padding: 0; }
body.pr-zen #svgHost, body.pr-zen #svgHost svg {
  border-radius: 0;
  box-shadow: none;
}
/* The authored document title is often centred inside the drawing and can be
   cropped by the readability camera. Zen owns one quiet, always-visible
   sheet-native title bar instead. Its mark and count are deliberately small:
   they orient the audience without competing with the diagram. */
#prZenTitle { display: none; }
/* The outgoing cross-fade frame is reparented from #svgHost into a temporary
   sibling. Keep the authored heading hidden there too; otherwise it becomes
   visible again for the ghost's 420–700ms lifetime on every Next/autoplay
   transition, which records as a one-frame title splash. */
body.pr-zen #svgHost g[data-role="doc-title"],
body.pr-zen #canvasWrap > .pr-frame-ghost g[data-role="doc-title"] { display: none; }
body.pr-zen-title #prZenTitle {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  z-index: 6;
  top: 0;
  left: 0;
  right: 0;
  box-sizing: border-box;
  min-height: clamp(60px, 8vh, 80px);
  padding: clamp(12px, 2vh, 20px) clamp(16px, 5vw, 72px) clamp(10px, 1.5vh, 15px);
  color: var(--pr-sheet-ink, #1b1b22);
  background: color-mix(in srgb, var(--iris) 5%, var(--pr-sheet, #fff));
  pointer-events: none;
  text-shadow: none;
}
/* The title itself gets a protected middle lane. The two positioned bookends
   stay genuinely flush to the bar's sides, while a long title cannot overlap
   either one on a narrow screen. */
#prZenTitleText {
  display: block;
  min-width: 0;
  max-width: min(76vw, calc(100% - 148px));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: inherit;
  font: 700 clamp(18px, 2vw, 30px)/1.2 var(--sans);
  letter-spacing: -.025em;
  text-align: center;
}
#prZenMark {
  position: absolute;
  left: clamp(16px, 3vw, 40px);
  width: clamp(20px, 2.15vw, 27px);
  height: clamp(20px, 2.15vw, 27px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 82%, var(--iris));
  appearance: none;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  pointer-events: auto;
}
#prZenMark svg { display: block; width: 100%; height: 100%; }
#prZenMark:hover:not(:disabled) { background: color-mix(in srgb, var(--iris) 10%, transparent); }
#prZenMark:focus-visible { outline: 2px solid var(--iris); outline-offset: 3px; }
#prZenMark:disabled { cursor: default; opacity: .72; }
#prZenStep {
  position: absolute;
  right: clamp(16px, 3vw, 40px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 50px;
  padding: 4px 8px;
  border-radius: 999px;
  color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 78%, var(--pr-sheet, #fff));
  background: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 6%, var(--pr-sheet, #fff));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 10%, transparent) inset;
  font: 650 clamp(10.5px, 1vw, 12px)/1 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: .035em;
  white-space: nowrap;
}
/* This is a layout lane, not a visual frame: the diagram's fit is measured
   against the remaining space, so the title never sits on top of a node. */
body.pr-zen-title.presenting #canvasWrap {
  padding-top: clamp(60px, 8vh, 80px) !important;
}
/* Zen's optional Step Guide is a first-class split layout, not an overlay.
   Keep it beneath the bare title, while the normal reserve logic handles its
   side/bottom footprint and preserves the full note treatment (image + why). */
body.pr-zen-notes.pr-zen-title:not(.pr-notes-bottom) #prNarration {
  top: clamp(60px, 8vh, 80px) !important;
}
/* Opening and closing cards are still show content in Zen — never a reason
   to bring back the old dark theatre overlay. The card title itself already
   inherits the document sheet inline; these two modal surfaces need the same
   treatment so the whole show reads as one continuous canvas. */
body.pr-zen #prIntro,
body.pr-zen #prEnd {
  background: var(--pr-sheet, #fff);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.pr-zen #prIntro .pr-intro-card,
body.pr-zen #prEnd .pr-end-card { color: var(--pr-sheet-ink, #1b1b22); }
body.pr-zen #prIntro .pr-intro-mark,
body.pr-zen #prEnd .pr-end-mark { color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 76%, var(--pr-sheet, #fff)); }
body.pr-zen #prIntro .pr-brandin-word { color: var(--pr-sheet-ink, #1b1b22); }
body.pr-zen #prIntro .pr-intro-meta span,
body.pr-zen #prIntro .pr-intro-foot,
body.pr-zen #prEnd .pr-end-sub,
body.pr-zen #prEnd .pr-end-h,
body.pr-zen #prEnd .pr-end-takeaways li,
body.pr-zen #prEnd .pr-end-share-txt small,
body.pr-zen #prEnd .pr-end-brand { color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 68%, var(--pr-sheet, #fff)); }
/* The wordmark inside that line has to follow it. Zen paints the end slide on
   the SHEET (opaque, and usually white), while the base rule below sets the
   wordmark to a near-white that only makes sense on the dark scrim a non-zen
   end slide draws for itself — measured at 1.11 contrast on a white sheet,
   i.e. "Made with" legible and "Diagram" gone. Emphasis here means CLOSER TO
   THE INK, not brighter: mixing against the sheet's own ink is what makes
   that flip correctly on a chalkboard or blueprint sheet too. */
body.pr-zen #prEnd .pr-end-brand .dbrand { color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 88%, var(--pr-sheet, #fff)); }
body.pr-zen #prIntro .pr-intro-meta span,
body.pr-zen #prIntro .pr-mini,
body.pr-zen #prEnd .pr-end-btn:not(.pr-end-primary) {
  border-color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 18%, var(--pr-sheet, #fff));
}
body.pr-zen #prIntro .pr-mini,
body.pr-zen #prEnd .pr-end-btn:not(.pr-end-primary) {
  color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 86%, var(--pr-sheet, #fff));
  background: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 6%, var(--pr-sheet, #fff));
}
body.pr-zen #prIntro .pr-mini:hover,
body.pr-zen #prEnd .pr-end-btn:not(.pr-end-primary):hover {
  background: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 11%, var(--pr-sheet, #fff));
}
#prZenToggle.on { background: color-mix(in srgb, var(--iris) 30%, transparent); color: #cfc8ff; }

/* ---- Tap-zone feedback (#prTapFx, js/app.js gesture layer): a soft
   directional chevron that breathes once where the tap landed. Pure
   feedback — pointer-events none, aria-hidden, removed from flow when
   hidden. ---- */
#prTapFx {
  position: absolute; top: 50%; z-index: 8;
  width: 56px; height: 56px; margin-top: -28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(13, 15, 24, 0.5);
  color: rgba(240, 242, 252, 0.95);
  pointer-events: none;
  opacity: 0;
}
#prTapFx[hidden] { display: none; }
#prTapFx svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
/* Offset from the DIAGRAM column, not the wrap: absolute offsets resolve
   against the padding box, and the notes reserve is paid as padding — so a
   plain `right: 18px` put the forward chevron on top of the notes panel.
   The lanes are published by reserveNotesColumn (publishTapLanes). */
#prTapFx.left { left: calc(18px + var(--pr-tap-left, 0px)); }
#prTapFx.right { right: calc(18px + var(--pr-tap-right, 0px)); }
#prTapFx.left svg { transform: rotate(180deg); }
#prTapFx.show { animation: prTapPulse .38s cubic-bezier(0, 0, 0.2, 1); }
@keyframes prTapPulse {
  0% { opacity: 0; transform: scale(.82); }
  30% { opacity: .95; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  #prTapFx.show { animation: none; opacity: .8; transition: opacity .25s ease; }
}

/* ---- Segmented step progress (#prSegBar, present-plus.js) ---------------
   A slim strip of cells over the top of the stage: filled behind you, bright
   where you are, faint ahead. Yields to the opt-in numbered stepper. */
body.presenting #prSegBar {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  z-index: 24; display: flex; gap: 4px; padding: 4px 6px;
  max-width: min(680px, 72vw);
  background: color-mix(in srgb, #0b0d14 55%, transparent);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: opacity .35s ease;
}
#prSegBar[hidden] { display: none; }
#prSegBar .pr-seg {
  flex: 1 1 0; min-width: 10px; height: 4px; padding: 0; border: 0;
  border-radius: 999px; cursor: pointer;
  background: rgba(233, 236, 255, .22);
  transition: background .3s ease, transform .2s ease;
}
#prSegBar .pr-seg:hover { transform: scaleY(1.8); }
#prSegBar .pr-seg.is-done { background: color-mix(in srgb, var(--iris, #6a5cff) 60%, transparent); }
#prSegBar .pr-seg.is-active {
  background: var(--iris-bright, #8b80ff);
  box-shadow: 0 0 8px color-mix(in srgb, var(--iris-bright, #8b80ff) 70%, transparent);
}
body.pr-idle #prSegBar { opacity: .35; }

/* ---- Step Guide collapse (body.pr-guide-collapsed) ----------------------
   The panel folds to a slim rail; content is hidden, never removed.
   layoutPresentChrome measures the panel's REAL rect, so the sheet takes
   the reclaimed width with no second geometry. */
#prGuideCollapse svg { transition: transform .25s ease; }
body.pr-guide-collapsed #prNarration { width: 46px !important; min-width: 46px !important; cursor: pointer; overflow: hidden; }
body.pr-guide-collapsed #prNarration > :not(#prNarrationHead) { display: none !important; }
body.pr-guide-collapsed #prNarrationHead { flex-direction: column; gap: 10px; }
body.pr-guide-collapsed .pr-nh-label { writing-mode: vertical-rl; }
body.pr-guide-collapsed .pr-nh-label svg { display: none; }
body.pr-guide-collapsed #prNarrationEditBtn, body.pr-guide-collapsed #prNarrationFlip { display: none; }
body.pr-guide-collapsed #prGuideCollapse svg { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
  #prSegBar, #prSegBar .pr-seg, #prGuideCollapse svg { transition: none; }
}

/* ---- Captions & live subtitles. ----
   Everything in the bottom band stacks off --pr-band: the height #presentBar
   actually occupies, measured by js/present-plus.js (syncBottomBand). The old
   fixed 78px assumed a single-row bar, but the bar wraps to two rows whenever
   the CANVAS is narrow (side panels open, not just small screens) and then sat
   right on top of the caption. The 66px fallback reproduces the original
   offsets exactly, so nothing moves before the first measurement. */
/* ---- The reading sizes -------------------------------------------------
   Every piece of type an audience READS during a show — the note, the
   subtitle strip, the step caption, the why bubble — is written as
   `calc(<size> * var(--pr-text-k, 1))` so smart stage can lift the lot with
   one number (body.pr-smart below) and leave every relationship between them
   intact. A multiplier rather than a second set of sizes on purpose: the
   audience skins already set their own sizes on a heavier selector, and
   another absolute rule would have to out-specify them one at a time and then
   stay in step forever. Unset it is exactly 1, which is what "intelligence
   off" has to mean.
   ---------------------------------------------------------------------- */
body.pr-smart { --pr-text-k: 1.12; }
/* Viewer-owned reading distance. These override the automatic Smart Stage
   multiplier without touching the diagram document; the SVG planner receives
   the matching measured-pixel targets from presentAdaptiveStageSpec(). */
body.presenting[data-pr-viewing="mobile"] { --pr-text-k: 1.16; }
body.presenting[data-pr-viewing="laptop"] { --pr-text-k: 1.12; }
body.presenting[data-pr-viewing="tv"] { --pr-text-k: 1.32; }

#prCaption {
  position: absolute; left: 50%; bottom: calc(12px + var(--pr-band, 66px)); transform: translateX(-50%);
  width: max-content; max-width: min(760px, 88%);
  background: rgba(12, 14, 22, 0.8);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  color: #fff; border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px; padding: 10px 20px;
  font-size: calc(16px * var(--pr-text-k, 1)); font-weight: 650; line-height: 1.35; text-align: center;
  z-index: 6; opacity: 0; transition: opacity .25s ease, transform .25s ease;
  pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#prCaption.show { opacity: 1; }
/* `width: max-content` for the same reason #presentBar needs it: an
   absolutely-positioned box with only `left: 50%` shrink-to-fits into the
   space to the RIGHT of that 50%, so max-width never got to do its job and a
   wrapping subtitle was stuck at half the canvas (three lines where two fit).
   The caption escaped this only because `nowrap` makes its min-content huge. */
#prSubtitle {
  position: absolute; left: 50%; bottom: calc(12px + var(--pr-band, 66px)); transform: translateX(-50%);
  width: max-content; max-width: min(820px, 90%);
  background: rgba(12, 14, 22, 0.86);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  color: #fff; border: 1px solid color-mix(in srgb, var(--iris) 35%, transparent);
  border-left: 3px solid var(--iris);
  border-radius: 12px; padding: 11px 20px;
  font-size: calc(16.5px * var(--pr-text-k, 1)); font-weight: 600; line-height: 1.45; text-align: left;
  z-index: 6; pointer-events: none;
}
#prSubtitle b { color: var(--iris-bright); font-weight: inherit; }

/* ---- Audience skins ----------------------------------------------------
   body.pr-aud-<key> is stamped by the Audience preset (present-plus.js).
   Present-only re-tints: the chrome stays DARK in every skin (deliberate,
   same rule as the base stage) — these shift its hue and scale the reading
   surfaces, they never lighten the room. The notes-text bumps repeat the
   full #prNarration[data-note-style] chain because that selector's
   specificity is what beats the per-style font rules below it. */
body.presenting.pr-aud-kids #stage {
  background: linear-gradient(180deg, #221046 0%, #2c1258 58%, #3a1766 100%);
}
body.pr-aud-kids #prCaption {
  background: rgba(255, 209, 102, 0.94); color: #3a2500;
  border-color: rgba(212, 150, 0, 0.8); font-weight: 750; font-size: calc(17.5px * var(--pr-text-k, 1));
}
body.pr-aud-kids #prSubtitle { font-size: calc(19px * var(--pr-text-k, 1)); line-height: 1.5; }
body.pr-aud-kids #prNarration[data-note-style] #prNarrationText { font-size: calc(17.5px * var(--pr-text-k, 1)); line-height: 1.62; }
body.presenting.pr-aud-tween #stage {
  background: linear-gradient(180deg, #0b1f1b 0%, #0f2c26 58%, #123a30 100%);
}
body.pr-aud-tween #prCaption { border-color: rgba(52, 211, 153, 0.45); }
body.pr-aud-tween #prSubtitle { font-size: calc(17.5px * var(--pr-text-k, 1)); }
body.pr-aud-tween #prNarration[data-note-style] #prNarrationText { font-size: calc(16px * var(--pr-text-k, 1)); line-height: 1.55; }

/* ---- Title card (legacy quick card, still used in watch mode). ---- */
#prTitleCard {
  position: absolute; inset: 0; z-index: 7;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center; padding: 24px;
  opacity: 0; transition: none; pointer-events: none;
}
#prTitleCard.show { opacity: 1; }
#prTitleCardHeader, #prTitleCardFooter {
  font-size: clamp(15px, 1.35vw, 22px); font-weight: 650; line-height: 1.4; max-width: 80%;
}
#prTitleCardTitle {
  font-size: clamp(30px, 4.6vw, 68px); font-weight: 800; line-height: 1.1; max-width: 86%;
}
/* Captures leave the fully opaque title on a frame boundary. Glow/skin title
   shadows are disabled only in the recorded file, where they soften stems. */
body.pr-rec #prTitleCardTitle,
body.pr-rec #prTitleCardHeader,
body.pr-rec #prTitleCardFooter,
body.pr-rec #prZenTitleText,
body.pr-rec #prTvTitle { text-shadow: none !important; }

/* ---- Intro screen. ---- */
#prIntro, #prEnd {
  position: absolute; inset: 0; z-index: 8;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background:
    radial-gradient(900px 480px at 50% 20%, color-mix(in srgb, var(--iris) 10%, transparent), transparent 70%),
    rgba(8, 9, 15, 0.78);
  -webkit-backdrop-filter: blur(14px) saturate(1.2); backdrop-filter: blur(14px) saturate(1.2);
}
.pr-intro-card, .pr-end-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  max-width: min(620px, 92%); max-height: 100%; overflow-y: auto; padding: 10px;
  color: #eef0f8;
  animation: prCardIn .5s var(--ease-out) both;
}
@keyframes prCardIn { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
.pr-intro-eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: #8b80ff; margin-bottom: 16px;
}
.pr-intro-title { font-size: clamp(28px, 4.6vw, 52px); font-weight: 680; letter-spacing: -0.03em; line-height: 1.08; text-wrap: balance; }
.pr-intro-meta { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 18px; }
.pr-intro-meta span {
  font-family: var(--mono); font-size: 11.5px; color: rgba(238,240,248,.72);
  border: 1px solid rgba(255,255,255,.16); border-radius: 999px; padding: 5px 12px;
}
.pr-intro-play {
  margin-top: 34px;
  display: inline-flex; align-items: center; gap: 12px;
  font-size: 17px; font-weight: 640; color: #fff; cursor: pointer;
  background: var(--iris); border: none; border-radius: 999px; padding: 14px 34px 14px 24px;
  box-shadow: 0 1px 0 rgba(255,255,255,.24) inset, 0 16px 44px -12px color-mix(in srgb, var(--iris) 85%, transparent);
  transition: transform var(--dur-2) var(--ease-spring), filter var(--dur-1) var(--ease-out);
  position: relative;
}
.pr-intro-play:hover { transform: scale(1.045); filter: brightness(1.08); }
.pr-intro-play::after { content: ""; position: absolute; inset: 0; border-radius: 999px; border: 1.5px solid var(--iris-bright); opacity: 0; pointer-events: none; }
.pr-intro-play:hover::after { animation: lp-play-ring .9s var(--ease-out); }
.pr-intro-play-ico {
  width: 34px; height: 34px; border-radius: 50%; background: rgba(255,255,255,.2);
  display: inline-flex; align-items: center; justify-content: center; font-size: 13px; padding-left: 2px;
}
.pr-intro-row { display: flex; gap: 10px; margin-top: 16px; }
.pr-intro-foot { margin-top: 26px; font-family: var(--mono); font-size: 11px; color: rgba(238,240,248,.45); }
.pr-mini {
  font: inherit; font-size: 12.5px; font-weight: 560; color: rgba(238,240,248,.85); cursor: pointer;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.14); border-radius: 9px;
  padding: 7px 13px;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.pr-mini:hover { background: rgba(255,255,255,.15); border-color: rgba(255,255,255,.3); }
.pr-mini-wide { width: 100%; margin-top: 8px; text-align: center; }

/* ---- End slide. ---- */
.pr-end-mark { width: 46px; height: 46px; color: #8b93ad; margin-bottom: 14px; }
.pr-end-mark svg { width: 100%; height: 100%; }
.pr-end-title { font-size: clamp(30px, 4.6vw, 50px); font-weight: 680; letter-spacing: -0.03em; }
.pr-end-sub { margin-top: 10px; font-size: 14.5px; color: rgba(238,240,248,.7); }
.pr-end-takeaways { margin-top: 22px; width: 100%; max-width: 460px; text-align: left; }
.pr-end-h { font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: rgba(238,240,248,.5); margin-bottom: 8px; }
.pr-end-takeaways ol { margin: 0; padding: 0 0 0 20px; display: flex; flex-direction: column; gap: 6px; }
.pr-end-takeaways li { font-size: 13.5px; line-height: 1.45; color: rgba(238,240,248,.85); }
.pr-end-share { margin-top: 22px; display: flex; align-items: center; gap: 16px; }
.pr-end-share svg { width: 92px; height: 92px; border-radius: 10px; background: #fff; padding: 6px; color: #10121a; }
.pr-end-share-txt { text-align: left; display: flex; flex-direction: column; gap: 8px; }
.pr-end-share-txt small { font-size: 11.5px; color: rgba(238,240,248,.55); max-width: 220px; line-height: 1.45; }
.pr-end-ctas { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 26px; }
.pr-end-btn {
  font: inherit; font-size: 13.5px; font-weight: 580; color: rgba(238,240,248,.9); cursor: pointer;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.14); border-radius: 11px;
  padding: 10px 18px;
  transition: background var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.pr-end-btn:hover { background: rgba(255,255,255,.16); transform: translateY(-1px); }
.pr-end-primary { background: var(--iris); border-color: transparent; color: #fff; box-shadow: 0 10px 26px -10px color-mix(in srgb, var(--iris) 80%, transparent); }
.pr-end-primary:hover { background: var(--iris); filter: brightness(1.08); }
.pr-end-brand { margin-top: 28px; font-size: 12px; color: rgba(238,240,248,.5); }
.pr-end-brand .dbrand { color: rgba(238,240,248,.8); }

/* ---- Popovers (settings / share / record). ---- */
.pr-pop {
  position: absolute; bottom: 76px; left: 50%; transform: translateX(-50%);
  width: min(340px, calc(100% - 28px)); max-height: min(66vh, 560px); overflow-y: auto;
  background: rgba(13, 15, 24, 0.9);
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255,255,255,.12); border-radius: 16px;
  box-shadow: 0 1px 0 rgba(255,255,255,.07) inset, 0 24px 64px -20px rgba(0,0,0,.7);
  padding: 16px; z-index: 9; color: #e8eaf4;
  animation: prPopIn .22s var(--ease-out) both;
}
@keyframes prPopIn { from { opacity: 0; transform: translateX(-50%) translateY(8px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
/* Phones: the popover becomes a full-width bottom sheet — thumb-reachable,
   rounded top, riding above the home indicator. Same element, same wiring. */
@media (max-width: 760px), (max-height: 560px) and (max-width: 1024px) {
  .pr-pop {
    left: 0; right: 0; bottom: 0; transform: none;
    width: auto; max-height: 72vh;
    border-radius: 18px 18px 0 0; border-left: 0; border-right: 0; border-bottom: 0;
    padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    animation: prSheetIn .26s var(--ease-out) both;
  }
  @keyframes prSheetIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
  body.pr-idle .pr-pop { transform: translateY(10px); }
}
.pr-pop-sec { padding: 12px 2px; }
.pr-pop-sec + .pr-pop-sec { border-top: 1px solid rgba(255,255,255,.08); }
.pr-pop-h { font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: rgba(232,234,244,.78); margin-bottom: 10px; }
.pr-voice-row { display: flex; gap: 8px; }
.pr-voice-row select, .pr-pop select {
  flex: 1; min-width: 0; font: inherit; font-size: 13px; color: #e8eaf4;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.14); border-radius: 9px; padding: 7px 9px;
}
.pr-pop select option { background: #14161f; color: #e8eaf4; }
.pr-slider-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; font-size: 12.5px; color: rgba(232,234,244,.8); }
.pr-slider-row span { width: 52px; flex: none; }
.pr-slider-row em { font-style: normal; font-family: var(--mono); font-size: 11px; width: 36px; text-align: right; color: rgba(232,234,244,.85); }
.pr-slider-row input[type="range"] { flex: 1; appearance: none; -webkit-appearance: none; height: 20px; background: transparent; cursor: pointer; min-width: 0; }
.pr-slider-row input[type="range"]::-webkit-slider-runnable-track { height: 3px; border-radius: 3px; background: rgba(255,255,255,.18); }
.pr-slider-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; background: var(--iris-bright);
  margin-top: -5.5px; box-shadow: 0 0 0 3px color-mix(in srgb, var(--iris) 30%, transparent);
}
.pr-slider-row input[type="range"]::-moz-range-track { height: 3px; border-radius: 3px; background: rgba(255,255,255,.18); }
.pr-slider-row input[type="range"]::-moz-range-thumb { width: 14px; height: 14px; border: none; border-radius: 50%; background: var(--iris-bright); }
.pr-check { display: flex; align-items: center; gap: 9px; font-size: 13px; color: rgba(232,234,244,.85); margin-top: 10px; cursor: pointer; }
.pr-check input { accent-color: var(--iris); width: 15px; height: 15px; }
.pr-music-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }
.pr-music-card {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 12.5px; font-weight: 540; color: rgba(232,234,244,.85);
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.1); border-radius: 10px;
  padding: 8px 10px; text-align: left;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.pr-music-card:hover { background: rgba(255,255,255,.1); }
.pr-music-card.on { border-color: var(--iris); background: color-mix(in srgb, var(--iris) 22%, transparent); color: #fff; }
.pr-seg-row { display: flex; gap: 4px; background: rgba(255,255,255,.06); border-radius: 10px; padding: 3px; }
.pr-seg {
  flex: 1; font: inherit; font-size: 12.5px; font-weight: 560; color: rgba(232,234,244,.7); cursor: pointer;
  background: transparent; border: none; border-radius: 8px; padding: 6px 4px;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.pr-seg:hover { color: #fff; }
.pr-seg.on { background: var(--iris); color: #fff; }
.pr-pop-share { width: min(360px, calc(100% - 28px)); }
.pr-pop-rec { width: min(300px, calc(100% - 28px)); }
.pr-share-preview {
  display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 11px; align-items: center;
  margin: 8px 0 10px; padding: 8px; border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px; background: rgba(255,255,255,.055);
}
.pr-share-preview img, .pr-share-preview-mark {
  width: 76px; height: 48px; object-fit: contain; border-radius: 8px;
  background: color-mix(in srgb, var(--iris) 26%, #0c1020);
}
.pr-share-preview-mark { display: grid; place-items: center; color: #fff; font: 750 22px/1 var(--sans); }
.pr-share-preview span:last-child { display: flex; min-width: 0; flex-direction: column; gap: 4px; }
.pr-share-preview b { color: #f4f6ff; font-size: 13px; line-height: 1.3; }
.pr-share-preview small { color: rgba(232,234,244,.65); font-size: 10.5px; line-height: 1.3; }
.pr-share-summary { margin: 0 0 8px; color: rgba(232,234,244,.78); font-size: 11.5px; line-height: 1.5; }
.pr-share-link { display: flex; gap: 6px; margin: 8px 0 12px; }
.pr-share-link input {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 11.5px; color: rgba(232,234,244,.85);
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.12); border-radius: 8px; padding: 7px 9px;
}
.pr-share-qr { display: flex; justify-content: center; padding: 6px 0 2px; }
.pr-share-qr svg { width: 132px; height: 132px; background: #fff; border-radius: 10px; padding: 8px; color: #10121a; }
.pr-share-note { font-size: 11.5px; line-height: 1.5; color: rgba(232,234,244,.78); margin-top: 8px; }
.pr-share-native {
  width: 100%; min-height: 36px; margin: -3px 0 6px; border: 1px solid color-mix(in srgb, var(--iris-bright) 50%, transparent);
  border-radius: 9px; background: color-mix(in srgb, var(--iris) 24%, transparent); color: #fff;
  font: 650 12px/1 var(--sans); cursor: pointer;
}
.pr-share-native:hover { background: color-mix(in srgb, var(--iris) 38%, transparent); }
.pr-rec-opt {
  display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left; cursor: pointer;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.1); border-radius: 11px;
  padding: 11px 13px; margin-top: 8px; color: #e8eaf4; font: inherit;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.pr-rec-opt:hover { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.25); }
.pr-rec-opt b { font-size: 13.5px; font-weight: 620; }
.pr-rec-opt span { font-size: 11.5px; color: rgba(232,234,244,.75); }

/* ---- Q&A panel. ---- */
#prQa {
  position: absolute; right: 16px; bottom: 76px; z-index: 9;
  width: min(340px, calc(100% - 28px)); max-height: min(60vh, 480px);
  display: flex; flex-direction: column;
  background: rgba(13, 15, 24, 0.92);
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255,255,255,.12); border-radius: 16px;
  box-shadow: 0 24px 64px -20px rgba(0,0,0,.7);
  color: #e8eaf4; overflow: hidden;
  animation: prPopIn .22s var(--ease-out) both; transform: none;
}
#prQa.pr-pop-in { animation: none; }
.pr-qa-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; font-size: 13px; font-weight: 620; border-bottom: 1px solid rgba(255,255,255,.08); }
.pr-qa-log { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.pr-qa-hint { font-size: 12px; line-height: 1.5; color: rgba(232,234,244,.75); }
.pr-qa-q { align-self: flex-end; max-width: 85%; background: var(--iris); color: #fff; border-radius: 12px 12px 3px 12px; padding: 7px 12px; font-size: 13px; }
.pr-qa-a { align-self: flex-start; max-width: 90%; background: rgba(255,255,255,.08); border-radius: 12px 12px 12px 3px; padding: 8px 12px; font-size: 13px; line-height: 1.5; }
#prQaForm { display: flex; gap: 6px; padding: 10px 12px; border-top: 1px solid rgba(255,255,255,.08); }
#prQaInput {
  flex: 1; min-width: 0; font: inherit; font-size: 13px; color: #fff;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.14); border-radius: 9px; padding: 8px 10px;
}
#prQaInput::placeholder { color: rgba(232,234,244,.4); }

/* ---- Keyboard shortcuts sheet. ---- */
#prShortcuts {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 10;
  width: min(400px, calc(100% - 32px));
  background: rgba(13, 15, 24, 0.94);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border: 1px solid rgba(255,255,255,.12); border-radius: 16px; padding: 20px 22px;
  color: #e8eaf4; box-shadow: 0 30px 80px -24px rgba(0,0,0,.8);
  animation: prCardIn .25s var(--ease-out) both;
}
.pr-keys-head { font-size: 15px; font-weight: 640; margin-bottom: 14px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pr-keys-grid { display: grid; grid-template-columns: auto 1fr; gap: 9px 16px; font-size: 13px; color: rgba(232,234,244,.8); align-items: center; }
.pr-keys-grid kbd {
  font-family: var(--mono); font-size: 11px; color: #e8eaf4;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.16); border-bottom-width: 2px;
  border-radius: 6px; padding: 2.5px 7px;
}

/* ---- Laser / pen canvas + spotlight. ---- */
#prToolsCanvas { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
body.pr-tool-laser #prToolsCanvas, body.pr-tool-pen #prToolsCanvas { pointer-events: auto; }
body.pr-tool-laser #prToolsCanvas { cursor: none; }
body.pr-tool-pen #prToolsCanvas { cursor: crosshair; }
#prSpotlight {
  /* This is a focus lens, not a blackout. The older 9999px shadow dimmed the
     entire sheet — especially unpleasant over white Zen canvases — while the
     exact node trace already tells the audience what is new. */
  position: absolute; z-index: 4; pointer-events: none; box-sizing: border-box;
  border-radius: var(--pr-focus-radius, 18px);
  border: 1.5px solid var(--pr-focus-edge, color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 72%, #1f2937));
  background: radial-gradient(ellipse at center, var(--pr-focus-fill, color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 7%, transparent)) 0%, transparent 72%);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-focus-edge, var(--pr-focus, #4f46e5)) 16%, transparent),
              0 0 18px 2px var(--pr-focus-halo, color-mix(in srgb, var(--pr-focus, #4f46e5) 20%, transparent));
  transition: left .5s var(--ease-out), top .5s var(--ease-out), width .5s var(--ease-out), height .5s var(--ease-out), opacity .3s ease;
}
/* Automatic step focus has one visual owner: the animated SVG outline that
   follows the real silhouette. Keep this positioned lens as the geometry/
   camera anchor, but do not draw a second border around the same subject.
   The deliberate cursor-spotlight tool below still paints its circular lens. */
body.presenting:not(.pr-tool-spot) #prSpotlight {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}
/* The diagram sheet, not the dark Present shell, determines focus contrast.
   `current` can be any authored palette, so app.js stamps this from its actual
   sheet colour instead of assuming a visual-theme name. */
#stage[data-pr-sheet-tone="light"] {
  --pr-focus-edge: color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 76%, #17213b);
  --pr-focus-halo: color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 20%, transparent);
  --pr-focus-fill: color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 6%, transparent);
  /* A paper sheet needs a richer, inked glint rather than a pale neon wash.
     The base is supplied by the active Present/document theme in app.js. */
  --pr-connector-flow-core: color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 68%, #17213b);
  --pr-connector-flow-spark: color-mix(in srgb, var(--pr-motion-spark-base, var(--iris-bright, #8b80ff)) 70%, #fff);
  --pr-connector-flow-halo: color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 24%, transparent);
}
#stage[data-pr-sheet-tone="dark"] {
  --pr-focus-edge: color-mix(in srgb, var(--pr-focus, var(--iris-bright, #8b80ff)) 72%, #fff);
  --pr-focus-halo: color-mix(in srgb, var(--pr-focus, var(--iris-bright, #8b80ff)) 34%, transparent);
  --pr-focus-fill: color-mix(in srgb, var(--pr-focus, var(--iris-bright, #8b80ff)) 12%, transparent);
  /* On midnight sheets, lift the same theme hue toward white and give the
     small companion dash a brighter glint without turning the whole map neon. */
  --pr-connector-flow-core: color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 84%, #fff);
  --pr-connector-flow-spark: color-mix(in srgb, var(--pr-motion-spark-base, var(--iris-bright, #8b80ff)) 88%, #fff);
  --pr-connector-flow-halo: color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 42%, transparent);
}
body.pr-tool-spot #prSpotlight { border-radius: 50%; }
@media (forced-colors: active) {
  #prSpotlight { background: transparent; border: 2px solid CanvasText; box-shadow: none; }
}

/* ---- The step's OWN shape arriving ----
   The sequence tool tweens its draw-on, but every other tool used to hard-cut
   a new node into place: one frame it is absent, the next it simply exists.
   present-plus.js stamps .pr-shape-in on just the element(s) this step
   reveals, so the eye is led to what actually changed.
   transform-box: fill-box is required — without it an SVG transform-origin is
   the whole canvas, and the shape swings in from the corner. */
body.presenting #svgHost .pr-shape-in {
  animation: prShapeIn .45s cubic-bezier(.22, 1, .36, 1) both;
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
@keyframes prShapeIn {
  from { opacity: 0; transform: scale(.82); }
  70% { opacity: 1; transform: scale(1.03); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting #svgHost .pr-shape-in { animation: prShapeFade .25s ease both; }
  @keyframes prShapeFade { from { opacity: 0; } to { opacity: 1; } }
}

/* ---- Whole-frame transitions (Fade / Zoom / Morph — Flow is the
   per-element default). js/present-plus.js stamps .pr-svg-in on the fresh
   SVG only on whole-step renders, so the sequence tool's fractional tween
   never retriggers these. ---- */
.pr-trans-fade #svgHost .pr-svg-in { animation: prSvgFade .38s ease both; }
.pr-trans-zoom #svgHost .pr-svg-in { animation: prSvgZoom .5s var(--ease-out) both; transform-origin: 50% 50%; }
.pr-trans-morph #svgHost .pr-svg-in { animation: prSvgMorph .6s var(--ease-spring) both; transform-origin: 50% 50%; }
@keyframes prSvgFade { from { opacity: 0; } to { opacity: 1; } }
/* The outgoing sheet, frozen at its exact on-screen box and dissolving out
   over the incoming frame (renderPresentAt's cross-fade). pointer-events off
   so a viewer's tap mid-dissolve still reaches the gesture layer. */
#canvasWrap > .pr-frame-ghost { position: absolute; z-index: 3; pointer-events: none; animation: prGhostOut .42s ease forwards; }
@keyframes prGhostOut { from { opacity: 1; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { #canvasWrap > .pr-frame-ghost { display: none; } }
@keyframes prSvgZoom { from { opacity: 0; transform: scale(.965); } to { opacity: 1; transform: scale(1); } }
@keyframes prSvgMorph { 0% { opacity: 0; transform: scale(.94) translateY(8px); } 60% { opacity: 1; } 100% { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pr-trans-fade #svgHost .pr-svg-in, .pr-trans-zoom #svgHost .pr-svg-in, .pr-trans-morph #svgHost .pr-svg-in { animation: none; }
}

/* ---- Progress: slim gradient + chapter ticks + times. ---- */
#prProgress {
  position: absolute; left: 16px; right: 16px; top: 16px; z-index: 6;
  pointer-events: none;
  transition: left .3s ease, right .3s ease, opacity .35s ease;
}
body.pr-idle #prProgress { opacity: 0; }
#prProgressTrack {
  position: relative; height: 5px; border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  box-shadow: 0 1px 6px rgba(0, 0, 0, .3);
  cursor: pointer; pointer-events: auto;
}
#prProgressTrack:hover { height: 7px; }
#prProgressFill {
  position: absolute; top: 0; left: 0; bottom: 0; width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--iris-deep), var(--iris-bright));
  box-shadow: 0 0 10px color-mix(in srgb, var(--iris) 55%, transparent);
  transition: width .3s cubic-bezier(.4, 0, .2, 1);
}
#prProgressPuck {
  position: absolute; top: 50%; left: 0%;
  width: 11px; height: 11px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--iris) 55%, transparent), 0 2px 6px rgba(0, 0, 0, .4);
  transform: translate(-50%, -50%);
  transition: left .3s cubic-bezier(.4, 0, .2, 1);
}
#prChapters { position: absolute; inset: 0; pointer-events: none; }
.pr-chap {
  position: absolute; top: 50%; width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255,255,255,.6); border: 1.5px solid rgba(10,12,20,.5);
  transform: translate(-50%, -50%);
  pointer-events: auto; cursor: pointer;
}
/* Invisible 26px hit area — the dot itself must stay small on a 5px track. */
.pr-chap::before { content: ""; position: absolute; inset: -9px; border-radius: 50%; }
/* The bar lives at the top of the canvas, so its tooltip opens downward. */
.pr-chap::after { bottom: auto; top: calc(100% + 12px); }
.pr-chap:hover { background: #fff; transform: translate(-50%, -50%) scale(1.3); }
.pr-chap.done { background: var(--iris-bright); }
.pr-progress-times {
  display: flex; justify-content: space-between; margin-top: 7px;
  font-family: var(--mono); font-size: 10.5px; color: rgba(255,255,255,.85);
}
.pr-progress-times span {
  background: rgba(12,14,22,.6); border-radius: 6px; padding: 2px 7px;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.pr-progress-times span:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
  .pr-intro-card, .pr-end-card, .pr-pop, #prShortcuts, #prQa { animation: none; }
  .pr-intro-play:hover::after { animation: none; }
  #prSpotlight { transition: opacity .3s ease; }
  #presentBar, #prBrand, #prProgress { transition: opacity .2s ease; }
  body.pr-idle #presentBar { transform: translateX(-50%); }
  body.pr-idle .pr-pop { transform: none; }
}
/* Sizing: `max-content` keeps the row from shrink-to-fitting the space right
   of left:50% (an absolutely-positioned flex box would otherwise wrap early),
   while `max-width` + `wrap` let it fold into a second row whenever the CANVAS
   is narrow — which happens with side panels open, not just on small screens,
   so this must be container-relative rather than a viewport media query. */
#presentBar { width: max-content; max-width: calc(100% - 24px); flex-wrap: wrap; justify-content: center; row-gap: 6px; }
.prc { min-width: 0; }

/* ---- The bar's diet: transport + sound + exit, everything else earns its
   place per screen class. Buttons are HIDDEN, never removed — app.js binds
   every id at parse, and each hidden control keeps a twin: First/Last =
   Home/End + the progress strip; SpeedCycle = the pace slider in Settings;
   SmartToggle = the Settings checkbox (#prSmartStage). ---- */
#prFirst, #prLast, #prSpeedCycle, #prSmartToggle { display: none; }

@media (max-width: 1024px) {
  /* TABLETS keep the presenter's kit. An earlier cut hid laser/pen/spot
     here and that was wrong twice over: the bar has room at this width
     (measured, one row), and a tablet is exactly the device someone
     PRESENTS from — where L/D/S do not exist because there is no keyboard.
     What does stand down: Restart (the end slide's Replay and the seg
     bar's first cell both reach it) and Pin (an idle-mouse concept — on
     touch any tap wakes the dock) plus the running clock. */
  #prRestart, #prPin, #prTime { display: none; }
}
@media (max-width: 760px), (max-height: 560px) and (max-width: 1024px) {
  /* PHONES: ONE ROW, or it is not a pill — it is a second notes panel.
     MEASURED at 390px: 8 controls (374px of buttons) + gaps + two dividers
     needed 432px against 374px available, so the bar wrapped to two rows and
     ate 116px of an 844px screen. Seven controls, no internal rules:
     Prev · Play · Next · mute · settings · zen · exit, each a 44px target,
     riding above the home indicator. Voice keeps its Settings checkbox (and
     mute silences it in one tap); like/share live on the end slide, which is
     where a phone viewer reaches for them anyway. */
  #presentBar { gap: 4px; padding: 6px; bottom: max(10px, env(safe-area-inset-bottom)); }
  .prc + .prc::before { display: none; }
  /* Voice keeps its Settings checkbox, captions gained one (#prShowCaptions),
     like/share live on the end slide. The ink tools are the one honest loss:
     they are a desk-and-stylus feature, their keys need a keyboard, and a
     finger drawing on a 390px stage is not the gesture anyone wants — they
     return the moment the screen does. */
  #prNarrationToggle, #prAudienceCycle, #prFull, .prc-status,
  #prVoiceToggle, #prCaptionToggle, #prLikeBtn,
  #prToolLaser, #prToolPen, #prToolSpot, #prConnectorMotionToggle { display: none !important; }
  /* Phones are touch-first: taps navigate, drags pan and pinches zoom. Do not
     advertise a keyboard-only help surface there. */
  #prShortcutsBtn { display: none !important; }
  .pr-play { min-width: 58px; padding: 7px 12px; }
  /* .pr-pop is the full-width bottom sheet on phones (rule beside .pr-pop's
     own definition) — only the Q&A panel keeps a lifted bottom here. */
  #prQa { bottom: calc(66px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 400px) {
  #prExit { padding: 7px 8px; }
}

/* A true flush split-pane docked to the canvas edge — background/color/
   width/side are all set inline from JS (layoutPresentChrome) to match
   the diagram's own active theme and the 85/15 diagram/notes split, so it
   reads as part of the same sheet rather than a dark tooltip floating on
   top of the diagram (which could cover nodes underneath it). */
#prNarration {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  padding: 22px;
  opacity: 0;
  /* Opacity keeps the guide available for its short exit transition, but an
     invisible full-height panel must never sit over the newly expanded sheet
     and steal taps from the diagram. */
  pointer-events: none;
  transition: opacity .3s ease, left .3s ease, right .3s ease, width .3s ease;
}
#prNarration.pos-left { border-right: 1px solid rgba(0, 0, 0, .12); box-shadow: 6px 0 20px rgba(0, 0, 0, .08); }
#prNarration.pos-right { border-left: 1px solid rgba(0, 0, 0, .12); box-shadow: -6px 0 20px rgba(0, 0, 0, .08); }
#prNarration.show { opacity: 1; pointer-events: auto; }
#prNarrationHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  opacity: .6;
  margin-bottom: 14px;
  flex: none;
}
#prNarrationHeadBtns { display: flex; gap: 2px; }
#prNarrationFlip, #prNarrationEditBtn {
  font-size: 14px;
  padding: 3px 7px;
  border-radius: 6px;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 600;
  opacity: .8;
}
#prNarrationFlip:hover, #prNarrationEditBtn:hover { background: rgba(128, 128, 128, .18); opacity: 1; }
#prNarrationText {
  font-size: calc(19px * var(--pr-text-k, 1));
  line-height: 1.6;
  overflow-y: auto;
  opacity: 0;
  transition: opacity .25s ease;
}
#prNarrationText.show { opacity: 1; }
#prNarrationText.hidden-editing { display: none; }

/* ---- Notes panel: style presets, entrance, word-by-word highlight ----
   The preset is a data attribute set from Present settings (present-plus.js
   setNoteStyle). All four are tuned for the dark presentation chrome; Paper
   is deliberately light for editorial contrast. */
#prNarration[data-note-style] #prNarrationText {
  padding: 16px 18px;
  border-radius: 14px;
  flex: 0 1 auto;
}
#prNarration[data-note-style="sleek"] #prNarrationText{
  background: rgba(255, 255, 255, .05);
  border-left: 3px solid #7a8aff;
  border-radius: 6px 14px 14px 6px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .35);
}
#prNarration[data-note-style="glass"] #prNarrationText{
  background: rgba(255, 255, 255, .07);
  -webkit-backdrop-filter: blur(16px) saturate(1.35);
  backdrop-filter: blur(16px) saturate(1.35);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .12);
}
#prNarration[data-note-style="aurora"] #prNarrationText{
  border: 1px solid transparent;
  border-radius: 16px;
  color: #e9ecff;   /* dark card — the panel's inherited ink is dark on light sheets */
  background:
    linear-gradient(rgba(18, 20, 30, .88), rgba(18, 20, 30, .88)) padding-box,
    linear-gradient(135deg, #7a8aff, #22d3ee 45%, #a78bfa) border-box;
  box-shadow: 0 0 36px rgba(122, 138, 255, .22), 0 14px 40px rgba(0, 0, 0, .45);
}
#prNarration[data-note-style="paper"] #prNarrationText{
  background: linear-gradient(180deg, #faf4e7, #f1e8d4);
  color: #33302c;
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  font-size: 20px;
  line-height: 1.65;
  border-radius: 12px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, .4), inset 0 0 0 1px rgba(120, 100, 60, .18);
}

/* ---- Audience presets: one premium template per segment ---- */

/* Corporate — boardroom-crisp white card, navy meter, tight ink. */
/* ---- Audience presets: one premium template per segment ---- */

/* Corporate — boardroom-crisp white card, navy meter, tight ink. */
#prNarration[data-note-style="corporate"] #prNarrationText{
  background: #ffffff;
  color: #1f2937;
  border: 1px solid #dde2ec;
  border-top: 4px solid transparent;
  border-radius: 10px;
  background-clip: padding-box;
  position: relative;
  box-shadow: 0 14px 34px rgba(15, 23, 42, .18);
  font-size: 17.5px;
  line-height: 1.55;
  letter-spacing: -.005em;
}
#prNarration[data-note-style="corporate"] #prNarrationText::after {
  content: ""; position: absolute; top: -4px; left: -1px; right: -1px; height: 4px;
  border-radius: 10px 10px 0 0;
  background: linear-gradient(90deg, #1e3a8a, #3b82f6 60%, #93c5fd);
}
#prNarration[data-note-style="corporate"] #prNarrationText::before {
  content: "STEP " attr(data-step);
  /* BLOCK, not inline-block: as an inline box the note's first words flowed
     up beside the chip and sat against it, and the bottom margin separated
     nothing. width:max-content keeps the pill hugging its own text instead of
     stretching the full column. */
  display: block; width: max-content; max-width: 100%; margin: 0 0 10px;
  font-size: 10px; font-weight: 800; letter-spacing: .14em;
  color: #1e3a8a; background: #eef2ff; border: 1px solid #c7d2fe;
  padding: 3px 8px; border-radius: 5px;
}
#prNarration[data-note-style="corporate"] #prNarrationText.karaoke .kw.now { color: #2563eb; }

/* Kids — sunny, bubbly, friendly round type, a touch of tilt. */
/* Kids — sunny, bubbly, friendly round type, a touch of tilt. */
#prNarration[data-note-style="kids"] #prNarrationText{
  background: linear-gradient(160deg, #fff6d8, #ffe7ee 85%);
  color: #4a3510;
  border: 3px solid #ffb703;
  border-radius: 22px;
  transform: rotate(-.6deg);
  box-shadow: 0 12px 30px rgba(180, 100, 0, .22);
  font-family: 'Chalkboard SE', 'Comic Sans MS', 'Segoe Print', cursive;
  font-size: 20px;
  line-height: 1.55;
}
#prNarration[data-note-style="kids"] #prNarrationText::before {
  content: "✨ Step " attr(data-step);
  display: block; width: max-content; max-width: 100%; margin: 0 0 10px;
  font-size: 12px; font-weight: 700;
  color: #b45309; background: #ffffffaa;
  padding: 3px 10px; border-radius: 999px; border: 2px dashed #fcbf49;
}
#prNarration[data-note-style="kids"] #prNarrationText.karaoke .kw { opacity: .70; }
#prNarration[data-note-style="kids"] #prNarrationText.karaoke .kw.now { color: #e11d48; }

/* Classroom — chalk on a green board in a wooden frame. */
/* Classroom — chalk on a green board in a wooden frame. */
#prNarration[data-note-style="classroom"] #prNarrationText{
  background:
    radial-gradient(120% 90% at 30% 20%, rgba(255, 255, 255, .06), transparent 60%),
    #24463a;
  color: #f2fbf4;
  border: 7px solid #8b5e34;
  border-radius: 8px;
  box-shadow: inset 0 0 24px rgba(0, 0, 0, .35), 0 14px 34px rgba(0, 0, 0, .4);
  font-family: 'Chalkboard SE', 'Bradley Hand', 'Segoe Print', cursive;
  font-size: 19px;
  line-height: 1.6;
}
#prNarration[data-note-style="classroom"] #prNarrationText::before {
  content: "Step " attr(data-step);
  display: block; width: max-content; max-width: 100%; margin: 0 0 10px; padding-bottom: 2px;
  font-size: 13px; color: #ffe066;
  border-bottom: 2px dashed rgba(255, 224, 102, .55);
}
#prNarration[data-note-style="classroom"] #prNarrationText.karaoke .kw { opacity: .70; }
#prNarration[data-note-style="classroom"] #prNarrationText.karaoke .kw.now { color: #ffe066; }

/* Tech — dark terminal, mono type, cyan cursor line. */
/* Tech — dark terminal, mono type, cyan cursor line. */
#prNarration[data-note-style="tech"] #prNarrationText{
  background: #0b1020;
  color: #d2e3ff;
  border: 1px solid #1e293b;
  border-left: 3px solid #22d3ee;
  border-radius: 8px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .5);
  font-family: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15.5px;
  line-height: 1.65;
}
#prNarration[data-note-style="tech"] #prNarrationText::before {
  content: "▸ step_" attr(data-step);
  display: block; margin: 0 0 8px;
  font-size: 11px; letter-spacing: .06em; color: #22d3ee; opacity: .9;
}
#prNarration[data-note-style="tech"] #prNarrationText.karaoke .kw { opacity: .70; }
#prNarration[data-note-style="tech"] #prNarrationText.karaoke .kw.now { color: #22d3ee; }

/* The style row wraps to two lines now. */
.pr-seg-wrap { flex-wrap: wrap; }

/* Note image — rides above the styled text card, follows the same sticky
   key as the text, and joins the entrance animation. */
#prNarrationImg {
  /* contain, never cover: every home this base rule reaches shows the WHOLE
     picture — the presenting redesign overrides geometry but must never have
     to undo a crop. */
  width: 100%; height: auto; max-height: 34%; object-fit: contain; flex: none;
  border-radius: 12px; margin-bottom: 10px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .3);
}
#prNarration[data-note-style="kids"] #prNarrationImg { border: 3px solid #ffb703; border-radius: 18px; transform: rotate(.5deg); }
#prNarration[data-note-style="classroom"] #prNarrationImg { border: 5px solid #8b5e34; border-radius: 6px; }
#prNarration[data-note-style="corporate"] #prNarrationImg { border: 1px solid #dde2ec; border-radius: 8px; }
#prNarration[data-note-style="tech"] #prNarrationImg { border: 1px solid #1e293b; border-radius: 6px; }

/* Notes editor: per-step image row */
.pnl-img-row { display: flex; align-items: center; gap: 8px; margin: 4px 0 2px; flex-wrap: wrap; }
/* The review thumbnail is FITTED, never cropped (the fitImageBox doctrine):
   a fixed height with auto width takes the picture's own proportions, so a
   wide diagram photo and a square icon both show whole. The old 54x38 cover
   box sliced whatever did not match its shape — "the images are truncated"
   (operator, Aug 24). Click still opens the full lightbox. */
.pnl-img-thumb { height: 64px; width: auto; max-width: 170px; object-fit: contain; border-radius: 6px; border: 1px solid var(--border-soft); background: var(--chrome-2, rgba(128, 128, 128, .06)); }
.pnl-img-btn { font-size: 11px; font-weight: 600; color: var(--muted); padding: 4px 8px; border: 1px dashed var(--border-soft); border-radius: 7px; }
.pnl-img-btn:hover { color: var(--text); background: var(--chrome-2, rgba(128, 128, 128, .08)); }
.pnl-title-media {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 11px;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--panel-2);
}
.pnl-title-media-head { margin: 0; color: var(--text); font-size: 13px; font-weight: 750; }
.pnl-title-media-help { color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.pnl-title-media-row { margin-top: 4px; }
.pnl-title-img-thumb { cursor: zoom-in; }
.pnl-title-layout { max-width: 230px; }
.pnl-img-place { color: var(--text); border-style: solid; }
/* Image guidance uses the SAME limits as pickNoteImage(). It is deliberately
   visible before a file is chosen; making users discover the right aspect
   only after upload is too late. The compact current-size line confirms what
   Diagramium actually stored after its on-device optimization. */
.pnl-media-spec {
  width: 100%;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 2px 8px;
  align-items: center;
  padding: 7px 8px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--panel);
}
.pnl-img-row > .pnl-media-spec { flex: 1 0 100%; }
.pnl-media-spec-kicker {
  grid-row: 1 / 4;
  align-self: start;
  padding: 3px 5px;
  border-radius: 5px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, var(--panel));
  font-size: 8.5px;
  font-weight: 850;
  line-height: 1.15;
  letter-spacing: .08em;
  white-space: nowrap;
}
.pnl-media-spec-main { color: var(--text); font-size: 11.5px; font-weight: 720; line-height: 1.3; }
.pnl-media-spec-sub { color: var(--muted); font-size: 10.5px; line-height: 1.35; }
.pnl-media-current { color: var(--accent); font-size: 10.5px; font-weight: 650; line-height: 1.3; }
.pnl-media-current[hidden] { display: none; }
.pnl-img-stored-inline {
  flex: 1 0 100%;
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.3;
}

/* Entrance: a new note glides in from the panel's own edge and settles. */
#prNarration.pr-note-in #prNarrationText,
#prNarration.pr-note-in #prNarrationImg { animation: prNoteInR .55s cubic-bezier(.22, 1, .36, 1) both; }
#prNarration.pos-left.pr-note-in #prNarrationText,
#prNarration.pos-left.pr-note-in #prNarrationImg { animation-name: prNoteInL; }
@keyframes prNoteInR {
  from { opacity: 0; transform: translateX(26px); }
  to { opacity: 1; transform: none; }
}
@keyframes prNoteInL {
  from { opacity: 0; transform: translateX(-26px); }
  to { opacity: 1; transform: none; }
}
/* The step's picture gets its OWN arrival rather than sliding with the text.
   It is the thing the eye goes to, so it lifts and focuses into place a beat
   after the words start — which reads as deliberate instead of as one block
   of panel sliding sideways. */
#prNarration.pr-note-in #prNarrationImg,
#prNarration.pos-left.pr-note-in #prNarrationImg {
  animation: prNoteImgIn .62s cubic-bezier(.22, 1, .36, 1) .07s both;
}
@keyframes prNoteImgIn {
  from { opacity: 0; transform: scale(.93) translateY(12px); filter: blur(7px); }
  60%  { opacity: 1; filter: blur(0); }
  to   { opacity: 1; transform: none; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  #prNarration.pr-note-in #prNarrationText,
  #prNarration.pr-note-in #prNarrationImg,
  #prNarration.pos-left.pr-note-in #prNarrationText,
  #prNarration.pos-left.pr-note-in #prNarrationImg { animation: prNoteFade .25s ease both; }
  @keyframes prNoteFade { from { opacity: 0; } to { opacity: 1; } }
}

/* While the voice reads the note, its words fill in like a progress bar —
   same .kw/.said/.now contract as the subtitle strip (present-plus.js).
   The current word pools a wash of its own accent behind itself: the pill
   is painted in currentColor, so every note style's .now hue (corporate
   blue, kids rose, tech cyan…) recolours the liquid for free. */
#prNarrationText.karaoke .kw {
  opacity: .70;
  transition: opacity .16s ease, color .16s ease;
  border-radius: 4px;
}
#prNarrationText.karaoke .kw.said { opacity: 1; }
#prNarrationText.karaoke .kw.now {
  opacity: 1; color: #9fb0ff;
  background-image: linear-gradient(90deg,
    color-mix(in srgb, currentColor 26%, transparent),
    color-mix(in srgb, currentColor 12%, transparent));
  background-repeat: no-repeat;
  background-size: 0% 100%;
  animation: kwLiquid .34s ease-out forwards;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 14%, transparent);
}
#prNarration[data-note-style="paper"] #prNarrationText.karaoke .kw.now { color: #6d28d9; }
#prNarrationEdit {
  flex: 1;
  width: 100%;
  resize: none;
  font: inherit;
  font-size: 17px;
  line-height: 1.55;
  color: inherit;
  background: rgba(128, 128, 128, .1);
  border: 1px solid rgba(128, 128, 128, .3);
  border-radius: 8px;
  padding: 10px;
}
#prNarrationEditBtns { display: flex; gap: 8px; margin-top: 10px; flex: none; }
#prNarrationList { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
.pnl-item { display: flex; flex-direction: column; gap: 6px; }
.pnl-empty { font-size: 13px; opacity: .6; line-height: 1.5; padding: 8px 2px; }
.pnl-label { font-size: 12px; font-weight: 700; opacity: .55; }
.pnl-text {
  width: 100%;
  min-height: 64px;
  resize: vertical;
  font: inherit;
  font-size: 15px;
  line-height: 1.5;
  color: inherit;
  background: rgba(128, 128, 128, .1);
  border: 1px solid rgba(128, 128, 128, .3);
  border-radius: 8px;
  padding: 8px 10px;
}
.pnl-save {
  align-self: flex-start;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 6px;
  font-weight: 600;
  background: var(--accent);
  color: var(--on-accent);
}
.pnl-save.saved { background: #10b981; }
/* Editor-only: the notes pane has no room on a phone. Present is EXCLUDED —
   the show has its own notes layouts (side column / bottom band / collapsed
   rail) and a blanket display:none here made reserveNotesColumn measure a
   zero rect and pay a stage-sized padding for a panel that wasn't there. */
@media (max-width: 760px) { body:not(.presenting) #prNarration { display: none; } }

body.presenting #hintBar { display: none; }
/* Presenting is FULL-BLEED: the editor chrome leaves entirely, same as watch
   mode below ("no other layout change needed" — #canvasWrap is flex:1 in
   #main's row). The old treatment kept palette/side at 0.45 opacity as a
   "you're still in the editor" hint, which cost ~500px of stage on a laptop
   and left a phone a 36px-wide show. Exit restores everything by dropping
   the class. */
body.presenting #topbar, body.presenting #palette, body.presenting #side { display: none; }
body.presenting #svgHost [data-hit] { cursor: default; }
/* The gesture layer owns the diagram surface: without touch-action the
   browser claims a horizontal swipe for its own scrolling/navigation, and a
   400ms hold summons text selection and the iOS callout instead of pausing.
   Scoped to #zoomLayer ON PURPOSE — the settings sheet (#prSettings) and
   the notes panel scroll by touch and live outside it. */
/* BOTH declarations belong to the diagram surface, not to the wrap. Every
   Present overlay — the Q&A transcript, the end slide's takeaways, the notes
   panel, the shortcut sheet — is a DESCENDANT of #canvasWrap, and
   `user-select: auto` on a child computes to `none` under a `none` parent, so
   scoping this to the wrap quietly made every word in the show unselectable.
   #zoomLayer holds only the sheet, which is exactly what the hold gesture
   touches and the only thing that must not select or raise a callout. */
body.presenting #zoomLayer {
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
}

/* clean stage while a narrated video is being recorded */
body.recording #topbar, body.recording #palette, body.recording #side,
body.recording #hintBar, body.recording #presentBar, body.recording #toasts,
body.recording #prProgress, body.recording #prNarration { display: none !important; }
body.recording #canvasWrap { background-image: none; }

/* Watch mode (Present triggered from the Explore gallery) — a YouTube-style
   clean player: hide all editor chrome but, unlike .recording above, KEEP
   #presentBar visible as the play/pause/scrubber bar. #canvasWrap is
   flex:1 inside #main's flex row, so with #palette/#side gone it fills
   the full viewport width with no other layout change needed. */
body.watching #topbar, body.watching #palette, body.watching #side { display: none; }

#canvasWrap:fullscreen { background-color: var(--canvas-bg); }

#hintBar {
  position: absolute;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  background: rgba(20, 22, 31, 0.82);
  color: #c6cadb;
  font-size: 11px;
  padding: 6px 14px;
  border-radius: 99px;
  pointer-events: none;
  white-space: nowrap;
  backdrop-filter: blur(4px);
  z-index: 5;
}

/* ---- Side panel (right) ---- */
#side {
  position: relative;
  width: var(--side-user-w, 292px);
  transition: width .18s ease;
  flex: none;
  background: var(--chrome);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
#side.code-mode { width: max(430px, var(--side-user-w, 292px)); }
/* THE PANEL SLIDES (operator, Sep 5). Its left edge is a drag handle so the
   Theme tab's cards get room; app.js sets --side-user-w / --insp-w only, so
   the code-mode floor and the collapsed state keep their own rules. The
   accent line is the focus ring's replacement (a separator has no box). */
.side-resize { position: absolute; left: 0; top: 0; bottom: 0; width: 9px; cursor: ew-resize; z-index: 6; touch-action: none; }
.side-resize::after { content: ''; position: absolute; left: 3px; top: 10px; bottom: 10px; width: 2px; border-radius: 2px; background: transparent; transition: background .15s; }
.side-resize:hover::after, .side-resize:focus-visible::after, body.side-resizing .side-resize::after { background: var(--accent); }
.side-resize:focus-visible { outline: none; }
#side.collapsed .side-resize { display: none; }
body.side-resizing { cursor: ew-resize; user-select: none; }
body.side-resizing #side { transition: none; }
#tabs {
  display: flex;
  gap: 4px;
  padding: 10px 12px 0;
  border-bottom: 1px solid var(--border);
}
.tab {
  padding: 7px 12px 9px;
  color: var(--muted);
  font-weight: 600;
  font-size: 12.5px;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .12s;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); border-bottom-color: var(--accent); }
.tabpane { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 14px; min-height: 0; }

/* inspector fields */
.insp-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 13px;
}
.insp-head .chip {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent-ink);
  background: var(--accent-soft);
  padding: 3px 7px;
  border-radius: 5px;
}
.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.field input[type="text"], .field input[type="number"], .field input[type="date"],
.field input:not([type]), .field select, .field textarea {
  background: var(--chrome-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 9px;
  color: var(--text);
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); outline: none; }
.field textarea.insp-multiline { min-height: 54px; line-height: 1.35; resize: vertical; }
.field select { appearance: none; -webkit-appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: calc(100% - 16px) 55%, calc(100% - 11px) 55%; background-size: 5px 5px; background-repeat: no-repeat; padding-right: 26px; }
.field select[multiple] { appearance: auto; -webkit-appearance: auto; background-image: none; padding-right: 9px; }

.inline-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.inline-row > * { flex: none; }
.muted { color: var(--muted); font-size: 11.5px; line-height: 1.5; }

.seg { display: flex; background: var(--chrome-2); border: 1px solid var(--border); border-radius: 8px; padding: 2px; gap: 2px; }
.seg-btn { flex: 1; padding: 6px 4px; border-radius: 6px; color: var(--muted); font-size: 12px; text-align: center; transition: background .12s, color .12s; }
.seg-btn:hover { color: var(--text); }
.seg-btn.active { background: var(--chrome-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }

/* Account-gated formats seen by a guest (js/app.js `syncExpFormatLocks`).
   Dimmed and padlocked, never `disabled` — the click is what reveals
   #expGateHint and the way in, and Present's ⏺ Record buttons reach this
   modal by clicking the seg, so a dead button would break Record outright.
   --faint + 🔒 is the lock convention this app already uses for locked
   layers (.ck-layer.locked); both tokens are real and theme-aware, which
   matters because an invented one fails SILENTLY to its fallback and would
   look right in dark and wrong in light. */
.seg-btn.locked { color: var(--faint); }
.seg-btn.locked:hover { color: var(--muted); }
.seg-btn.locked.active { color: var(--muted); }
.seg-btn.locked::before { content: "🔒"; font-size: 8.5px; margin-right: 3px; opacity: .8; vertical-align: 1px; }

.swatches { display: flex; flex-wrap: wrap; gap: 6px; }
.swatch {
  width: 22px; height: 22px;
  border-radius: 6px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform .08s;
  padding: 0;
}
.swatch:hover { transform: scale(1.12); }
.swatch.active { border-color: #fff; box-shadow: 0 0 0 2px var(--accent); }
.swatch.none {
  background: var(--chrome-2);
  border: 1px solid var(--border);
  position: relative;
  color: var(--muted);
  font-size: 13px;
  line-height: 1;
}
.swatch-custom { width: 22px; height: 22px; padding: 0; border: 1px solid var(--border); border-radius: 6px; background: none; cursor: pointer; }
.swatch-custom::-webkit-color-swatch-wrapper { padding: 2px; }
.swatch-custom::-webkit-color-swatch { border: none; border-radius: 4px; }

.emoji-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.emoji-btn { font-size: 16px; padding: 4px 0; border-radius: 6px; text-align: center; transition: background .1s; line-height: 1.3; }
.emoji-btn:hover { background: var(--chrome-3); }
.emoji-btn.active { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }

.theme-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.theme-card {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px;
  background: var(--chrome-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  font-size: 12px;
  color: var(--muted);
  transition: border-color .12s, color .12s;
}
.theme-card:hover { color: var(--text); border-color: var(--accent); }
.theme-card.active { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.theme-dot { width: 14px; height: 14px; border-radius: 4px; flex: none; border: 1px solid rgba(0,0,0,.15); }

/* ---- Quick decoration presets (js/decor-presets.js). Each card draws its
   own preset at thumbnail scale, so a preview can never drift from what
   clicking it actually does. ---- */
.dp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 7px; margin-bottom: 6px; }
.dp-card {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 6px 5px 5px;
  background: var(--chrome-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  color: var(--muted);
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
}
.dp-card:hover { color: var(--text); border-color: var(--accent); }
.dp-card.active { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.dp-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dp-prev { width: 100%; height: auto; display: block; border-radius: 4px; }
.dp-name { font-size: 11px; font-weight: 600; letter-spacing: -0.01em; }

.check { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 12.5px; color: var(--text); text-transform: none; letter-spacing: 0; font-weight: 500; }
.check input { accent-color: var(--accent); width: 15px; height: 15px; }

.row-btns { display: flex; gap: 7px; }
.row-btns .btn-ghost { flex: 1; text-align: center; padding: 6px 4px; font-size: 12px; }
.insp-sep { border-top: 1px solid var(--border-soft); margin: 2px 0; }

/* ---- Spotlight Card inspector (CommonSettings.spotCardFieldsHTML) ----
   The picture list: thumbnail + size slider (% of the card's width) + a
   remove button per row, and one Add button below. */
.spotcard-imgs { display: flex; flex-direction: column; gap: 6px; }
.spotcard-img-row { display: flex; align-items: center; gap: 7px; }
.spotcard-img-row img {
  width: 36px; height: 27px; object-fit: cover; flex: 0 0 auto;
  border-radius: 5px; border: 1px solid var(--border-soft); background: var(--panel-2);
}
.spotcard-img-row input[type="range"] { flex: 1 1 auto; min-width: 0; }
.spotcard-img-x {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0; cursor: pointer;
  border: 1px solid var(--border-soft); border-radius: 6px;
  background: var(--panel-2); color: var(--muted); font-size: 11px; line-height: 1;
}
.spotcard-img-x:hover { color: var(--text); border-color: var(--border); }
.spotcard-add {
  margin-top: 6px; padding: 5px 10px; cursor: pointer; font-size: 11.5px;
  border: 1px dashed var(--border); border-radius: 8px;
  background: transparent; color: var(--muted);
}
.spotcard-add:hover { color: var(--text); border-color: var(--accent, var(--border)); }

/* The block-list editor: one bordered card per block with a kind chip,
   move/remove tools, its text, and two compact style rows. */
.spotcard-blocks { display: flex; flex-direction: column; gap: 8px; }
.spotcard-blk {
  border: 1px solid var(--border-soft); border-radius: 9px;
  padding: 7px 8px; background: var(--panel-2);
  display: flex; flex-direction: column; gap: 6px;
}
.spotcard-blk.sel { border-color: var(--accent-ring, var(--accent, #6d7cff)); background: var(--accent-soft, var(--panel-2)); }
.spotcard-blk-head { display: flex; align-items: center; justify-content: space-between; }
.spotcard-blk-kind { font-size: 10.5px; font-weight: 700; letter-spacing: .03em; color: var(--muted); }
.spotcard-blk-tools { display: flex; gap: 3px; }
.spotcard-blk-tools button {
  width: 20px; height: 20px; padding: 0; cursor: pointer; font-size: 10.5px; line-height: 1;
  border: 1px solid var(--border-soft); border-radius: 5px;
  background: var(--panel); color: var(--muted);
}
.spotcard-blk-tools button:hover:not(:disabled) { color: var(--text); border-color: var(--border); }
.spotcard-blk-tools button:disabled { opacity: .35; cursor: default; }
.spotcard-style { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.spotcard-style select { flex: 1 1 auto; min-width: 0; font-size: 11px; padding: 3px 4px; }
.spotcard-style input[type="number"] { width: 52px; font-size: 11px; padding: 3px 4px; }
.spotcard-style input[type="color"] {
  width: 26px; height: 22px; padding: 0; border: 1px solid var(--border-soft);
  border-radius: 5px; background: transparent; cursor: pointer;
}
.spotcard-tg {
  min-width: 22px; height: 22px; padding: 0 4px; cursor: pointer; font-size: 11px; line-height: 1;
  border: 1px solid var(--border-soft); border-radius: 5px;
  background: var(--panel); color: var(--muted);
}
.spotcard-tg:hover { color: var(--text); border-color: var(--border); }
.spotcard-tg.on { background: var(--accent-soft, var(--panel)); color: var(--accent-ink, var(--text)); border-color: var(--accent-ring, var(--border)); }
.spotcard-addrow { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 6px; }
.spotcard-addrow .spotcard-add { margin-top: 0; flex: 1 1 auto; }

/* code pane */
#codePane { padding: 12px; gap: 10px; }
.code-tools { display: flex; align-items: center; gap: 7px; }
.btn-ghost.sm { padding: 4px 10px; font-size: 12px; }
#codeWrap {
  flex: 1;
  min-height: 220px;
  display: flex;
  background: var(--chrome-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
#codeWrap:focus-within { border-color: var(--accent); }
#codeGutter {
  flex: none;
  width: 34px;
  padding: 10px 6px 10px 0;
  text-align: right;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.65;
  color: var(--muted);
  opacity: .55;
  background: var(--chrome);
  border-right: 1px solid var(--border-soft);
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  white-space: pre;
}
#codeText {
  flex: 1;
  min-width: 0;
  resize: none;
  background: transparent;
  border: none;
  padding: 10px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.65;
  color: var(--text);
  white-space: pre;
  overflow: auto;
}
#codeText:focus { outline: none; }
#codeStatus { font-size: 11.5px; }
#codeStatus.ok { color: #57c98b; }
#codeStatus.err { color: var(--danger); }
#codeErrors { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--danger); }
#cheat { border-top: 1px solid var(--border-soft); padding-top: 8px; }
#cheat summary { cursor: pointer; color: var(--muted); font-size: 12px; font-weight: 600; }
#cheat pre {
  margin-top: 8px;
  background: var(--chrome-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.7;
  color: var(--muted);
  overflow-x: auto;
}

/* ============ Modals ============ */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 12, 20, 0.62);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  backdrop-filter: blur(3px);
}
.modal {
  width: 400px;
  max-width: calc(100vw - 40px);
  max-height: calc(100vh - 60px);
  overflow-y: auto;
  background: var(--chrome-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.modal.wide { width: 620px; }
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px 0;
}
.modal-head h3 { font-size: 15px; }
.modal-x { font-size: 20px; color: var(--muted); line-height: 1; padding: 2px 6px; border-radius: 6px; }
.modal-x:hover { color: var(--text); background: var(--chrome-3); }
.modal-body { padding: 14px 18px 18px; display: flex; flex-direction: column; gap: 14px; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; }
.modal-sep { border-top: 1px solid var(--border-soft); }

/* ---- Export hub (#modalExportHub) ----
   The one dialog for GIF / animated SVG / movie. Same token discipline as
   every modal here: only names this file defines. */
.modal.xh { width: 520px; }
.xh-formats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.xh-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 10px 11px; text-align: left; cursor: pointer;
  background: var(--chrome-3); border: 1px solid var(--border-soft);
  border-radius: 10px; color: var(--text); font: inherit;
}
.xh-card b { font-size: 13px; }
.xh-card .xh-ico { font-size: 17px; line-height: 1; }
.xh-card .xh-sub { font-size: 10.5px; line-height: 1.35; color: var(--muted); }
.xh-card:hover { border-color: var(--border); }
.xh-card.active {
  border-color: #6d7cff;
  box-shadow: 0 0 0 1px #6d7cff inset;
  background: rgba(109, 124, 255, 0.08);
}
.xh-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.xh-foot .muted { font-size: 11px; line-height: 1.4; }
.xh-progress { display: flex; flex-direction: column; gap: 6px; }
.xh-bar { height: 6px; border-radius: 3px; background: var(--chrome-3); overflow: hidden; }
.xh-bar i { display: block; height: 100%; width: 0; border-radius: 3px; background: #6d7cff; transition: width 0.2s ease; }
.xh #xhVoiceWrap { display: flex; flex-direction: column; gap: 6px; }
.xh .xh-studio {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  color: var(--text); background: rgba(16, 185, 129, 0.1);
  border: 1px solid rgba(16, 185, 129, 0.4); border-radius: 8px; padding: 6px 10px;
}
/* ---- Design-panel group headings (CommonSettings.grp) ----
   A small uppercase label with a rule that fades out beside it — the same
   quiet divider language as the diagram's own title underline, so the
   inspector reads as sections rather than one long column of fields. */
.cs-grp { display: flex; align-items: center; gap: 8px; margin: 18px 0 4px; }
/* The accent tick is what separates a SECTION heading from the field labels
   under it — those are muted uppercase too, so without it the two read as
   the same level and the panel is still one long column. */
.cs-grp::before {
  content: ""; flex: none; width: 3px; height: 11px;
  border-radius: 2px; background: #6d7cff;
}
.cs-grp span {
  font-size: 10.5px; font-weight: 750; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text); white-space: nowrap;
}
.cs-grp::after {
  content: ""; flex: 1; height: 1px; border-radius: 1px;
  background: linear-gradient(to right, var(--border), transparent);
}
.cs-grp:first-child { margin-top: 4px; }

.xh-adv { text-align: center; margin-top: -6px; }
.xh-adv .btn-ghost { font-size: 11.5px; color: var(--muted); }
/* The Fine-tune fold: a first export is three cards + one button; every
   tuning row lives behind this summary, remembered per browser. */
/* Include group (operator, Sep 6 2026): three labelled toggle lines. */
.xh-inc-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 4px 0; }
.xh-inc-line[hidden] { display: none; }
/* Still-image Include row (Diagram · Legend · Notes): a part the document has
   nothing for is disabled — shown, dimmed, and explained by its title. */
/* Branding sits directly above Include on the image side and reads as the
   same kind of row (operator, Sep 20 2026). Same key column, same seg, so the
   two lines stack as one block above PNG / SVG / PDF / Copy. */
.xh-still-brand { margin: 2px 0 2px; }
.xh-still-brand .seg-btn { white-space: nowrap; }
.xh-still-parts { margin: 2px 0 8px; }
.xh-still-parts .seg-btn { white-space: nowrap; }
.xh-still-parts .seg-btn:disabled { opacity: .45; cursor: not-allowed; }
.xh-inc-k { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); min-width: 92px; }
.xh-link { font: inherit; font-size: 11px; font-weight: 650; color: var(--text); background: transparent; border: 0; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.xh-link[hidden] { display: none; }
.exp-card-content { margin-top: 6px; }
.exp-card-content > label { display: block; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.exp-card-checks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.exp-range input, .xh-range input { width: 58px; font: inherit; font-size: 12.5px; padding: 4px 6px; border-radius: 7px; border: 1px solid var(--border); background: var(--chrome-2); color: var(--text); }
.xh-range { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text); }
.xh-more { border: 1px solid var(--border-soft); border-radius: 10px; padding: 2px 10px; margin: 2px 0 4px; }
.xh-more > summary {
  cursor: pointer; user-select: none; list-style: none;
  font-size: 12px; font-weight: 600; padding: 7px 2px; color: var(--text);
}
.xh-more > summary::-webkit-details-marker { display: none; }
.xh-more > summary::after { content: "▸"; float: right; font-size: 10px; opacity: .55; transition: transform .15s ease; }
.xh-more[open] > summary::after { transform: rotate(90deg); }
.xh-more[open] { padding-bottom: 8px; }
.xh-more[open] > summary { border-bottom: 1px dashed var(--border-soft); margin-bottom: 8px; }
/* Image or Animation — the export dialog's first choice (export-hub.js
   applyKind). Each side's elements carry data-xh-kind; the modal's data-kind
   hides the other side outright, independent of data-xh-for's hidden. */
.xh-kind { display: grid; grid-template-columns: 1fr 1fr; margin: 0 0 2px; }
.xh-kind .seg-btn { justify-content: center; font-weight: 650; }
.modal.xh[data-kind="image"] [data-xh-kind="animation"],
.modal.xh[data-kind="animation"] [data-xh-kind="image"] { display: none !important; }

/* ---- Embed dialog (#modalEmbed) ----
   Tokens copied from the neighbouring modal styles above rather than invented:
   an unknown custom property in var(--x, fallback) fails SILENTLY to its
   fallback, so a panel styled with a made-up name looks right in dark and is
   still that hard-coded colour in light. --chrome-2 / --border-soft / --text /
   --muted are the ones this file actually defines. */
.emb-opts { display: flex; flex-wrap: wrap; gap: 10px 18px; }
.emb-opt { display: flex; align-items: center; gap: 7px; font-size: 13.5px; color: var(--text); cursor: pointer; }
.emb-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px 12px; }
.emb-field { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--muted); }
.emb-field select,
.emb-field input {
  font: inherit; font-size: 13.5px; color: var(--text);
  padding: 7px 9px; border-radius: 8px;
  background: var(--chrome-2, rgba(128, 128, 128, .08));
  border: 1px solid var(--border-soft);
}
.emb-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; line-height: 1.5; color: var(--text);
  padding: 11px 12px; border-radius: 10px; resize: vertical;
  background: var(--chrome-2, rgba(128, 128, 128, .08));
  border: 1px solid var(--border-soft);
  white-space: pre; overflow-x: auto;
}
.emb-note { font-size: 12.5px; line-height: 1.5; }

/* ---- Icon library modal ---- */
.il-modal { width: min(860px, 94vw); max-height: min(84vh, 780px); display: flex; flex-direction: column; }
.il-toolbar { display: flex; gap: 10px; align-items: center; padding: 12px 18px 4px; }
.il-toolbar input[type="search"] {
  flex: 1; min-width: 0; font-size: 14px; padding: 10px 14px; border-radius: 10px;
  background: var(--chrome-2, rgba(128, 128, 128, .08)); border: 1px solid var(--border-soft);
}
.il-tools { display: flex; gap: 6px; }
.il-tool { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border-soft); font-size: 13px; color: var(--text); }
.il-tool:hover { background: var(--chrome-3, rgba(128, 128, 128, .14)); }
.il-tool.on { background: color-mix(in srgb, #6d7cff 18%, transparent); border-color: #6d7cff; }
.il-upload { font-weight: 600; }
.il-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 18px; align-items: center; }
.il-chip {
  font-size: 11.5px; font-weight: 600; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--border-soft); color: var(--text); white-space: nowrap;
}
.il-chip em { font-style: normal; opacity: .55; margin-left: 3px; }
.il-chip:hover { background: var(--chrome-3, rgba(128, 128, 128, .14)); }
.il-chip.on { background: color-mix(in srgb, #6d7cff 22%, transparent); border-color: #6d7cff; }
.il-chip-sep { width: 1px; height: 16px; background: var(--border-soft); margin: 0 3px; }
.il-grid { flex: 1; overflow-y: auto; padding: 6px 18px 14px; }
.il-view-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.il-view-list { display: flex; flex-direction: column; gap: 4px; }
.il-item {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 12px 6px 9px; border-radius: 12px; border: 1px solid transparent; color: var(--text);
  cursor: pointer; text-align: center;
}
.il-item:hover { background: var(--chrome-2, rgba(128, 128, 128, .08)); border-color: var(--border-soft); }
.il-item:focus-visible { outline: 2px solid #6d7cff; outline-offset: 1px; }
.il-view-list .il-item { flex-direction: row; justify-content: flex-start; gap: 12px; padding: 7px 10px; text-align: left; }
.il-glyph { width: 34px; height: 34px; flex: none; display: flex; align-items: center; justify-content: center; }
.il-glyph svg { width: 100%; height: 100%; }
.il-view-list .il-glyph { width: 24px; height: 24px; }
.il-name { font-size: 11px; font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.il-view-list .il-name { font-size: 12.5px; flex: 1; white-space: nowrap; }
.il-meta { font-size: 11px; color: var(--muted); white-space: nowrap; }
.il-fav {
  position: absolute; top: 4px; right: 6px; font-size: 12px; line-height: 1;
  color: var(--muted); opacity: 0; transition: opacity .12s ease, color .12s ease; padding: 3px;
}
.il-view-list .il-fav { position: static; order: 3; opacity: .5; }
.il-item:hover .il-fav, .il-fav.on { opacity: 1; }
.il-fav.on { color: #f59e0b; }
.il-empty { padding: 40px 10px; text-align: center; color: var(--muted); font-size: 13px; }
.il-foot {
  display: flex; gap: 12px; align-items: center; padding: 9px 18px;
  border-top: 1px solid var(--border-soft); font-size: 11px; color: var(--muted);
}
.il-note { color: #f59e0b; font-weight: 600; }
.il-lic { margin-left: auto; text-align: right; }

/* Export modal: "the shared audio can't carry the narration" recovery panel */
.exp-audio-retry {
  display: flex; flex-direction: column; gap: 10px;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, #f59e0b 45%, var(--border-soft));
  background: color-mix(in srgb, #f59e0b 9%, transparent);
  font-size: 12.5px; line-height: 1.5; color: var(--text);
}
/* Narration-source picker inside the export modal: premium studio clips vs
   the device's live voice, plus the studio persona dropdown. */
.exp-voice-src { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 2px 0 4px; }
.exp-voice-src select { flex: 0 1 auto; min-width: 190px; }
.exp-voice-src .seg-btn[data-val="studio"].active {
  background: linear-gradient(135deg, color-mix(in srgb, var(--iris) 28%, var(--chrome-2)), var(--chrome-2));
  border-color: color-mix(in srgb, var(--iris) 55%, var(--border));
}
/* "Present look" block in the export modal — the stagecraft options mirrored
   from Present mode's settings panel. Its segmented rows carry more choices
   than a modal row fits on one line, so they wrap into a chip grid. */
.exp-look-sub {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin: 8px 0 -2px;
}
.exp-look-sub:first-of-type { margin-top: 2px; }
.seg.seg-wrap { flex-wrap: wrap; }
.seg.seg-wrap .seg-btn { flex: 1 0 auto; min-width: 74px; }


.provider-disabled { font-size: 11.5px; cursor: default; }
.file-recent-list { display: flex; flex-direction: column; gap: 4px; max-height: 190px; overflow-y: auto; }
.file-recent-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-radius: 8px;
  background: var(--chrome-3);
  border: 1px solid transparent;
  font-size: 12.5px;
  cursor: pointer;
}
.file-recent-item:hover { border-color: var(--accent); }
.file-recent-item .fri-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-recent-item .fri-meta { flex: none; color: var(--muted); font-size: 11px; }
.file-recent-item .fri-remove { flex: none; color: var(--muted); padding: 0 4px; font-size: 15px; line-height: 1; border-radius: 5px; }
.file-recent-item .fri-remove:hover { color: var(--danger); background: var(--chrome); }

/* Type picker modal — "What do you want to make?" Tiles are cloned from the
   home type cards at runtime, so the 16 types live in exactly one place. */
.tp-modal { width: 760px; }
.tp-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
@media (max-width: 680px) { .tp-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 480px) { .tp-grid { grid-template-columns: repeat(2, 1fr); } }
.tp-tile {
  display: flex; flex-direction: column; gap: 9px; padding: 10px;
  background: var(--chrome); border: 1px solid var(--border-soft); border-radius: 12px;
  cursor: pointer; text-align: left; color: inherit; font: inherit;
  transition: border-color .12s, transform .1s ease, box-shadow .15s;
}
.tp-tile:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.tp-prev {
  background: linear-gradient(160deg, #ffffff, #eef1f8);
  border: 1px solid var(--border-soft); border-radius: 8px; padding: 9px 10px; line-height: 0;
}
.tp-prev svg { width: 100%; height: auto; display: block; }
.tp-name { font-size: 12.5px; font-weight: 600; letter-spacing: -0.01em; }
.tp-foot { margin-top: 6px; font-size: 13px; color: var(--muted); }
.tp-foot .link-btn { color: var(--accent-ink); font-weight: 600; background: none; border: none; cursor: pointer; padding: 0; font: inherit; }
.tp-foot .link-btn:hover { text-decoration: underline; }

.tpl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.tpl-cat {
  grid-column: 1 / -1;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  margin-top: 8px;
}
.tpl-cat:first-child { margin-top: 0; }
.tpl-card {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  text-align: left;
  padding: 12px;
  background: var(--chrome);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  transition: border-color .12s, transform .08s;
}
.tpl-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.tpl-emoji { font-size: 22px; line-height: 1.2; }
.tpl-name { font-weight: 700; font-size: 12.5px; margin-bottom: 3px; }
.tpl-desc { font-size: 11.5px; color: var(--muted); line-height: 1.45; }
/* Blank canvas leads the Start dialog across the whole row; the dashed edge
   reads as an empty page beside the ready-made cards. */
.tpl-card.tpl-blank { grid-column: 1 / -1; align-items: center; border: 1px dashed var(--border); }
.tpl-card.tpl-blank:hover { border-color: var(--accent); }
.tpl-blank[hidden] + .tpl-cat { margin-top: 0; }

.help-cols { display: flex; flex-direction: row; gap: 22px; }
.help-cols > div { flex: 1; min-width: 0; }
.help-cols h4 { font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin-bottom: 8px; }
.help-cols h4 + .help-list + h4 { margin-top: 16px; }
.help-list { list-style: none; display: flex; flex-direction: column; gap: 7px; font-size: 12.5px; line-height: 1.5; }
.help-list b { color: var(--text); font-weight: 600; }
.help-list li { color: var(--muted); }
.help-h { font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin-bottom: 10px; }

/* notation legend */
.note-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px; }
.note-item { display: flex; gap: 11px; align-items: flex-start; }
.note-item svg { flex: none; margin-top: 1px; }
.note-item b { display: block; font-size: 12.5px; margin-bottom: 2px; }
.note-item span { font-size: 11.5px; color: var(--muted); line-height: 1.45; }
.note-item span b { display: inline; font-size: inherit; margin: 0; color: var(--text); font-weight: 600; }
.note-item code, .legal code {
  font-family: var(--mono);
  font-size: 11px;
  background: var(--chrome-3);
  border-radius: 4px;
  padding: 1px 5px;
}

/* legal modal */
.legal { gap: 4px; }
.legal section { padding: 10px 0 14px; border-bottom: 1px solid var(--border-soft); }
.legal section:last-child { border-bottom: none; }
.legal h4 { font-size: 13.5px; margin-bottom: 8px; display: flex; align-items: center; gap: 8px; }
.legal p, .legal ul { font-size: 12.5px; color: var(--muted); line-height: 1.6; margin-bottom: 8px; }
.legal ul { padding-left: 18px; display: flex; flex-direction: column; gap: 5px; }
.legal b { color: var(--text); font-weight: 600; }
.legal .fineprint { font-size: 11px; opacity: .8; font-style: italic; }
.tag-dummy {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #f59e0b;
  background: rgba(245, 158, 11, .14);
  padding: 2px 6px;
  border-radius: 4px;
}

/* ============ Home page ============ */
/* The scene rules below are scoped `#homePage .lp3 …`. (They were
   an `:is()` naming a second page id while /educational-content shared the
   surface; that page was retired Sep 27 2026, and the one-id form has the
   same specificity, so nothing moved.) */
#homePage {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--chrome);
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  /* flex-start (not center) is deliberate: centering a flex item taller than its
     container clips the overflow above the fold with no way to scroll to it. */
  align-items: flex-start;
  justify-content: center;
}

.home-inner {
  position: relative;
  z-index: 1;
  max-width: 900px;
  width: 100%;
  padding: clamp(96px, 12vh, 128px) 22px 40px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin: auto 0;
}
.home-anim {
  animation: home-fade-up .55s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: var(--d, 0s);
}
@keyframes home-fade-up {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---- Scroll-reveal (js/scroll-fx.js): sections rise + fade in as they enter
   the viewport, so moving between sections feels smooth. The `sr` class is
   added by JS, so content is always visible without it. ---- */
.sr { opacity: 0; transform: translateY(14px); transition: opacity .38s var(--ease-out), transform .42s var(--ease-out); }
.sr.sr-in { opacity: 1; transform: none; }
/* Card-grid stagger: js/scroll-fx.js stamps --sr-i on each grid child; when
   the section reveals, its cards cascade in a beat apart. */
.sr .home-card, .sr .lp-tpl-card, .sr .lp-who .card { opacity: 0; transform: translateY(10px); }
.sr.sr-in .home-card, .sr.sr-in .lp-tpl-card, .sr.sr-in .lp-who .card {
  opacity: 1; transform: none;
  transition: opacity .34s var(--ease-out), transform .38s var(--ease-out);
  transition-delay: calc(var(--sr-i, 0) * 45ms);
}
/* When JS drives the reveal, don't also run the one-shot load animation. */
.home-anim.sr { animation: none; }
/* Smooth programmatic/anchor scrolls. */
#homePage, #explorePage { scroll-behavior: smooth; }
#homePage { scroll-padding-top: 84px; }
@media (prefers-reduced-motion: reduce) {
  .sr, .sr.sr-in { opacity: 1; transform: none; transition: none; }
  #homePage, #explorePage { scroll-behavior: auto; scroll-snap-type: none; }
}

/* ============ CanvasKit — floating toolbar, context menu, ⌘K ============ */
/* All fixed-position glass chrome, shared across every canvas tool. */

/* The stage guide (toggle F) is drawn INTO the rulers now — an accent band
   on the top and left ruler marking the 16:9 working area (canvas-kit's
   renderRulers). The old #ckFrame on-canvas rectangle and its "16:9" tag are
   gone: they crossed lines through the middle of people's diagrams to say
   what the margins can say. */

#ckToolbar {
  position: fixed; z-index: 40; display: flex; align-items: center; gap: 2px;
  padding: 4px; border-radius: var(--r-2);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border); box-shadow: var(--shadow-sm);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
@keyframes ck-pop { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.ck-btn {
  min-width: 28px; height: 28px; padding: 0 6px; border-radius: 7px;
  font-size: 14px; line-height: 1; color: var(--muted); display: inline-flex;
  align-items: center; justify-content: center;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.ck-btn:hover { background: var(--chrome-3); color: var(--text); }
.ck-sep { width: 1px; height: 18px; background: var(--border); margin: 0 4px; flex: none; }
.ck-swatches { display: inline-flex; align-items: center; gap: 3px; padding: 0 2px; }
.ck-swatch {
  width: 16px; height: 16px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, .25);
  cursor: pointer; padding: 0; transition: transform var(--dur-1) var(--ease-out);
}
.ck-swatch:hover { transform: scale(1.2); }
.ck-swatch.active { box-shadow: 0 0 0 2px var(--accent-ring); }
.ck-swatch-none { background: var(--chrome-3); color: var(--muted); font-size: 9px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; border-color: var(--border); }

#ckMenu {
  position: fixed; z-index: 41; min-width: 190px; padding: 5px; border-radius: var(--r-2);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
.ck-mi {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  width: 100%; padding: 7px 10px; border-radius: 7px; font-size: 12.5px; color: var(--text);
  text-align: left;
}
.ck-mi:hover:not(:disabled) { background: var(--accent-soft); }
.ck-mi:disabled { color: var(--faint); cursor: default; }
.ck-mi kbd { font-family: var(--mono); font-size: 10.5px; color: var(--faint); }
.ck-msep { height: 1px; background: var(--border); margin: 4px 6px; }

#canvasWrap.space-pan { cursor: grab; }
#canvasWrap.space-pan:active { cursor: grabbing; }

/* Magic Insert launcher — the round on-canvas button (kids-app style),
   the visible twin of ⌘K. Sits above the canvas, bottom-left. */
#miLauncher {
  position: absolute; left: 16px; bottom: 14px; z-index: 12;
  width: 46px; height: 46px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--on-accent);
  background: linear-gradient(160deg, var(--iris-bright), var(--iris-deep));
  box-shadow: 0 8px 24px -8px color-mix(in srgb, var(--iris) 70%, transparent),
    0 1px 0 rgba(255, 255, 255, .25) inset;
  transition: transform var(--dur-1) var(--ease-spring), box-shadow var(--dur-2) var(--ease-out);
}
#miLauncher:hover { transform: scale(1.1) rotate(8deg); box-shadow: var(--glow-accent), 0 1px 0 rgba(255, 255, 255, .25) inset; }
#miLauncher:active { transform: scale(.96); }
#miLauncher svg { display: block; }
body.presenting #miLauncher, body.watching #miLauncher, body.recording #miLauncher { display: none !important; }
@media (prefers-reduced-motion: reduce) { #miLauncher, #miLauncher:hover { transition: none; transform: none; } }
/* Presenting/recording owns the screen — no editing chrome. Belt for the JS
   guard, which only re-evaluates on the next render. */
body.presenting #ckToolbar, body.watching #ckToolbar, body.recording #ckToolbar,
body.presenting #ckMenu, body.watching #ckMenu, body.recording #ckMenu { display: none !important; }

/* ⌘K command palette */
#ckPalette {
  position: fixed; inset: 0; z-index: 90;
  background: color-mix(in srgb, var(--paper) 55%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  display: flex; align-items: flex-start; justify-content: center; padding-top: 14vh;
}
.ckp {
  width: min(560px, 92vw); border-radius: var(--r-3); overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--border); box-shadow: var(--shadow-lg), var(--glow-accent);
  animation: ckp-in var(--dur-2) var(--ease-out);
}
@keyframes ckp-in { from { opacity: 0; transform: translateY(-8px) scale(.985); } to { opacity: 1; transform: none; } }
#ckpInput {
  width: 100%; padding: 15px 18px; font-size: 15px; background: none; border: none; outline: none;
  border-bottom: 1px solid var(--border); color: var(--text);
}
#ckpInput::placeholder { color: var(--faint); }
.ckp-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.ckp-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px;
  border-radius: 8px; font-size: 13px; color: var(--text); text-align: left;
}
.ckp-item.hi { background: var(--accent-soft); }
.ckp-kind {
  flex: none; font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--accent-ink); background: var(--accent-soft); border-radius: 5px; padding: 3px 6px;
}
.ckp-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ckp-item kbd { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.ckp-empty { padding: 18px; text-align: center; color: var(--faint); font-size: 13px; }
/* Magic Insert extensions: category chips, group headers, star/delete, footer */
.ckp-chips { display: flex; gap: 6px; padding: 9px 12px; border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none; }
.ckp-chip {
  flex: none; font-size: 12px; font-weight: 550; color: var(--muted); cursor: pointer;
  padding: 5px 12px; border-radius: var(--r-full); border: 1px solid var(--border);
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.ckp-chip:hover { color: var(--text); border-color: var(--accent); }
.ckp-chip.on { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.ckp-group {
  font-family: var(--mono); font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--faint); padding: 10px 12px 3px;
}
.ckp-item { cursor: pointer; user-select: none; }
.ckp-glyph { flex: none; width: 26px; text-align: center; font-size: 16px; }
.ckp-desc { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; color: var(--faint); text-align: right; }
.ckp-item .ckp-label { flex: none; max-width: 45%; }
.ckp-star, .ckp-del {
  flex: none; width: 22px; height: 22px; border-radius: 6px; font-size: 13px; line-height: 1;
  color: var(--faint); opacity: 0; transition: opacity var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.ckp-item:hover .ckp-star, .ckp-item.hi .ckp-star,
.ckp-item:hover .ckp-del, .ckp-item.hi .ckp-del { opacity: 1; }
.ckp-star:hover, .ckp-star.on { color: var(--d-amber); opacity: 1; }
.ckp-del:hover { color: var(--danger); }
.ckp-foot {
  display: flex; gap: 16px; justify-content: center; padding: 8px 12px;
  border-top: 1px solid var(--border); font-family: var(--mono); font-size: 10.5px; color: var(--faint);
}

/* Layers panel */
#ckLayers {
  position: fixed; left: 232px; top: 76px; z-index: 39; width: 216px;
  border-radius: var(--r-2); overflow: hidden;
  background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
.ck-layers-head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); padding: 9px 6px 7px 12px; border-bottom: 1px solid var(--border);
}
.ck-layers-x { width: 22px; height: 22px; border-radius: 6px; color: var(--faint); font-size: 14px; }
.ck-layers-x:hover { color: var(--text); background: var(--chrome-3); }
.ck-layers-list { max-height: 46vh; overflow-y: auto; padding: 5px; }
.ck-layer {
  display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: 7px;
  font-size: 12.5px; color: var(--text); cursor: pointer;
}
.ck-layer:hover { background: var(--chrome-3); }
.ck-layer.sel { background: var(--accent-soft); }
.ck-layer.drop { box-shadow: 0 -2px 0 var(--accent); }
.ck-layer.locked .ck-layer-name { color: var(--faint); }
.ck-layer-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ck-layer-lock { flex: none; font-size: 11px; opacity: .35; }
.ck-layer:hover .ck-layer-lock, .ck-layer.locked .ck-layer-lock { opacity: 1; }
.ck-layers-empty { padding: 14px; text-align: center; color: var(--faint); font-size: 12px; }

/* Minimap */
#ckMinimap {
  position: fixed; z-index: 39; width: 186px; border-radius: var(--r-2); overflow: hidden;
  background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
.ck-mini-head {
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); padding: 7px 12px 5px; border-bottom: 1px solid var(--border);
}
.ck-mini-stage { position: relative; margin: 8px; cursor: crosshair; border-radius: 6px; overflow: hidden; background: var(--canvas-bg); }
.ck-mini-stage svg { display: block; }
.ck-mini-view {
  position: absolute; border: 1.5px solid var(--iris); border-radius: 3px;
  background: color-mix(in srgb, var(--iris) 14%, transparent); pointer-events: none;
}
body.presenting #ckLayers, body.watching #ckLayers, body.recording #ckLayers,
body.presenting #ckMinimap, body.watching #ckMinimap, body.recording #ckMinimap { display: none !important; }

/* Animated connector flow — marching dashes in the editor and Present mode
   (raster exports draw the static dash pattern). */
@keyframes fc-flow-dash { to { stroke-dashoffset: -30; } }
.fc-flow { animation: fc-flow-dash 1s linear infinite; }

/* Live Present's optional arrow motion is a travelling accent overlay, never
   the real shaft. The base arrow therefore keeps its authored dash, colour,
   width and arrowhead; labels remain readable even in a moving diagram.
   `pathLength=100` on the cloned runner makes its comet-and-spark rhythm
   proportionate on both tiny local links and long diagram-spanning routes. */
@keyframes pr-connector-flow-glint {
  0% { stroke-dashoffset: 100; stroke-opacity: .62; }
  14% { stroke-opacity: .98; }
  62% { stroke-opacity: .86; }
  84% { stroke-opacity: .96; }
  100% { stroke-dashoffset: 0; stroke-opacity: .68; }
}
body.presenting #svgHost .pr-connector-motion-trace {
  fill: none !important;
  /* The runner is the Present theme's kinetic accent. It is intentionally
     separate from the authored shaft (and from the branch-coloured one-shot
     arrival trace), so changing Current/Aurora/Gallery immediately changes
     the live flow treatment without restyling the diagram itself. */
  stroke: var(--pr-connector-flow-color,
    color-mix(in srgb,
      var(--pr-connector-flow-core, var(--iris-bright, #8b80ff)) 84%,
      var(--pr-connector-flow-spark, #fff))) !important;
  stroke-width: var(--pr-connector-flow-width, 3.4) !important;
  stroke-opacity: .92;
  /* A long rounded comet followed by a pin-point sparkle. `pathLength=100`
     on the clone keeps the treatment proportional across local and long
     connectors, without adding a particle layer over the diagram. */
  stroke-dasharray: 12 3 1.35 83.65 !important;
  stroke-dashoffset: 100;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 1px var(--pr-connector-flow-spark, transparent))
          drop-shadow(0 0 3px var(--pr-connector-flow-halo, transparent));
  animation: pr-connector-flow-glint var(--pr-connector-flow-duration, 3.4s) linear infinite;
  animation-delay: var(--pr-connector-flow-delay, 0s);
}
body.presenting #prConnectorMotionToggle.on,
body.presenting #prConnectorMotionToggle[aria-pressed="true"] {
  color: var(--pr-stage-ink, #e9ecff);
  background: color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 25%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-motion-base, var(--iris-bright, #8b80ff)) 48%, transparent) inset,
              0 0 14px -8px var(--pr-motion-base, var(--iris-bright, #8b80ff));
}
@media (prefers-reduced-motion: reduce) {
  body.presenting #svgHost [data-pr-connector-motion] { display: none !important; animation: none !important; }
}

/* Rulers + user guides (toggle R) */
#ckRulerH, #ckRulerV {
  position: fixed; z-index: 38; background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  cursor: crosshair;
}
#ckRulerH { height: 22px; border-bottom: 1px solid var(--border); }
#ckRulerV { width: 22px; border-right: 1px solid var(--border); }
#ckGuides { position: fixed; inset: 0; z-index: 37; pointer-events: none; }
.ck-guide { position: fixed; pointer-events: auto; }
.ck-guide-x { width: 9px; margin-left: -4.5px; cursor: ew-resize; }
.ck-guide-y { height: 9px; margin-top: -4.5px; cursor: ns-resize; }
.ck-guide::after { content: ""; position: absolute; background: color-mix(in srgb, var(--iris) 75%, transparent); }
.ck-guide-x::after { left: 4px; top: 0; bottom: 0; width: 1px; }
.ck-guide-y::after { top: 4px; left: 0; right: 0; height: 1px; }
body.presenting #ckRulerH, body.presenting #ckRulerV, body.presenting #ckGuides,
body.watching #ckRulerH, body.watching #ckRulerV, body.watching #ckGuides { display: none !important; }

/* Present-mode entrance animations — the element revealed by the current step
   carries one of these (see graphtool buildSvg). Classes only have rules in
   the live document, so exported SVG/GIF/video stay static by design. */
@keyframes prFade { from { opacity: 0; } }
@keyframes prGrow { from { opacity: 0; transform: scale(.55); } }
@keyframes prSlide { from { opacity: 0; transform: translateY(20px); } }
@keyframes prPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }
@keyframes prWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
/* dasharray lives inside the keyframes with fill-mode "backwards", so once the
   draw finishes the edge's own dash pattern (dashed/dotted/flow) reasserts. */
@keyframes prDrawPath {
  from { stroke-dasharray: 100; stroke-dashoffset: 100; }
  to { stroke-dasharray: 100; stroke-dashoffset: 0; }
}
.pr-anim-fade { animation: prFade .5s var(--ease-out) both; }
.pr-anim-grow { animation: prGrow .5s var(--ease-spring) both; transform-box: fill-box; transform-origin: center; }
.pr-anim-slide { animation: prSlide .5s var(--ease-out) both; }
.pr-anim-pulse { animation: prFade .35s var(--ease-out) both, prPulse 1.5s .4s ease-in-out 2; transform-box: fill-box; transform-origin: center; }
.pr-anim-draw { animation: prWipe .55s var(--ease-out) both; }
.pr-anim-drawpath { animation: prDrawPath .55s var(--ease-out) backwards; }
/* Pencil sketch: the INK holds back while an injected tracer (PencilTrace in
   app.js) draws the shape's outline with a pencil riding the tip, then the
   ink fades in as the pencil lifts. The hold and the trace share one clock —
   PencilTrace reads this animation's duration off the element, so retiming
   the entrance retimes the pencil with it. */
.pr-anim-sketch { animation: prSketchInk 2.6s var(--ease-out) both; }
/* The workshop placement's CSS fallback: held off-stage, then simply there —
   the HAND choreography (PencilTrace) overrides this wholesale; this exists
   so a no-JS/reduced path still reveals on the CSS clock. */
.pr-anim-place { animation: prSketchInk 1.6s var(--ease-out) both; }
/* Terminal panels hold until the prompt has "created" them (the typing engine
   overrides with its own schedule; this is the CSS-clock fallback). */
.pr-anim-type { animation: prSketchInk 1.4s steps(2, jump-none) both; }
/* Metro stations hold until the train arrives (the rider engine reveals them);
   this is the CSS-clock fallback. */
.pr-anim-ride { animation: prSketchInk 1.3s var(--ease-out) both; }
/* Mission Control: the module flies its approach path and settles — pure CSS,
   translate + overshoot, opacity riding along. Entrance transforms are the
   sanctioned kind (pr-anim-slide precedent); nothing after the settle moves. */
.pr-anim-dock { animation: prDockIn 1.05s cubic-bezier(0.18, 0.9, 0.24, 1.06) both; }
@keyframes prDockIn {
  0% { opacity: 0; transform: translate(150px, -100px); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: translate(0, 0); }
}
/* Neon: the sign buzzes on — the broken-tube stutter, then steady. steps()
   keeps each flash discrete; the timing is the whole joke. */
.pr-anim-buzz { animation: prBuzzOn 1.15s steps(1, jump-none) both; }
@keyframes prBuzzOn {
  0% { opacity: 0; }
  8% { opacity: 1; } 12% { opacity: 0; }
  22% { opacity: 0.85; } 27% { opacity: 0.1; }
  38% { opacity: 1; } 42% { opacity: 0.4; }
  55% { opacity: 1; }
  100% { opacity: 1; }
}
@keyframes prSketchInk {
  /* Hold to 50% — the trace runs exactly the first half (PencilTrace uses
     duration/2) — then arrive fast: the ink lands AS the pencil lifts, which
     is what makes it read as drawn rather than revealed. */
  0%, 50% { opacity: 0; }
  66% { opacity: 1; }
  100% { opacity: 1; }
}
.pr-pencil-line {
  fill: none; stroke-linecap: round; stroke-linejoin: round;
  pointer-events: none;
}
/* Ink & paper — the document-wide font/background override in Settings. */
.cs-inkpaper { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cs-book-style-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.cs-book-cover-field { display: grid; gap: 7px; }
.cs-book-cover-control {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 8px; border: 1px solid var(--border-soft); border-radius: 9px;
  background: var(--panel-2);
}
.cs-book-cover-preview {
  flex: none; width: 42px; height: 63px; object-fit: contain; border-radius: 3px 7px 7px 3px;
  background: var(--chrome); box-shadow: 3px 4px 9px -5px rgba(0,0,0,.75);
}
.cs-book-cover-preview[hidden] { display: none; }
.cs-book-cover-copy { display: grid; gap: 2px; min-width: 0; }
.cs-book-cover-copy b { color: var(--text); font-size: 11.5px; }
.cs-book-cover-copy small, .cs-book-cover-help { color: var(--muted); font-size: 10.5px; line-height: 1.4; }
.cs-book-cover-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.cs-book-style {
  min-width: 0; min-height: 47px; display: flex; align-items: center; gap: 7px;
  padding: 6px; color: var(--text); text-align: left; border: 1px solid var(--border-soft);
  border-radius: 8px; background: var(--panel-2); cursor: pointer;
}
.cs-book-style:hover { border-color: var(--accent); }
.cs-book-style.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.cs-book-style > i {
  position: relative; flex: none; width: 25px; height: 34px; border-radius: 2px 5px 5px 2px;
  background: linear-gradient(145deg, color-mix(in srgb, var(--book-cover) 82%, white), var(--book-cover));
  box-shadow: 3px 3px 0 -1px var(--book-paper), 0 5px 9px -5px #000;
}
.cs-book-style > i::after { content: ""; position: absolute; inset: 5px; border: 1px solid var(--book-accent); }
.cs-book-style > i::before { content: ""; position: absolute; z-index: 1; pointer-events: none; }
.cs-book-style[data-book-style="literary"] > i::before {
  left: 11px; top: 14px; width: 4px; height: 4px; border: 1px solid var(--book-accent); transform: rotate(45deg);
}
.cs-book-style[data-book-style="textbook"] > i {
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--book-cover) 55%, black) 0 6px, var(--book-accent) 6px 8px, transparent 8px),
    linear-gradient(145deg, color-mix(in srgb, var(--book-cover) 82%, white), var(--book-cover));
}
.cs-book-style[data-book-style="textbook"] > i::after { inset: 5px 4px 5px 10px; border-width: 2px 1px 1px; }
.cs-book-style[data-book-style="graphic"] > i {
  border-radius: 1px 4px 4px 1px;
  background:
    linear-gradient(145deg, transparent 0 55%, var(--book-accent) 56% 74%, transparent 75%),
    radial-gradient(circle, rgba(255,255,255,.18) 0 1px, transparent 1.2px) 0 0 / 6px 6px,
    var(--book-cover);
}
.cs-book-style[data-book-style="graphic"] > i::after { inset: 4px; border-width: 2px; }
.cs-book-style[data-book-style="fieldguide"] > i {
  background:
    repeating-linear-gradient(2deg, rgba(255,255,255,.07) 0 1px, transparent 1px 4px),
    var(--book-cover);
}
.cs-book-style[data-book-style="fieldguide"] > i::after {
  inset: 8px 5px; border: 1px dashed var(--book-accent); background: color-mix(in srgb, var(--book-paper) 16%, transparent);
}
.cs-book-style[data-book-style="monograph"] > i {
  border-radius: 1px 4px 4px 1px;
  background: linear-gradient(90deg, #050608 0 6px, var(--book-accent) 6px 7px, var(--book-cover) 7px);
}
.cs-book-style[data-book-style="monograph"] > i::after { inset: 6px 4px 11px 10px; border: 0; border-top: 1px solid var(--book-accent); border-left: 1px solid var(--book-accent); }
.cs-book-style[data-book-style="handbook"] > i {
  border-radius: 3px 6px 6px 3px;
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--book-cover) 64%, black) 0 6px, var(--book-accent) 6px 8px, transparent 8px),
    linear-gradient(153deg, transparent 0 68%, color-mix(in srgb, #f2c94c 80%, transparent) 69% 76%, transparent 77%),
    linear-gradient(145deg, color-mix(in srgb, var(--book-cover) 84%, white), var(--book-cover));
}
.cs-book-style[data-book-style="handbook"] > i::after {
  inset: 5px 4px 6px 10px; border: 0; border-top: 1px solid #f2c94c;
  border-left: 2px solid var(--book-accent); border-bottom: 1px solid #f2c94c;
}
.cs-book-style[data-book-style="handbook"] > i::before {
  right: 4px; bottom: 8px; width: 9px; height: 3px; border-radius: 999px;
  background: #f2c94c; transform: rotate(-8deg);
}
.cs-book-style span { min-width: 0; display: grid; gap: 2px; }
.cs-book-style b { overflow: hidden; text-overflow: ellipsis; font-size: 10.5px; white-space: nowrap; }
.cs-book-style small { color: var(--muted); font-size: 9px; }
.cs-ip { display: inline-flex; align-items: center; gap: 5px; }
.cs-ip input[type="color"] {
  width: 34px; height: 24px; padding: 1px; border: 1px solid var(--border);
  border-radius: 7px; background: var(--panel-2, var(--panel)); cursor: pointer;
}
.cs-ip small { color: var(--muted); font-size: 10.5px; }
.cs-ip-x {
  border: 1px solid var(--border); background: none; color: var(--muted);
  border-radius: 6px; width: 18px; height: 18px; line-height: 1; cursor: pointer;
  font-size: 12px; padding: 0;
}
.cs-ip-x:hover { color: var(--text); border-color: var(--text); }

/* The HAND chrome skin lives at the END of this file — it must outrank the
   Present polish sections' `font:` shorthands, which come after this line. */

@media (prefers-reduced-motion: reduce) {
  .fc-flow, .pr-anim-fade, .pr-anim-grow, .pr-anim-slide, .pr-anim-pulse, .pr-anim-draw, .pr-anim-drawpath, .pr-anim-sketch, .pr-anim-place, .pr-anim-type, .pr-anim-ride, .pr-anim-dock, .pr-anim-buzz { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  #ckToolbar, #ckMenu, #ckLayers, #ckMinimap, .ckp { animation: none; }
}

/* ============ Explore gallery page ============ */
#explorePage {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--chrome);
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
/* ============================================================
   Explore — template marketplace. Discovery-first surface built on the
   existing brand tokens (marigold signal, graphite/paper neutrals, dot grid).
   Class prefix .mkt-*. Pagination reuses .explore-page-* below.
   ============================================================ */
.mkt {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: none;
  margin: 0 auto;
  padding: clamp(76px, 8vh, 90px) clamp(18px, 4vw, 64px) 34px;
  text-align: left;
}
/* Full-width explore: header spans the viewport to match the body. */
#explorePage .lp-top-inner { max-width: none; padding: 0 clamp(18px, 4vw, 64px); }
/* ---- Hero + search (minimal, marketplace-style) ---- */
.mkt-hero { text-align: center; padding: 8px 0 6px; }
.mkt-title {
  font-size: clamp(26px, 3.6vw, 38px); font-weight: 800; letter-spacing: -.03em;
  line-height: 1.06; margin: 0; text-wrap: balance;
}
.mkt-sub { color: var(--muted); font-size: clamp(13.5px, 1.4vw, 15px); line-height: 1.5; max-width: 54ch; margin: 10px auto 0; }
.mkt-sub b { color: var(--text); font-weight: 600; }
.mkt-search {
  position: relative; display: flex; align-items: center; gap: 12px;
  max-width: 620px; margin: 22px auto 0; padding: 0 14px 0 18px; height: 54px;
  background: var(--chrome-2); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-sm); transition: border-color .16s ease, box-shadow .16s ease;
}
.mkt-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-ring), var(--shadow-sm); }
.mkt-search-ico { width: 21px; height: 21px; color: var(--faint); flex: none; }
.mkt-search input {
  flex: 1; min-width: 0; height: 100%; border: none; background: none; outline: none;
  color: var(--text); font-size: 15.5px; font-family: inherit;
}
.mkt-search input::placeholder { color: var(--faint); }
.mkt-kbd {
  font-family: var(--mono); font-size: 12px; color: var(--muted); flex: none;
  background: var(--chrome-3); border: 1px solid var(--border-soft); border-bottom-width: 2px;
  border-radius: 6px; padding: 2px 8px;
}
.mkt-suggests { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 7px; margin-top: 14px; }
.mkt-sugg-label { font-size: 12.5px; color: var(--faint); }
.mkt-sugg {
  font-size: 12.5px; font-weight: 550; color: var(--muted); cursor: pointer;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 999px; padding: 5px 12px;
  transition: color .12s, border-color .12s, transform .12s;
}
.mkt-sugg:hover { color: var(--text); border-color: var(--accent); transform: translateY(-1px); }


/* ---- Toolbar: filters + sort + count ---- */
/* Sticky glass toolbar — sort + result count stay in reach while scrolling
   the grid. Sits just under the fixed .lp-top header. */
.mkt-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  position: sticky; top: 64px; z-index: 5; margin: 12px 0 4px; padding: 8px 10px;
  background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border-soft); border-radius: var(--r-2); }
.mkt-filters { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.mkt-select {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 999px;
  padding: 8px 30px 8px 13px; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2398a0ae' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
  transition: border-color .12s, color .12s;
}
.mkt-select:hover { border-color: var(--accent); color: var(--text); }
.mkt-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mkt-select.is-set { color: var(--text); border-color: var(--accent); background-color: var(--accent-soft); }
.mkt-toggle {
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 999px; padding: 8px 13px;
  transition: color .12s, background .12s, border-color .12s;
}
.mkt-toggle:hover { color: var(--text); border-color: var(--accent); }
.mkt-toggle.on { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.mkt-sort { margin-left: 2px; }
.mkt-clear { font: inherit; font-size: 12.5px; font-weight: 600; color: var(--danger); cursor: pointer; background: none; border: none; padding: 8px 6px; }
.mkt-clear:hover { text-decoration: underline; }
.mkt-count { font-family: var(--mono); font-size: 12.5px; color: var(--faint); flex: none; }

/* ---- Quick access: continue / recent / favorites ---- */
.mkt-quick { display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: flex-start; margin: 8px 0 18px; }
.mkt-continue {
  display: inline-flex; align-items: center; gap: 12px; cursor: pointer; text-align: left;
  background: linear-gradient(120deg, var(--accent-soft), transparent 70%), var(--chrome-2);
  border: 1px solid var(--accent-ring); border-radius: 14px; padding: 12px 16px;
  transition: transform .12s, box-shadow .15s;
}
.mkt-continue:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.mkt-continue-ico { width: 38px; height: 38px; flex: none; display: grid; place-items: center; color: var(--accent-ink); background: var(--chrome); border: 1px solid var(--border-soft); border-radius: 10px; }
.mkt-continue-ico svg { width: 20px; height: 20px; }
.mkt-continue-txt { display: flex; flex-direction: column; }
.mkt-continue-k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-ink); }
.mkt-continue-t { font-size: 14px; font-weight: 650; color: var(--text); max-width: 30ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mkt-continue-go { font-size: 12.5px; font-weight: 600; color: var(--accent-ink); margin-left: 4px; }
.mkt-mini-block { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.mkt-mini-head { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); }
.mkt-mini-rail { display: flex; flex-wrap: wrap; gap: 8px; }
.mkt-mini {
  display: inline-flex; align-items: center; gap: 8px; flex: none; cursor: pointer; max-width: 220px;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 10px; padding: 5px 11px 5px 5px;
  transition: border-color .12s, transform .12s;
}
.mkt-mini:hover { border-color: var(--accent); transform: translateY(-1px); }
.mkt-mini-thumb { width: 40px; height: 26px; flex: none; border-radius: 6px; overflow: hidden; background: var(--canvas-bg); }
.mkt-mini-thumb svg { width: 100%; height: 100%; display: block; }
.mkt-mini-name { font-size: 12.5px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Sections + rails ---- */
.mkt-sections { display: flex; flex-direction: column; gap: 26px; margin-top: 6px; }
.mkt-section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 12px; }
.mkt-section-head h2 { font-size: clamp(16px, 2vw, 19px); font-weight: 760; letter-spacing: -.02em; display: flex; align-items: center; gap: 8px; }
.mkt-section-head p { font-size: 13px; color: var(--muted); margin-top: 3px; }
.mkt-h-ico { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 7px; font-size: 13px; background: var(--accent-soft); color: var(--accent-ink); }
.mkt-h-ico--ai { background: color-mix(in srgb, var(--d-violet) 20%, transparent); color: var(--d-violet); }
.mkt-seeall { font-family: var(--mono); font-size: 12.5px; font-weight: 600; color: var(--accent-ink); background: none; border: none; cursor: pointer; white-space: nowrap; flex: none; }
.mkt-seeall span { display: inline-block; transition: transform .15s; }
.mkt-seeall:hover span { transform: translateX(3px); }
/* One row of cards — the count is sliced in JS to exactly fill the width, so
   there is no horizontal scroll and no wrapping; the rest is behind "See more". */
.mkt-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(205px, 1fr)); gap: 14px; }


/* ---- Card ---- */
.mkt-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(205px, 1fr)); gap: 14px; }
.mkt-card {
  position: relative; display: flex; flex-direction: column; text-align: left; cursor: pointer;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 14px; overflow: hidden;
  transition: transform .14s ease, border-color .14s ease, box-shadow .16s ease;
  /* Off-screen cards skip layout/paint entirely; the intrinsic size keeps the
     scrollbar stable while they're skipped. */
  content-visibility: auto;
  contain-intrinsic-size: 240px 260px;
}
/* A soft, neutral lift — no colored glow, so the card reads calm. */
.mkt-card:hover {
  transform: translateY(-3px); border-color: color-mix(in srgb, var(--slate) 32%, var(--border-soft));
  box-shadow: var(--shadow);
}
.mkt-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mkt-thumb { position: relative; aspect-ratio: 16 / 10; background: var(--canvas-bg); overflow: hidden; }
/* The card's only artwork: the catalog row's own `icon_svg`, drawn inline.
   There is no per-template raster/SVG file layered on top — see renderExploreCard. */
.mkt-thumb > svg { width: 100%; height: 100%; display: block; padding: 8px 12px; }
.mkt-card.mkt-card--story .mkt-thumb { aspect-ratio: 16 / 9; }
.mkt-card.mkt-card--story .mkt-thumb > svg { padding: 0; }
/* One restrained frosted label — no bright fills competing with the artwork. A
   small colored dot carries the only hue. */
.mkt-badge {
  position: absolute; top: 9px; left: 9px; z-index: 2; display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
  color: #f4f5f8; padding: 3px 8px 3px 7px; border-radius: 6px;
  background: color-mix(in srgb, #05070c 58%, transparent); border: 1px solid rgba(255, 255, 255, .14);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.mkt-badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--badge-dot, var(--marigold)); }
.mkt-badge--trending { --badge-dot: var(--marigold); }
.mkt-badge--new { --badge-dot: #34d399; }

/* ---- Engagement strip (js/engagement.js) --------------------------------
   Views · watch time (text) + like · share (live buttons), one quiet row.
   Shared by Explore cards, search tiles and the quick view; empty spans stay
   hidden so an untouched diagram wears no zeros. */
.eng-strip {
  display: flex; align-items: center; gap: 10px;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border-soft);
  font-size: 11.5px; color: var(--faint);
}
.eng-strip svg { width: 14px; height: 14px; flex: none; }
.eng-stat { display: inline-flex; align-items: center; gap: 4px; }
.eng-stat b { font-weight: 600; font-variant-numeric: tabular-nums; }
.eng-like, .eng-share {
  display: inline-flex; align-items: center; gap: 4px;
  font: inherit; font-weight: 600; color: var(--faint);
  background: none; border: 0; padding: 3px 6px; margin: -3px 0;
  border-radius: 8px; cursor: pointer;
  transition: color var(--dur-1) ease, background var(--dur-1) ease, transform var(--dur-1) ease;
}
.eng-like { margin-left: auto; }   /* actions live on the right edge */
.eng-like:hover, .eng-share:hover { color: var(--text); background: var(--accent-soft); }
.eng-like:active, .eng-share:active { transform: scale(.92); }
.eng-like.is-on { color: var(--accent-ink); }
.eng-like.is-on svg { fill: color-mix(in srgb, var(--accent) 30%, transparent); }
.eng-strip--qv { font-size: 12.5px; margin-top: 10px; }
.eng-strip--qv svg { width: 16px; height: 16px; }
/* Search tiles pad their own body; keep the strip inside that gutter. */
.srch-tile .eng-strip { margin: 10px 12px 0; padding-top: 8px; }
/* Home demo tiles: tighter, and no extra gutter — the body already pads. */
/* min-height reserves the line the counts will occupy. The strip is mounted
   empty (its totals arrive from diagram_stats a moment later, and it stays
   empty below the display thresholds by design), so without a reserve every
   tile grew by ~14px the instant the numbers landed — a layout shift across
   the whole band, on a page whose CLS this work exists to fix. Matches the
   filled height: 11px font on the strip's line box. */
.lp-sample .eng-strip { margin-top: 7px; padding-top: 7px; font-size: 11px; gap: 8px; min-height: 14px; }
.lp-sample .eng-strip svg { width: 13px; height: 13px; }

/* ---- Watch-link boot veil (#watchBoot) ----------------------------------
   A player's loading screen, not an app's: the Present stage's own dark
   ground from the first paint, the mark, one progress bar. Deliberately dark
   in BOTH themes — it hands off to Present, whose chrome is dark in both.
   Shown only under html.preboot-watch; sample-present.js widens the fill per
   load stage and removes the class (the fade below) when the show is up. */
#watchBoot {
  display: none;
  position: fixed; inset: 0; z-index: 400;
  background: radial-gradient(60rem 40rem at 50% -10%, #171a2c, #0b0d14 70%);
  flex-direction: column; align-items: center; justify-content: center; gap: 22px;
  color: #e9ecff;
  transition: opacity .45s ease;
}
.preboot-watch #watchBoot { display: flex; }
#watchBoot.wb-out { opacity: 0; pointer-events: none; }
#watchBoot .wb-mark { width: 74px; height: 74px; color: #e9ecff; }
#watchBoot .wb-mark svg { width: 100%; height: 100%; }
#watchBoot .wb-bar {
  width: min(320px, 60vw); height: 4px; border-radius: 999px;
  background: rgba(233, 236, 255, .14); overflow: hidden;
}
#watchBoot .wb-bar i {
  display: block; height: 100%; width: 12%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--iris, #6a5cff), var(--iris-bright, #8b80ff));
  transition: width .5s cubic-bezier(.22, 1, .36, 1);
}
#watchBoot .wb-label {
  font-size: 13px; letter-spacing: .02em; color: rgba(233, 236, 255, .72);
}
@media (prefers-reduced-motion: reduce) {
  #watchBoot, #watchBoot .wb-bar i { transition: none; }
}

.mkt-fav {
  position: absolute; top: 8px; right: 8px; z-index: 2; width: 30px; height: 30px; cursor: pointer;
  display: grid; place-items: center; border-radius: 8px; border: 1px solid var(--border-soft);
  background: color-mix(in srgb, var(--chrome-2) 78%, transparent);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  color: var(--slate); opacity: 0; transition: color .12s, transform .12s, border-color .12s, opacity .14s;
}
/* Quiet at rest — only appears on hover, or stays if it's a saved favorite. */
.mkt-card:hover .mkt-fav, .mkt-card:focus-within .mkt-fav, .mkt-fav.is-on { opacity: 1; }
.mkt-fav svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; }
.mkt-fav:hover { color: var(--danger); transform: scale(1.08); border-color: var(--danger); }
.mkt-fav.is-on { color: var(--danger); border-color: var(--danger); }
.mkt-fav.is-on svg { fill: var(--danger); stroke: var(--danger); }
.mkt-thumb-hover {
  position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  background: color-mix(in srgb, var(--paper) 46%, transparent); opacity: 0; transition: opacity .16s ease;
}
.mkt-card:hover .mkt-thumb-hover, .mkt-card:focus-within .mkt-thumb-hover { opacity: 1; }
.mkt-thumb-hover button {
  font: inherit; font-size: 12.5px; font-weight: 650; cursor: pointer; padding: 7px 14px; border-radius: 9px; min-width: 118px; text-align: center;
  transform: translateY(6px); transition: transform .16s ease, filter .12s;
}
.mkt-card:hover .mkt-thumb-hover button { transform: translateY(0); }
.mkt-use { color: var(--on-accent); background: var(--accent); border: 1px solid var(--accent); box-shadow: 0 6px 18px -8px var(--marigold); }
.mkt-use:hover { filter: brightness(1.05); }
/* One-touch Present — warm marigold so it reads as a distinct "play" next to the
   iris Use button; dark ink keeps it high-contrast on the fixed fill in both themes. */
.mkt-present { color: #241a06; background: var(--marigold); border: 1px solid var(--marigold-deep); box-shadow: 0 6px 18px -8px var(--marigold); }
.mkt-present:hover { filter: brightness(1.05); }
.mkt-eye { color: var(--text); background: var(--chrome-2); border: 1px solid var(--border-soft); }
.mkt-eye:hover { border-color: var(--accent); }
.mkt-card-body { display: flex; flex-direction: column; gap: 5px; padding: 10px 12px 11px; flex: 1; }
.mkt-type { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 650; letter-spacing: .03em; text-transform: uppercase; color: var(--faint); }
.mkt-typeico { width: 14px; height: 14px; display: inline-grid; place-items: center; color: var(--slate); }
.mkt-typeico svg { width: 14px; height: 14px; }
.mkt-card-title { font-size: 13.5px; font-weight: 700; line-height: 1.28; color: var(--text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mkt-card-desc { font-size: 12px; color: var(--muted); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mkt-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 6px; margin-top: auto; padding-top: 4px; font-size: 11px; color: var(--muted); }
/* "Read the guide" — the narrated tour's article version (pages/diagram/).
   Sits under the meta row so it reads as a second action, not a stat. */
.mkt-guide { display: inline-flex; align-items: center; gap: 5px; margin-top: 6px; font-size: 11.5px;
  font-weight: 650; color: var(--iris-bright, #8b80ff); text-decoration: none; }
.mkt-guide:hover { text-decoration: underline; }
.mkt-guide span { transition: transform .15s ease; }
.mkt-guide:hover span { transform: translateX(3px); }
.mkt-diff { display: inline-flex; align-items: center; gap: 4px; font-weight: 550; }
.mkt-diff::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.mkt-diff--beg { color: var(--d-green); }
.mkt-diff--int { color: var(--d-amber); }
.mkt-diff--adv { color: var(--d-coral); }
.mkt-sep { color: var(--faint); }
.mkt-uses { margin-left: auto; font-family: var(--mono); font-size: 10.5px; color: var(--faint); }
.mkt-uses::before { content: "▲"; font-size: 7px; margin-right: 3px; vertical-align: middle; opacity: .7; }
/* The content-review stamp, on the meta line after the use count. Quiet —
   it is a provenance mark, not a promotion; the accent-ink text token keeps
   it readable in both themes without shouting. */

/* ---- completeness meter: Diagram / Notes / Images / Premium voice ----
   Four single-letter pips (D N I V). A filled pip means the axis is present;
   the first is always filled (every entry is a diagram). Compact by design —
   the full axis names live in the title/aria-label and in the filter. Shared
   by Explore cards (.dg-meter) and /search tiles. */
.dg-meter {
  display: inline-flex;
  gap: 3px;
  margin-top: 8px;
  vertical-align: middle;
}
.dg-pip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 4px;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  /* Absent: a faint outline, no fill — legible in both themes off --faint. */
  color: var(--faint);
  border: 1px solid var(--border-soft);
  background: transparent;
  font-family: var(--mono, ui-monospace, monospace);
}
.dg-pip.on {
  color: var(--on-signal, #fff);
  background: var(--accent);
  border-color: var(--accent);
}
:root[data-ui-theme="light"] .dg-pip.on { color: #fff; }

/* On a search tile the meter sits on its own line under the meta text. */
.srch-meter-wrap { display: block; margin-top: 6px; }
.srch-tile .dg-meter { margin-top: 0; }
.mkt-card--featured .mkt-thumb { aspect-ratio: 16 / 10; }
.mkt-card--featured.mkt-card--story .mkt-thumb { aspect-ratio: 16 / 9; }

/* ---- Results ---- */
.mkt-results-head { margin: 6px 0 16px; }
.mkt-results-head h2 { font-size: clamp(19px, 2.4vw, 24px); font-weight: 780; letter-spacing: -.02em; }
.mkt-empty { margin: 30px 0; color: var(--muted); font-size: 13.5px; text-align: center; }

/* ---- Pagination (reused engine class names) ---- */
.explore-pagination { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 6px; margin-top: 32px; }
.explore-page-btn {
  min-width: 36px; height: 36px; padding: 0 10px; border-radius: 9px; border: 1px solid var(--border-soft);
  background: var(--chrome-2); color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer;
}
.explore-page-btn:hover:not(:disabled) { border-color: var(--accent); }
.explore-page-btn.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); cursor: default; }
.explore-page-btn:disabled { opacity: .4; cursor: default; }
.explore-page-ellipsis { color: var(--muted); font-size: 13px; padding: 0 4px; }

/* ---- Quick-view modal ---- */
.mkt-qv-backdrop {
  position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 22px;
  background: color-mix(in srgb, #05070c 62%, transparent); -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
  opacity: 0; transition: opacity .18s ease;
}
.mkt-qv-backdrop.is-open { opacity: 1; }
.mkt-qv {
  position: relative; width: min(760px, 96vw); max-height: 88vh; overflow-y: auto;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 20px;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,.6); padding: 22px; transform: translateY(10px) scale(.98);
  transition: transform .2s cubic-bezier(.16,.84,.28,1);
}
.mkt-qv-backdrop.is-open .mkt-qv { transform: translateY(0) scale(1); }
.mkt-qv-x { position: absolute; top: 14px; right: 14px; z-index: 3; width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--border-soft); background: var(--chrome); color: var(--muted); font-size: 15px; cursor: pointer; }
.mkt-qv-x:hover { color: var(--text); border-color: var(--accent); }
.mkt-qv-body { display: grid; grid-template-columns: minmax(0, 260px) 1fr; gap: 22px; }
.mkt-qv-preview { position: relative; aspect-ratio: 5 / 3; background: var(--canvas-bg); border-radius: 14px; overflow: hidden; border: 1px solid var(--border-soft); }
.mkt-qv-preview svg { width: 100%; height: 100%; padding: 14px 18px; }
.mkt-qv-main { min-width: 0; }
.mkt-qv-title { font-size: 22px; font-weight: 780; letter-spacing: -.02em; margin: 8px 0 6px; line-height: 1.2; }
.mkt-qv-desc { font-size: 14px; color: var(--muted); line-height: 1.6; }
.mkt-qv-facts { display: flex; flex-wrap: wrap; gap: 7px; margin: 15px 0 0; }
.mkt-fact { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; color: var(--muted); background: var(--chrome-3); border: 1px solid var(--border-soft); border-radius: 8px; padding: 5px 10px; }
.mkt-fact.mkt-diff::before { content: ""; }
.mkt-fact--ai { color: var(--d-violet); }
.mkt-qv-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.mkt-qv-tag { font-size: 11px; color: var(--muted); background: var(--chrome-3); border-radius: 6px; padding: 3px 9px; }
.mkt-qv-actions { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 20px; }
.mkt-btn { display: inline-flex; align-items: center; gap: 7px; font: inherit; font-size: 13px; font-weight: 650; cursor: pointer; color: var(--text); background: var(--chrome-3); border: 1px solid var(--border-soft); border-radius: 11px; padding: 10px 16px; transition: border-color .12s, filter .12s, transform .12s; }
.mkt-btn:hover { border-color: var(--accent); transform: translateY(-1px); }
.mkt-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }
.mkt-btn--primary { color: var(--on-accent); background: var(--accent); border-color: var(--accent); box-shadow: 0 8px 22px -10px var(--marigold); }
.mkt-btn--primary:hover { filter: brightness(1.05); }
.mkt-btn.qv-fav.is-on { color: var(--danger); border-color: var(--danger); }
.mkt-btn.qv-fav.is-on svg { fill: var(--danger); stroke: var(--danger); }
.mkt-qv-similar { grid-column: 1 / -1; margin-top: 22px; border-top: 1px solid var(--border); padding-top: 18px; }
.mkt-qv-similar h3 { font-size: 14px; font-weight: 700; margin-bottom: 12px; }
.mkt-qv-sim-rail { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.mkt-sim { display: flex; flex-direction: column; gap: 6px; text-align: left; cursor: pointer; background: var(--chrome); border: 1px solid var(--border-soft); border-radius: 11px; overflow: hidden; padding-bottom: 8px; transition: border-color .12s, transform .12s; }
.mkt-sim:hover { border-color: var(--accent); transform: translateY(-2px); }
.mkt-sim-thumb { aspect-ratio: 5 / 3; background: var(--canvas-bg); overflow: hidden; }
.mkt-sim-thumb svg { width: 100%; height: 100%; padding: 6px 9px; }
.mkt-sim-name { font-size: 11.5px; font-weight: 600; color: var(--text); line-height: 1.3; padding: 0 9px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* ---- Responsive ---- */
@media (max-width: 900px) {
  .mkt-collections { grid-template-columns: repeat(2, 1fr); }
  .mkt-qv-body { grid-template-columns: 1fr; }
  .mkt-qv-preview { max-height: 200px; }
  .mkt-qv-sim-rail { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .mkt-collections { grid-template-columns: 1fr; }
  .mkt-grid { grid-template-columns: 1fr; }
  .mkt-toolbar { flex-direction: column; align-items: stretch; }
  .mkt-count { align-self: flex-end; }
}
/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .mkt-card, .mkt-coll, .mkt-tab, .mkt-sugg, .mkt-continue, .mkt-mini, .mkt-btn, .mkt-sim, .mkt-fav,
  .mkt-thumb-hover, .mkt-thumb-hover button, .srch-hover, .srch-hover button, .mkt-qv, .mkt-qv-backdrop, .mkt-seeall span { transition: none; transform: none !important; }
}

.link-btn { color: inherit; font: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.link-btn:hover { color: var(--accent-ink); }
@media (prefers-reduced-motion: reduce) {
  .home-anim { animation: none; }
}

/* ============ Toasts ============ */
#toasts {
  position: fixed;
  /* CLEAR THE BOTTOM PLATE. Toasts used to sit at bottom:40px, which is
     inside the canvas dock's own footprint (bottom:14px + ~46px tall), so
     every message landed on the dock and was hard to read and to dismiss.
     --toast-lift is the height of whatever bottom furniture is showing;
     each mode below sets it, so a message always floats just above. */
  bottom: calc(var(--toast-lift, 40px) + 18px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 200;
  pointer-events: none;
}
/* Editor toasts ("Not saved yet…") are about the editor beneath the marketing
   overlays — don't let them float over the landing/explore pages. */
body:has(#homePage:not([hidden])) #toasts,
body:has(#explorePage:not([hidden])) #toasts { display: none; }
/* Bottom furniture, per mode:
   editor  — the canvas dock  (bottom 14 + 5*2 padding + 36 button = 60)
   present — the control bar  (bottom 16 + 8*2 padding + ~34 button = 66)
   neither — nothing to clear, so the toast keeps its own resting height. */
body { --toast-lift: 60px; }
body.presenting { --toast-lift: 72px; }
body.embed-mode, body.watching, body.recording,
body:has(#homePage:not([hidden])),
body:has(#explorePage:not([hidden])) { --toast-lift: 8px; }
@media (max-width: 760px) {
  /* 44px touch buttons + 10px padding, and the dock rides the safe-area. */
  body { --toast-lift: calc(64px + env(safe-area-inset-bottom, 0px)); }
}
/* Likewise the editor chrome itself: the overlays cover it visually, but
   without this it stays keyboard-focusable and screen-reader-visible
   beneath the marketing pages (WCAG 2.4.3/2.4.7). visibility also removes
   it from the tab order and accessibility tree. */
body:has(#homePage:not([hidden])) :is(#topbar, #main),
body:has(#explorePage:not([hidden])) :is(#topbar, #main) { visibility: hidden; }
.toast {
  background: #262b3d;
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 16px;
  border-radius: 10px;
  font-size: 12.5px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  animation: toast-in .18s ease-out;
}
.toast.out { opacity: 0; transition: opacity .3s; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* scrollbars that match the chrome */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(154, 161, 184, 0.28); border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background-color: rgba(154, 161, 184, 0.45); }
#canvasWrap::-webkit-scrollbar-thumb { background-color: rgba(20, 22, 31, 0.25); border: 3px solid transparent; background-clip: content-box; }

/* ============================================================
   Comment pane — shared annotation surface (every diagram type).
   #stage wraps #canvasWrap + the pane so the pane reserves real
   layout space (and never scrolls away with the diagram). Docks
   left / right (adjustable width) or bottom (adjustable height).
   ============================================================ */
#stage {
  flex: 1;
  min-width: 0;
  min-height: 0;
  position: relative;
  display: flex;
  flex-direction: row;
}
#stage.cp-bottom { flex-direction: column; }
#stage > #canvasWrap { flex: 1 1 auto; min-width: 0; min-height: 0; }

#commentPane {
  flex: none;
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--chrome);
  color: var(--text);
  overflow: hidden;
  z-index: 8;
}
#commentPane[hidden] { display: none; }
#stage.cp-left  #commentPane { order: -1; border-right: 1px solid var(--border); }
#stage.cp-right #commentPane { order: 1; border-left: 1px solid var(--border); }
#stage.cp-bottom #commentPane { order: 1; border-top: 1px solid var(--border); width: auto !important; }

#commentPaneResizer { position: absolute; z-index: 3; background: transparent; transition: background .12s; }
#stage.cp-right  #commentPaneResizer { left: 0; top: 0; bottom: 0; width: 7px; cursor: col-resize; }
#stage.cp-left   #commentPaneResizer { right: 0; top: 0; bottom: 0; width: 7px; cursor: col-resize; }
#stage.cp-bottom #commentPaneResizer { top: 0; left: 0; right: 0; height: 7px; cursor: row-resize; }
#commentPaneResizer:hover { background: var(--accent-soft); }

#commentPaneHead {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 12px; border-bottom: 1px solid var(--border); flex: none;
}
.cp-title { font-size: 13px; font-weight: 600; white-space: nowrap; }
.cp-head-actions { display: flex; align-items: center; gap: 6px; }
#cpPosition { padding: 2px; }
#cpPosition .seg-btn { flex: none; padding: 3px 7px; font-size: 13px; }
#cpAddNote.sm { padding: 4px 9px; font-size: 12px; }
.cp-icon-btn { padding: 4px 7px; border-radius: 6px; color: var(--muted); }
.cp-icon-btn:hover { background: var(--chrome-3); color: var(--text); }

#commentPaneBody { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 10px; }
#stage.cp-bottom #commentPaneBody { flex-direction: row; flex-wrap: wrap; align-items: flex-start; }

.cp-note {
  border: 1px solid var(--border); border-radius: 10px; background: var(--chrome-2);
  padding: 8px; display: flex; flex-direction: column; gap: 6px;
}
#stage.cp-bottom .cp-note { width: 240px; }
.cp-note.linking { box-shadow: 0 0 0 2px var(--accent-ring); border-color: var(--accent); }
.cp-note.active { border-color: var(--accent); }
.cp-note textarea {
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 46px;
  border: none; background: transparent; color: var(--text); font: inherit; font-size: 12.5px; outline: none;
}
.cp-note-foot { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cp-link-btn, .cp-del-btn {
  padding: 3px 8px; border-radius: 6px; font-size: 11.5px; color: var(--muted);
  border: 1px solid var(--border); background: var(--chrome);
}
.cp-link-btn:hover, .cp-del-btn:hover { color: var(--text); background: var(--chrome-3); }
.cp-link-btn.linked { color: var(--accent-ink); border-color: var(--accent-ring); }
.cp-linked-label { font-size: 11px; color: var(--muted); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-empty { color: var(--muted); font-size: 12px; padding: 14px; text-align: center; line-height: 1.5; }

/* Sized (width/height/viewBox) by JS each redraw to match #stage, so it needs
   only to be pinned at the stage origin — a percentage height here would
   collapse to 0 against the flex container and flatten the lines. */
#commentConnectors { position: absolute; top: 0; left: 0; pointer-events: none; overflow: visible; z-index: 7; }
#commentConnectors[hidden] { display: none; }
.cp-connector { stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 5 4; fill: none; opacity: .8; }
.cp-connector-dot { fill: var(--accent); }

/* While arming a shape link, the whole canvas reads as clickable. */
body.cp-linking #svgHost svg { cursor: crosshair; }

#stage:fullscreen { background-color: var(--canvas-bg); }

/* The comment pane is authoring chrome — keep it out of clean recordings. */
body.recording #commentPane, body.recording #commentConnectors { display: none !important; }

@media (max-width: 760px) { #commentPane { display: none; } }

/* ============================================================
   Threat model (STRIDE) — security-focused visuals for the
   threatmodel graph tool: threat badges, attack paths, the
   click-to-view popover and the inspector threat editor.
   ============================================================ */
.insp-subhead { font-size: 12px; font-weight: 700; color: var(--text); margin: 2px 0 8px; display: flex; align-items: center; gap: 6px; }
.tm-count-pill { background: var(--danger); color: #fff; font-size: 10px; font-weight: 700; border-radius: 9px; padding: 1px 7px; }

/* Attack-path "marching ants" — editor canvas only; exported SVG stays static. */
@keyframes tm-dash { to { stroke-dashoffset: -14; } }
#svgHost .tm-attack-path { animation: tm-dash .6s linear infinite; }
@media (prefers-reduced-motion: reduce) { #svgHost .tm-attack-path { animation: none; } }
#svgHost .tm-badge { cursor: pointer; }

/* Inspector: per-threat editor card */
.tm-threat-edit { border: 1px solid var(--border); border-left-width: 3px; border-radius: 8px; padding: 8px; margin-bottom: 8px; background: var(--chrome-2); display: flex; flex-direction: column; gap: 6px; }
.tm-te-row2 { display: flex; gap: 6px; }
.tm-te-row2 select { flex: 1; min-width: 0; }
.tm-threat-edit input, .tm-threat-edit textarea, .tm-threat-edit select {
  width: 100%; box-sizing: border-box; background: var(--chrome); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 7px; font: inherit; font-size: 12px; resize: vertical;
}
.tm-threat-edit .tm-te-del { color: var(--danger); }
.tm-attack-check input { accent-color: var(--danger); }

/* Click-to-view threat popover (appended to <body>, fixed position) */
.tm-threat-pop {
  position: fixed; z-index: 3000; width: 328px; max-width: calc(100vw - 24px); max-height: 72vh; overflow: auto;
  background: var(--chrome-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: 0 18px 48px rgba(0, 0, 0, .42); font: 13px/1.45 var(--font);
}
[data-ui-theme="light"] .tm-threat-pop { box-shadow: 0 18px 48px rgba(20, 24, 40, .2); }
.tm-pop-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--chrome-2); }
.tm-pop-title { font-weight: 700; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-pop-count { font-size: 11px; color: var(--muted); white-space: nowrap; }
.tm-pop-x { border: none; background: none; color: var(--muted); font-size: 20px; line-height: 1; cursor: pointer; padding: 0 2px; }
.tm-pop-x:hover { color: var(--text); }
.tm-pop-body { padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
.tm-threat-card { border: 1px solid var(--border); border-left-width: 4px; border-radius: 8px; padding: 8px 10px; background: var(--chrome); }
.tm-threat-top { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
.tm-stride-chip { color: #fff; font-weight: 700; font-size: 11px; width: 20px; height: 20px; border-radius: 5px; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.tm-threat-title { font-weight: 600; flex: 1; }
.tm-sev-chip { color: #fff; font-size: 10px; font-weight: 700; border-radius: 6px; padding: 2px 7px; text-transform: uppercase; letter-spacing: .03em; flex: none; }
.tm-threat-cat { font-size: 11px; color: var(--muted); margin-bottom: 6px; }
.tm-threat-row { display: grid; grid-template-columns: 74px 1fr; gap: 8px; font-size: 12px; margin-top: 4px; }
.tm-threat-row b { color: var(--muted); font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: .03em; padding-top: 1px; }

/* Contextual disclaimer for high-risk ready-made diagrams (js/engagement.js).
   Quiet line pinned to the stage foot, above the bottom band; dark-chrome ink
   like all Present furniture. Kept out of the tap lanes' way (pointer-events
   only on the link). */
body.presenting #prRiskNote { position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 4px; z-index: 40; max-width: min(92%, 720px); text-align: center;
  font-size: 11px; line-height: 1.4; color: rgba(233, 236, 248, .55);
  pointer-events: none; }
#prRiskNote { display: none; }
body.presenting #prRiskNote { display: block; }
#prRiskNote a { color: rgba(233, 236, 248, .75); pointer-events: auto; }

/* ============ Explore left sidebar (types + collections tile) ============ */
.mkt-body { display: flex; align-items: flex-start; gap: 24px; margin-top: 18px; }
/* Sticky filter rail — stays alongside the grid as you scroll; its own
   scrollbar appears only when the rail outgrows the viewport. */
.mkt-side { flex: 0 0 212px; align-self: flex-start;
  display: flex; flex-direction: column; gap: 14px;
  position: sticky; top: 76px; max-height: calc(100vh - 96px); overflow-y: auto;
  scrollbar-width: thin; }
.mkt-main { flex: 1; min-width: 0; }

/* Type nav — vertical list (was the horizontal .mkt-tabs strip) */
.mkt-side-tabs { display: flex; flex-direction: column; gap: 2px; }
.mkt-side-tabs .mkt-tab { width: 100%; justify-content: flex-start; border-radius: 9px; font-weight: 550; flex: none; }

/* Collections — expandable tile */
.mkt-coll-panel { border: 1px solid var(--border-soft); border-radius: 12px; overflow: hidden; background: var(--chrome-2); }
.mkt-coll-toggle { display: flex; align-items: center; justify-content: space-between; width: 100%; font: inherit;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
  cursor: pointer; background: none; border: none; padding: 12px 13px; }
.mkt-coll-toggle:hover { color: var(--text); }
.mkt-chev { transition: transform .18s ease; font-size: 11px; }
.mkt-coll-panel.is-collapsed .mkt-chev { transform: rotate(-90deg); }
.mkt-coll-list { display: flex; flex-direction: column; gap: 1px; padding: 0 6px 8px; max-height: 430px; overflow-y: auto; }
.mkt-coll-panel.is-collapsed .mkt-coll-list { display: none; }
.mkt-coll-empty { font-size: 12px; color: var(--faint); padding: 2px 8px 6px; }

/* Checkbox lists (Templates + Collections) — neutral rows, no colour fill; the
   only accent is the tick itself. Collapse with the panel toggle. */
.mkt-checklist { padding: 2px 6px 8px; max-height: 430px; overflow-y: auto; }
#exploreCatTabs.mkt-checklist { flex-direction: column; gap: 1px; }
.mkt-coll-panel.is-collapsed .mkt-side-tabs { display: none; }
.mkt-check-item { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; cursor: pointer;
  background: none; border: none; border-radius: 8px; padding: 7px 10px; color: var(--muted); font: inherit; font-size: 13px;
  transition: background .12s ease, color .12s ease; }
.mkt-check-item:hover { background: var(--chrome-3); color: var(--text); }
.mkt-check-item.active { color: var(--text); font-weight: 600; }
.mkt-check { position: relative; width: 16px; height: 16px; flex: none; border: 1.6px solid var(--border); border-radius: 5px;
  transition: background .12s ease, border-color .12s ease; }
.mkt-check-item:hover .mkt-check { border-color: var(--slate); }
.mkt-check-item.active .mkt-check { background: var(--accent); border-color: var(--accent); }
.mkt-check-item.active .mkt-check::after { content: ""; position: absolute; inset: 0; background: var(--on-accent);
  -webkit-mask: no-repeat center / 10px 10px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  mask: no-repeat center / 10px 10px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
.mkt-check-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mkt-check-count { flex: none; font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--faint); }

/* Collection row (overrides the old grid-card .mkt-coll) */
.mkt-coll { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; cursor: pointer;
  background: none; border: none; border-radius: 8px; padding: 7px 8px; transition: background .12s; }
.mkt-coll:hover { background: var(--chrome-3); transform: none; box-shadow: none; border-color: transparent; }
.mkt-coll.is-active { background: var(--accent-soft); }
.mkt-coll-ico { width: 26px; height: 26px; flex: none; display: grid; place-items: center; font-size: 14px; border-radius: 7px;
  background: color-mix(in srgb, var(--coll) 18%, transparent); border: 1px solid color-mix(in srgb, var(--coll) 34%, transparent); }
.mkt-coll-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mkt-coll-count { flex: none; font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--faint); }

@media (max-width: 860px) {
  .mkt-body { flex-direction: column; }
  .mkt-side { flex: none; width: 100%; position: static; max-height: none; overflow: visible; flex-direction: row; flex-wrap: wrap; }
  .mkt-side-tabs { flex-direction: row; flex-wrap: wrap; flex: 1 1 100%; }
  .mkt-side-tabs .mkt-tab { width: auto; }
  .mkt-coll-panel { flex: 1 1 100%; }
  .mkt-coll-list { max-height: 260px; }
}

/* ---- Sidebar "Filters" tile (Industry, Role, quick toggles) ---- */
.mkt-coll-panel.is-collapsed .mkt-side-body { display: none; }
.mkt-side-body { display: flex; flex-direction: column; gap: 11px; padding: 4px 11px 13px; }
.mkt-field { display: flex; flex-direction: column; gap: 5px; }
.mkt-field-lab { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); }
.mkt-select--block { width: 100%; }
.mkt-side-toggles { display: flex; flex-wrap: wrap; gap: 6px; }
.mkt-side-toggles .mkt-toggle { padding: 6px 11px; font-size: 12px; }
.mkt-side-body .mkt-clear { align-self: flex-start; padding: 4px 2px; }
/* Top bar is now just Sort + count — keep it tidy. */
.mkt-toolbar { margin-top: 2px; }

/* Sidebar is a flex column with max-height; keep children at natural height
   (don't let flex shrink them, which clipped the panel bodies). */
.mkt-side > * { flex: 0 0 auto; }

/* ============================================================
   Present mode: Stagecraft II — pre-show settings, karaoke subtitles,
   live presentation recording, and the brand mark on every slide.
   (js/present-plus.js drives all of it.)
   ============================================================ */

/* ---- Intro card brand mark. Same lockup as the end slide. ---- */
.pr-intro-mark { width: 46px; height: 46px; margin: 0 auto 2px; color: #cdd5e4; }
.pr-intro-mark svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* ---- Opening brand animation ------------------------------------------
   Deliberately playful and over-eager: the mark bounces in with squash and
   stretch, the accent dot arcs around and lands with a wobble, sparkles pop,
   and the wordmark springs up letter by letter with real overshoot. Every
   animation is gated on `.pr-brandin-run`, which present-plus re-applies each
   time the intro opens — CSS animations fire once per element, so without
   that a second show would display a finished logo and no motion. */
.pr-brandin {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.pr-brandin .pr-intro-mark { width: 74px; height: 74px; margin: 0; }
.pr-brandin-glow {
  /* The purple bloom that used to sit behind the brand animation. Removed on
     request: the splash reads as a clean sheet now, and a violet radial behind
     the mark read as a smudge on the light theme's white card. The element
     stays in the DOM (the animation choreography references it) but paints
     nothing. */
  display: none;
}
/* Nothing moves until the run class lands. */
.pr-brandin-run .pr-brandin-glow { animation: prBiGlow 2.2s cubic-bezier(.22,.9,.28,1) forwards; }
.pr-brandin-run .pr-intro-mark { animation: prBiDrop 1.05s cubic-bezier(.28,1.5,.42,1) forwards; }
.pr-brandin .pr-intro-mark { opacity: 0; }

.pr-bi-stem { stroke-dasharray: 56; stroke-dashoffset: 56; }
.pr-bi-bowl { stroke-dasharray: 172; stroke-dashoffset: 172; }
.pr-brandin-run .pr-bi-stem { animation: prBiDraw .46s cubic-bezier(.65,0,.35,1) .34s forwards; }
.pr-brandin-run .pr-bi-bowl { animation: prBiDraw .7s cubic-bezier(.65,0,.35,1) .5s forwards; }
.pr-bi-node { opacity: 0; transform-box: fill-box; transform-origin: center; }
.pr-brandin-run .pr-bi-node { animation: prBiPop .5s cubic-bezier(.34,1.8,.5,1) forwards; }
.pr-brandin-run .pr-bi-node-a { animation-delay: .74s; }
.pr-brandin-run .pr-bi-node-b { animation-delay: .84s; }
/* The accent dot is the brand's one moving part — it gets the biggest arc. */
.pr-bi-orbit { opacity: 0; transform-box: fill-box; transform-origin: center; }
.pr-brandin-run .pr-bi-orbit { animation: prBiOrbit 1.1s cubic-bezier(.3,1.7,.45,1) .92s forwards; }

.pr-brandin-word {
  position: relative;
  display: flex;
  font-family: 'Diagramium Wordmark', var(--sans);
  font-weight: 700;
  font-size: 31px;
  letter-spacing: -0.02em;
  color: #fff;
  line-height: 1.15;
  padding: 0 2px;
}
.pr-bi-l {
  display: inline-block;
  opacity: 0;
  transform: translateY(120%) scale(.5) rotate(-12deg);
  transform-origin: 50% 100%;
}
.pr-brandin-run .pr-bi-l { animation: prBiLetter .78s cubic-bezier(.28,1.7,.42,1) forwards; }
.pr-bi-l.um { color: var(--iris-bright); }
/* 46ms apart: enough to read as a run of letters, tight enough to stay one move. */
.pr-brandin-run .pr-bi-l:nth-child(1) { animation-delay: 1.12s; }
.pr-brandin-run .pr-bi-l:nth-child(2) { animation-delay: 1.166s; }
.pr-brandin-run .pr-bi-l:nth-child(3) { animation-delay: 1.212s; }
.pr-brandin-run .pr-bi-l:nth-child(4) { animation-delay: 1.258s; }
.pr-brandin-run .pr-bi-l:nth-child(5) { animation-delay: 1.304s; }
.pr-brandin-run .pr-bi-l:nth-child(6) { animation-delay: 1.35s; }
.pr-brandin-run .pr-bi-l:nth-child(7) { animation-delay: 1.396s; }
.pr-brandin-run .pr-bi-l:nth-child(8) { animation-delay: 1.442s; }
.pr-brandin-run .pr-bi-l:nth-child(9) { animation-delay: 1.488s; }
.pr-brandin-run .pr-bi-l:nth-child(10) { animation-delay: 1.534s; }
.pr-brandin-sheen {
  position: absolute;
  inset: 0 auto 0 -60%;
  width: 55%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.85), transparent);
  transform: skewX(-18deg);
  opacity: 0;
  pointer-events: none;
}
.pr-brandin-run .pr-brandin-sheen { animation: prBiSheen 1s cubic-bezier(.4,0,.2,1) 1.95s forwards; }
/* Sparkles: four dots that burst outward as the mark lands. */
.pr-bi-spark {
  position: absolute;
  top: 26px;
  left: 50%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  background: var(--iris-bright);
}
.pr-bi-spark:nth-of-type(2) { background: #ffd166; }
.pr-bi-spark:nth-of-type(3) { background: #46d4ff; }
.pr-bi-spark:nth-of-type(4) { background: #ff8fd0; }
.pr-brandin-run .pr-bi-spark { animation: prBiSpark .9s cubic-bezier(.2,.9,.3,1) forwards; }
.pr-brandin-run .pr-bi-spark:nth-of-type(1) { animation-delay: .74s; --sx: -66px; --sy: -30px; }
.pr-brandin-run .pr-bi-spark:nth-of-type(2) { animation-delay: .8s;  --sx: 62px;  --sy: -38px; }
.pr-brandin-run .pr-bi-spark:nth-of-type(3) { animation-delay: .86s; --sx: -48px; --sy: 30px; }
.pr-brandin-run .pr-bi-spark:nth-of-type(4) { animation-delay: .92s; --sx: 54px;  --sy: 26px; }

@keyframes prBiGlow {
  0% { opacity: 0; transform: translateX(-50%) scale(.5); }
  34% { opacity: 1; transform: translateX(-50%) scale(1.12); }
  100% { opacity: .55; transform: translateX(-50%) scale(1); }
}
/* Drop, squash on impact, rebound — the classic bounce, on the whole mark. */
@keyframes prBiDrop {
  0% { opacity: 0; transform: translateY(-90px) scale(.4) rotate(-16deg); }
  45% { opacity: 1; transform: translateY(6px) scale(1.18, .84) rotate(4deg); }
  62% { transform: translateY(-10px) scale(.94, 1.1) rotate(-2deg); }
  80% { transform: translateY(3px) scale(1.05, .96); }
  100% { opacity: 1; transform: none; }
}
@keyframes prBiDraw { to { stroke-dashoffset: 0; } }
@keyframes prBiPop {
  0% { opacity: 0; transform: scale(.15); }
  65% { opacity: 1; transform: scale(1.45); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes prBiOrbit {
  0% { opacity: 0; transform: translate(-40px, -30px) scale(.2) rotate(-90deg); }
  50% { opacity: 1; transform: translate(8px, 6px) scale(1.5) rotate(10deg); }
  72% { transform: translate(-3px, -2px) scale(.88); }
  100% { opacity: 1; transform: none; }
}
@keyframes prBiLetter {
  0% { opacity: 0; transform: translateY(120%) scale(.5) rotate(-12deg); }
  55% { opacity: 1; transform: translateY(-14%) scale(1.16) rotate(3deg); }
  78% { transform: translateY(4%) scale(.96) rotate(-1deg); }
  100% { opacity: 1; transform: none; }
}
@keyframes prBiSheen {
  0% { opacity: 0; left: -60%; }
  20% { opacity: 1; }
  100% { opacity: 0; left: 115%; }
}
@keyframes prBiSpark {
  0% { opacity: 0; transform: translate(-50%, 0) scale(.2); }
  30% { opacity: 1; transform: translate(calc(-50% + var(--sx) * .55), calc(var(--sy) * .55)) scale(1.3); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--sx)), var(--sy)) scale(.3); }
}
/* ---- The same lockup on the presentation's title card ----------------
   The intro's performance in full — identical durations, delays and easing,
   so the start slide and the intro screen read as one animation. It runs
   ~2.95s, and app.js / present-plus hold the card for at least BRANDIN_MS
   (see maybeShowTitleCard / recShowStartSlide) so nothing is cut off. The
   shared .pr-bi-* classes do the drawing; these rules only re-scope the
   glow, the sparkle spread and the wordmark to the card's own layout. */
#prTitleCard .pr-bi-spark {
  position: absolute;
  top: 34%;
  left: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  background: var(--iris-bright);
}
#prTitleCard .pr-bi-spark:nth-of-type(2) { background: #ffd166; }
#prTitleCard .pr-bi-spark:nth-of-type(3) { background: #46d4ff; }
#prTitleCard .pr-bi-spark:nth-of-type(4) { background: #ff8fd0; }
#prTitleCard #prTitleCardMark { opacity: 0; }
#prTitleCard #prTitleCardBrand .pr-bi-l {
  display: inline-block;
  opacity: 0;
  transform: translateY(120%) scale(.5) rotate(-12deg);
  transform-origin: 50% 100%;
}
/* Armed by app.js (Present) and present-plus (recording) each time the card
   is shown — CSS animations fire once per element, so the run class has to be
   removed and re-added or a second show would display a finished logo. */
#prTitleCard.pr-brandin-run #prTitleCardMark { animation: prBiDrop 1.05s cubic-bezier(.28,1.5,.42,1) forwards; }
#prTitleCard.pr-brandin-run .pr-bi-stem { animation: prBiDraw .46s cubic-bezier(.65,0,.35,1) .34s forwards; }
#prTitleCard.pr-brandin-run .pr-bi-bowl { animation: prBiDraw .7s cubic-bezier(.65,0,.35,1) .5s forwards; }
#prTitleCard.pr-brandin-run .pr-bi-node { animation: prBiPop .5s cubic-bezier(.34,1.8,.5,1) forwards; }
#prTitleCard.pr-brandin-run .pr-bi-node-a { animation-delay: .74s; }
#prTitleCard.pr-brandin-run .pr-bi-node-b { animation-delay: .84s; }
#prTitleCard.pr-brandin-run .pr-bi-orbit { animation: prBiOrbit 1.1s cubic-bezier(.3,1.7,.45,1) .92s forwards; }
#prTitleCard.pr-brandin-run .pr-bi-spark { animation: prBiSpark .9s cubic-bezier(.2,.9,.3,1) forwards; }
#prTitleCard.pr-brandin-run .pr-bi-spark:nth-of-type(1) { animation-delay: .74s; --sx: -84px; --sy: -34px; }
#prTitleCard.pr-brandin-run .pr-bi-spark:nth-of-type(2) { animation-delay: .8s;  --sx: 80px;  --sy: -44px; }
#prTitleCard.pr-brandin-run .pr-bi-spark:nth-of-type(3) { animation-delay: .86s; --sx: -62px; --sy: 34px; }
#prTitleCard.pr-brandin-run .pr-bi-spark:nth-of-type(4) { animation-delay: .92s; --sx: 70px;  --sy: 30px; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l { animation: prBiLetter .78s cubic-bezier(.28,1.7,.42,1) forwards; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(1) { animation-delay: 1.12s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(2) { animation-delay: 1.166s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(3) { animation-delay: 1.212s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(4) { animation-delay: 1.258s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(5) { animation-delay: 1.304s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(6) { animation-delay: 1.35s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(7) { animation-delay: 1.396s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(8) { animation-delay: 1.442s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(9) { animation-delay: 1.488s; }
#prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l:nth-child(10) { animation-delay: 1.534s; }
/* Glow behind the mark and the sheen across the wordmark — the two pieces the
   card used to go without. Positioned against the card, which fills the stage,
   so the glow sits over the mark rather than the card's centre. */
#prTitleCard .pr-brandin-glow { display: none; }
#prTitleCard.pr-brandin-run .pr-brandin-glow { animation: prBiGlow 2.2s cubic-bezier(.22,.9,.28,1) forwards; }
#prTitleCardBrand { position: relative; }
#prTitleCard.pr-brandin-run .pr-brandin-sheen { animation: prBiSheen 1s cubic-bezier(.4,0,.2,1) 1.95s forwards; }

/* Reduced motion: the finished composition, arrived at rather than performed. */
@media (prefers-reduced-motion: reduce) {
  .pr-brandin-run .pr-brandin-glow { animation: none; opacity: .55; transform: translateX(-50%) scale(1); }
  .pr-brandin .pr-intro-mark, .pr-brandin-run .pr-intro-mark { animation: none; opacity: 1; transform: none; }
  .pr-bi-stem, .pr-bi-bowl { stroke-dashoffset: 0; }
  .pr-brandin-run .pr-bi-stem, .pr-brandin-run .pr-bi-bowl { animation: none; }
  .pr-brandin-run .pr-bi-node, .pr-brandin-run .pr-bi-orbit,
  .pr-brandin-run .pr-bi-l { animation: none; opacity: 1; transform: none; }
  .pr-brandin-run .pr-brandin-sheen, .pr-brandin-run .pr-bi-spark { animation: none; opacity: 0; }
  #prTitleCard #prTitleCardMark,
  #prTitleCard.pr-brandin-run #prTitleCardMark { animation: none; opacity: 1; transform: none; }
  #prTitleCard.pr-brandin-run .pr-bi-stem, #prTitleCard.pr-brandin-run .pr-bi-bowl { animation: none; }
  #prTitleCard.pr-brandin-run .pr-bi-node, #prTitleCard.pr-brandin-run .pr-bi-orbit { animation: none; opacity: 1; transform: none; }
  #prTitleCard #prTitleCardBrand .pr-bi-l,
  #prTitleCard.pr-brandin-run #prTitleCardBrand .pr-bi-l { animation: none; opacity: 1; transform: none; }
  #prTitleCard.pr-brandin-run .pr-bi-spark { animation: none; opacity: 0; }
  /* The id-scoped glow/sheen rules above out-specify the generic resets. */
  #prTitleCard.pr-brandin-run .pr-brandin-glow { animation: none; opacity: .55; transform: translateX(-50%) scale(1); }
  #prTitleCard.pr-brandin-run .pr-brandin-sheen { animation: none; opacity: 0; }
}

/* ---- Settings opened from the intro: same popover, centered as a modal
   above the intro overlay (.pr-pop is z-9, #prIntro z-8, so it wins).
   prPopIn fills forwards with its own transform, so the centered variant
   needs its own keyframes or the fill would pin it to translateX only. ---- */
.pr-pop.pr-centered {
  bottom: auto; top: 50%;
  transform: translate(-50%, -50%);
  max-height: min(78vh, 640px);
  animation-name: prPopInCenter;
}
@keyframes prPopInCenter {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 10px)); }
  to { opacity: 1; transform: translate(-50%, -50%); }
}
body.pr-idle .pr-pop.pr-centered { transform: translate(-50%, -50%); }

/* ---- Karaoke subtitles: every word is a span; the highlight sweeps
   word-by-word with the voice, like a progress bar made of words. Two layers
   of "liquid": the strip itself carries a soft accent wash whose right edge
   is --kfill (stamped by karaokeMark at the end of the word being spoken),
   and the current word fills with a gradient pill before settling into
   crisp white. background-image rides OVER the pill's base background:
   the shorthand in the base rule would wipe it, longhands here win. ---- */
#prSubtitle {
  background-image: linear-gradient(90deg,
    color-mix(in srgb, var(--iris) 30%, transparent),
    color-mix(in srgb, var(--iris-bright) 14%, transparent));
  background-repeat: no-repeat;
  background-size: calc(var(--kfill, 0) * 100%) 100%;
  transition: background-size .3s linear;
}
#prSubtitle .kw { color: rgba(255, 255, 255, 0.72); transition: color .18s ease; border-radius: 5px; }
#prSubtitle .kw.said { color: #ffffff; }
#prSubtitle .kw.now {
  color: #ffffff;
  background-image: linear-gradient(90deg, var(--iris), color-mix(in srgb, var(--iris-bright) 80%, #fff 20%));
  background-repeat: no-repeat;
  background-size: 0% 100%;
  animation: kwLiquid .34s ease-out forwards;
  box-shadow: 0 0 0 4px var(--iris), 0 2px 14px color-mix(in srgb, var(--iris) 55%, transparent);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.35);
}
@keyframes kwLiquid { to { background-size: 100% 100%; } }
@media (prefers-reduced-motion: reduce) {
  #prSubtitle { transition: none; }
  #prSubtitle .kw.now, #prNarrationText.karaoke .kw.now { animation: none; background-size: 100% 100%; }
}

/* ---- Title card (recording start slide + watch mode): branded. ---- */
#prTitleCardMark { width: 54px; height: 54px; margin-bottom: 4px; opacity: 1; }
#prTitleCardMark svg { width: 100%; height: 100%; display: block; }
#prTitleCardBrand {
  margin-top: 14px; font-family: var(--sans); font-weight: 700; font-size: 15px;
  letter-spacing: -0.03em; opacity: .82;
}
#prTitleCardBrand .um { color: var(--iris-bright); }

/* ---- "Record presentation" option — the headline act of the popover. ---- */
.pr-rec-opt.pr-rec-live { border-color: color-mix(in srgb, #f0546a 45%, transparent); }
.pr-rec-opt.pr-rec-live b { display: flex; align-items: center; gap: 7px; }
.pr-rec-dot-inline {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: #f0546a; box-shadow: 0 0 8px rgba(240, 84, 106, 0.9);
  animation: prRecPulse 1.4s ease-in-out infinite;
}
@keyframes prRecPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ---- Recording HUD: 3-2-1 countdown (before capture starts), then a
   short-lived REC pill that fades itself out of the recording. ---- */
#prRecHud { position: absolute; inset: 0; z-index: 11; pointer-events: none; }
#prRecCount {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  font-family: var(--sans); font-weight: 800; font-size: clamp(72px, 14vw, 150px);
  color: #ffffff; text-shadow: 0 12px 60px rgba(0, 0, 0, .55);
}
#prRecCount.tick { animation: prCountTick .92s var(--ease-out) both; }
@keyframes prCountTick {
  from { opacity: 0; transform: translate(-50%, -50%) scale(1.35); }
  25% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  85% { opacity: 1; }
  to { opacity: 0; transform: translate(-50%, -50%) scale(.92); }
}

/* ---- While recording (body.pr-rec): the tab IS the video. Editor chrome
   goes away entirely (the extra .watching class hides topbar/palette/side);
   the control bar, popovers and toasts must never appear in the file. The
   progress bar, captions, subtitles, presenter and brand mark stay — they
   are the presentation. ---- */
body.pr-rec #presentBar, body.pr-rec .pr-pop, body.pr-rec #toasts { display: none !important; }
body.pr-rec #prEnd .pr-end-ctas, body.pr-rec #prEnd .pr-end-share { display: none; }
body.pr-rec #prIntro { display: none; }
body.pr-rec #canvasWrap, body.pr-rec #canvasWrap * { cursor: default; }
/* The FILE is 16:9, whatever shape the window is: the stage letterboxes to
   the largest 16:9 box the window offers, and the tab capture is cropped to
   #stage — so the box IS the frame. Fixed-positioning frees it from the app
   column (the box must be measured against the window alone; fixed boxes are
   also immune to ancestor overflow) and the body paints the bars. Everything
   Present draws lives inside #stage by contract, so nothing is lost off the
   edges; fitPresent/layoutPresentChrome re-measure on the class toggle, the
   same machinery as a window resize. */
body.pr-rec #stage {
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(100vw, calc(100vh * 16 / 9));
  height: min(100vh, calc(100vw * 9 / 16));
}
body.pr-rec { background: #000; }
/* PORTRAIT SHOW (Theme → Screen → Portrait 9:16): the stage becomes the
   largest 9:16 box the window offers — the recorder's own letterbox move,
   turned on its side — so a phone-shaped show can be rehearsed, captured and
   exported on a laptop. Everything Present draws lives inside #stage by
   contract, so nothing is lost. Placed AFTER the recorder rule so a portrait
   take records 9:16 too. */
body.pr-portrait #stage {
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(100vw, calc(100vh * 9 / 16));
  height: min(100vh, calc(100vw * 16 / 9));
}
body.pr-portrait { background: #000; }
/* The drawing book's boards fill the portrait stage edge to edge, and the
   contents sheet stacks its list over the picture. */
/* `.presenting` is in these selectors on purpose: the base drawbook board
   rules (further down the file) are body.presenting.pr-chrome-drawbook …,
   and a portrait rule of EQUAL specificity written earlier loses to them —
   measured as the contents sheet staying a 16:9 strip with a scrollbar in
   the middle of the tall stage. The full-height board is what lets the
   contents list run its full length. */
body.presenting.pr-portrait.pr-chrome-drawbook #prIntro .pr-intro-card,
body.presenting.pr-portrait.pr-chrome-drawbook #prIntro.pr-drawbook-indexing .pr-intro-card,
body.presenting.pr-portrait.pr-chrome-drawbook #prEnd .pr-end-card {
  aspect-ratio: auto;
  width: 100%;
  height: 100%;
  max-height: none;
  max-width: none;
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-draw-index-body {
  grid-template-columns: 1fr;
  align-items: start;
  align-content: start;
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-draw-index-list {
  font-size: clamp(15px, 2.6vh, 22px);
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-draw-index-list li {
  padding: clamp(8px, 1.3vh, 14px) 0;
}
body.presenting.pr-portrait.pr-chrome-drawbook #prDrawIndexTitle {
  font-size: clamp(24px, 4.2vh, 40px);
}
/* The closing board on a phone: the three colophon panels become three
   full-width ROWS (label left, its line right) instead of three squeezed
   columns clipping their own labels ("SUBSCRI"), and the heading sizes from
   the frame's height so "Thank you" stays on one line. */
body.presenting.pr-portrait.pr-chrome-drawbook #prEnd h2 {
  font-size: clamp(30px, 5.6vh, 54px) !important;
  line-height: 1.05;
}
/* The landscape board's wide side padding (~24% of a 405px stage, measured
   96px a side) left the content a 213px column; a phone board uses a trim. */
body.presenting.pr-portrait.pr-chrome-drawbook #prEnd .pr-end-card {
  padding: 6vh 7% 5vh;
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-book-close-action-row {
  grid-template-columns: 1fr;
  gap: 10px;
}
body.presenting.pr-portrait.pr-chrome-drawbook #prEnd .pr-book-close-action-row :is(a, button) {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 0;
  padding: 12px 16px !important;
  text-align: left;
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-book-close-action-row b {
  flex: 0 0 auto;
  font-size: clamp(12px, 1.7vh, 15px);
}
body.presenting.pr-portrait.pr-chrome-drawbook .pr-book-close-action-row span {
  flex: 1 1 auto;
  text-align: right;
  font-size: clamp(12px, 1.7vh, 15px);
}
/* The narrow board wraps its control rows instead of clipping them. */
body.presenting.pr-portrait #prIntro .pr-intro-row,
body.presenting.pr-portrait #prIntro .pr-intro-meta,
body.presenting.pr-portrait #prEnd .pr-end-ctas,
body.presenting.pr-portrait.pr-chrome-drawbook #prEnd .pr-end-ctas {
  flex-wrap: wrap;
  justify-content: center;
  max-width: 100%;
  row-gap: 8px;
}

/* ============================================================
   Landing v2 — "The page is the canvas."
   The home overlay is styled as one continuous Diagramium canvas: the
   editor's dot grid runs behind everything, sections are labeled frames
   (mono scene tags), and every feature is explained by a live diagram of
   itself. Hover language borrows the product's own selection UI. One
   signature moment per section; calm at rest.
   Motion primitives (used everywhere, nothing else):
     RISE  — opacity+translateY entrance (.home-anim / .sr, scroll-fx.js)
     INK   — SVG strokes draw in via stroke-dashoffset
     POP   — nodes scale .92→1 on --ease-spring
   Scoped to #homePage (plus the shared .lp-top header, also used by
   #explorePage and mirrored in the generated pages/(generated).html).
   ============================================================ */

/* ---- Shared header (home + explore) — 60px glass bar. On the home overlay
   the hairline + glass appear only after a little scroll (js/landing.js
   toggles .is-scrolled); on explore it is always on. ---- */
.lp-top {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 62;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  background: var(--glass-bg);
  border-bottom: 1px solid var(--border);
}
#homePage .lp-top {
  background: transparent;
  border-bottom-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  transition: background var(--dur-3) var(--ease-out), border-color var(--dur-3) var(--ease-out);
}
#homePage .lp-top.is-scrolled {
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  background: var(--glass-bg);
  border-bottom-color: var(--border);
}
.lp-top-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 60px;
  max-width: none;
  margin: 0 auto;
  padding: 0 clamp(18px, 4vw, 64px);
}
.lp-brandline { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.lp-brandline .lock-icon { width: 30px; height: 30px; color: var(--slate); display: inline-flex; }
.lp-brandline .lock-icon svg { width: 30px; height: 30px; display: block; }
/* The wordmark is the brand (Outfit, operator Sep 27 2026) — sized to read as
   a logo on the site headers, not as a nav label. The editor toolbar keeps its
   own compact .brand size. */
.lp-brandline .wordmark { font-size: 27px; }
.lp-brandline .lock-icon, .lp-brandline .lock-icon svg { width: 34px; height: 34px; }
@media (max-width: 760px) {
  .lp-brandline .wordmark { font-size: 23px; }
  .lp-brandline .lock-icon, .lp-brandline .lock-icon svg { width: 30px; height: 30px; }
}
.wordmark { font-family: 'Diagramium Wordmark', var(--sans); font-weight: 700; font-size: 21px; letter-spacing: -0.02em; color: var(--wordmark); }
.wordmark .um { color: var(--mark); }
/* Brand name in running text: the "ium" suffix always carries the accent. */
.um { color: var(--accent); }
.dbrand { font-family: 'Diagramium Wordmark', var(--sans); font-weight: 700; letter-spacing: -0.01em; }
.lp-toolbar { display: flex; align-items: center; gap: 8px; position: relative; min-width: 0; }
.pillnav { display: none; gap: 2px; margin-right: 6px; }
.lp-mobile-menu-btn { display: inline-flex; justify-content: center; min-width: 74px; }
@media (min-width: 1080px) {
  .pillnav { display: flex; }
  .lp-mobile-menu-btn { display: none !important; }
}
.pillnav a,
.pillnav-action {
  font-size: 14px; color: var(--muted); text-decoration: none;
  padding: 7px 12px; border-radius: 8px; font-weight: 480; cursor: pointer;
  white-space: nowrap;   /* "Visual Learning" is two words; a pill never wraps */
  transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.pillnav-action {
  display: none;
  width: 100%; border: 0; background: transparent; font-family: inherit;
  text-align: left;
}
.pillnav a:hover,
.pillnav-action:hover { color: var(--text); background: var(--accent-soft); }
@media (max-width: 1079px) {
  .pillnav {
    display: none;
    position: absolute;
    z-index: 80;
    top: calc(100% + 12px);
    right: 0;
    width: min(290px, calc(100vw - 24px));
    max-height: min(70vh, 520px);
    overflow: auto;
    padding: 8px;
    margin: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: color-mix(in srgb, var(--chrome) 96%, transparent);
    box-shadow: 0 20px 54px rgba(4,7,18,.24), 0 2px 10px rgba(4,7,18,.12);
    backdrop-filter: blur(18px) saturate(1.08);
  }
  .pillnav.is-open { display: flex; }
  .pillnav a,
  .pillnav-action {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 10px 13px;
    border-radius: 11px;
    font-size: 14px;
  }
  .pillnav a[aria-current="page"] { color: var(--text); background: var(--panel-2); }
  .lp-toolbar > .accent-btn,
  .lp-toolbar > .theme-toggle-btn,
  #odOpenBtnTop { display: none !important; }
}
@media (max-width: 520px) {
  .lp-top-inner { padding-inline: 10px; gap: 8px; }
  .lp-toolbar { gap: 5px; }
  .lp-brandline { gap: 7px; }
  .lp-brandline .beta-badge { display: none; }
  .lp-mobile-menu-btn { min-width: 66px; padding-inline: 9px; }
  .lp-toolbar > .lp-tbtn-cta { padding-inline: 10px; }
  #btnExploreClearCache,
  #btnHomeClearCache { display: none !important; }
}
/* Below 430 every remaining control earns its keep at icon-or-tight size, so
   "Open editor" stays on screen — measured: at 390 the bar ran to 418px and
   the primary CTA was simply unreachable. Nothing is removed: the Menu button
   keeps its accessible name, only its printed word goes. */
@media (max-width: 430px) {
  .lp-toolbar { gap: 4px; }
  /* `.lp-toolbar .lp-tbtn` (0,2,0), not a bare `.lp-tbtn` (0,1,0): this block
     sits BEFORE the ≤600 one, every ≤430 viewport also matches ≤600, and at
     equal specificity the later rule wins — so the bare selector was dead and
     the measured 390px squeeze never actually applied. */
  .lp-toolbar .lp-tbtn { padding: 7px 9px; font-size: 12px; min-height: 40px; }
  .lp-mobile-menu-btn { min-width: 0; }
  .lp-mobile-menu-btn span:not([aria-hidden]) { display: none; }
  .lp-toolbar > .lp-tbtn-cta { padding-inline: 9px; }
}
@media (max-width: 360px) {
  .lp-brandline .wordmark { display: none; }
}
.lp-tbtn {
  font: inherit; font-size: 13px; font-weight: 560; color: var(--text); cursor: pointer;
  background: transparent; border: 1px solid var(--border); border-radius: 9px;
  padding: 8px 13px; display: inline-flex; align-items: center; gap: 7px;
  text-decoration: none;
  /* Chrome buttons never wrap their own label: a two-line "Sign in" reads as a
     broken control, and it was happening at every width up to desktop. */
  white-space: nowrap; flex: none;
  transition: border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.lp-tbtn:hover { border-color: var(--slate-2); background: var(--accent-soft); }
.lp-tbtn:focus-visible, .pillnav a:focus-visible, .pillnav-action:focus-visible,
.lp-mobile-menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lp-tbtn .glyph { font-family: var(--mono); font-size: 13px; line-height: 1; display: inline-flex; }
.lp-tbtn-icon { padding: 8px 9px; }
/* The one primary action in the bar reads as filled, everything else stays
   quiet — the outline treatment made "Open editor" one chip among six. */
.lp-tbtn-cta {
  border-color: transparent; background: var(--accent); color: var(--on-accent); font-weight: 600;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .16) inset, 0 6px 16px -8px var(--accent);
}
.lp-tbtn-cta:hover { border-color: transparent; background: var(--accent); filter: brightness(1.07); transform: translateY(-1px); }

/* ---- The canvas ground: dot grid + one soft iris wash. ---- */
#homePage::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(900px 520px at 72% 6%, color-mix(in srgb, var(--iris) 7%, transparent), transparent 70%),
    radial-gradient(circle, var(--dot) 1px, transparent 1.2px);
  background-size: auto, 24px 24px;
}
[data-ui-theme="light"] #homePage::before {
  background-image:
    radial-gradient(900px 520px at 72% 6%, color-mix(in srgb, var(--iris) 9%, transparent), transparent 70%),
    radial-gradient(circle, color-mix(in srgb, var(--slate) 26%, transparent) 1px, transparent 1.2px);
}
#homePage .home-inner {
  position: relative; z-index: 1;
  max-width: none; width: 100%;
  margin: 0;
  padding: 60px clamp(18px, 4vw, 64px) 0;
  text-align: left;
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
}

/* ---- Scene tags: every section is a labeled frame on the canvas.
   Drawn as a NODE on an EDGE — a port dot, the label, then a hairline rail
   running out to the margin — so the scenes read as steps of one diagram
   rather than isolated captions. Decorative only (aria-hidden in markup). ---- */
.lp-scene-tag {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
  color: var(--faint); margin-bottom: 18px; user-select: none;
}
.lp-scene-tag::before {
  content: ""; width: 7px; height: 7px; flex: none; border-radius: 2px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 70%, transparent);
  background: var(--accent-soft);
}
.lp-scene-tag::after {
  content: ""; flex: 1 1 auto; height: 1px;
  background: linear-gradient(90deg, var(--border), transparent);
}

/* ---- Section rhythm + masthead. ---- */
#homePage .lp-section { position: relative; width: 100%; padding: clamp(72px, 9vw, 122px) 0 0; }
.lp-sec-head { margin-bottom: 34px; }
.lp-kicker {
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-ink); font-weight: 600;
}
#homePage .lp-section h2 {
  font-size: clamp(30px, 3.8vw, 46px); font-weight: 620; letter-spacing: -0.025em;
  line-height: 1.08; margin: 12px 0 0; text-wrap: balance; max-width: 22ch;
}
#homePage .lp-section .lp-sub {
  color: var(--muted); max-width: 58ch; margin-top: 14px;
  font-size: 16.5px; line-height: 1.6; font-weight: 430;
}

/* ============ Hero — Script & Stage ============ */
.lp-hero {
  display: grid; grid-template-columns: 1fr; gap: 48px; align-items: center;
  width: 100%; padding: clamp(56px, 9vh, 104px) 0 clamp(40px, 6vh, 72px);
}
/* ---- Editor links: the row between the menu and the hero. A mono
   "Editors" label, then the nine editors as plain text links separated by
   hairline dividers. Scrolls sideways on narrow screens (the page body
   must never scroll horizontally). ---- */
.lp-editors {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 0 0; min-width: 0;
}
.lp-editors-label {
  flex: none;
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint); font-weight: 600;
}
.lp-editors-links {
  display: flex; align-items: center; min-width: 0;
  overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.lp-editors-links::-webkit-scrollbar { display: none; }
.lp-editors-links a {
  flex: none; position: relative;
  font-size: 13.5px; font-weight: 500; color: var(--muted); text-decoration: none;
  padding: 6px 10px; border-radius: 7px; white-space: nowrap;
  transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.lp-editors-links a + a::before {
  content: ""; position: absolute; left: -1px; top: 50%;
  width: 1px; height: 14px; transform: translateY(-50%);
  background: var(--border-soft);
}
.lp-editors-links a:hover { color: var(--text); background: var(--accent-soft); }
.lp-editors-links a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lp-editors-all { color: var(--accent-ink) !important; font-weight: 650 !important; }
/* The strip takes part of the hero's top padding, so the headline does not
   drop further down the first screen than it did before. */
.lp-editors + .lp-hero { padding-top: clamp(32px, 6vh, 72px); }
@media (max-width: 760px) {
  .lp-editors { gap: 10px; padding-top: 10px; }
  .lp-editors-links a { font-size: 13px; padding: 6px 8px; }
}
@media (min-width: 980px) { .lp-hero { grid-template-columns: 0.92fr 1.08fr; gap: clamp(40px, 4.5vw, 72px); } }
.lp-eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); font-weight: 560;
}
.lp-eyebrow-dot { width: 8px; height: 8px; background: var(--accent); border-radius: 2px; flex: none; }
/* Sized so the second line ("explain themselves.") holds ONE line on a
   desktop column: at the old 76px cap the phrase broke in two and the
   headline spent three lines — half the first viewport — saying it. */
#homePage .home-hero {
  font-size: clamp(38px, 4.8vw, 64px); font-weight: 640; letter-spacing: -0.033em;
  line-height: 1.04; margin: 20px 0 0; color: var(--text); text-wrap: balance;
}
.lp-warm {
  /* Ends bright on purpose: the old run finished on base iris, which sat at
     low contrast against the near-black ground and read as the DIM half of
     the headline. Both stops stay in the brand ramp. */
  background: linear-gradient(92deg, var(--iris-bright), var(--d-violet) 55%, var(--iris-bright));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  background-size: 200% 100%;
  animation: lp-ink-fill 900ms var(--ease-out) both;
}
@keyframes lp-ink-fill { from { background-position: 120% 0; opacity: .25; } to { background-position: 0% 0; opacity: 1; } }
#homePage .lp-hero .home-hero-sub {
  color: var(--muted); font-size: 17.5px; line-height: 1.62; font-weight: 430;
  margin: 22px 0 0; max-width: 46ch; text-align: left;
}
#homePage .lp-hero .home-hero-sub strong { color: var(--text); font-weight: 600; }
.lp-cta { display: flex; gap: 12px; margin-top: 32px; flex-wrap: wrap; align-items: center; }
.lp-btn {
  font-family: var(--font); font-weight: 570; font-size: 15px; border-radius: 11px;
  padding: 13px 22px; cursor: pointer; border: 1px solid transparent;
  text-decoration: none; display: inline-flex; align-items: center; gap: 9px;
  transition: transform var(--dur-1) var(--ease-out), filter var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out),
    background var(--dur-1) var(--ease-out);
}
.lp-btn:active { transform: translateY(0) scale(.985); }
.lp-btn-primary {
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .18) inset, 0 10px 26px -12px var(--accent);
}
.lp-btn-primary:hover {
  transform: translateY(-1px); filter: brightness(1.07);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .18) inset, 0 14px 32px -12px var(--accent);
}
.lp-btn-arrow { font-weight: 400; transition: transform var(--dur-2) var(--ease-out); }
.lp-btn:hover .lp-btn-arrow { transform: translateX(3px); }
.lp-btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.lp-btn-ghost:hover { border-color: var(--slate-2); background: var(--accent-soft); }
.lp-btn-lg { font-size: 16px; padding: 15px 28px; }
.lp-hero-fine {
  margin-top: 22px; font-family: var(--mono); font-size: 12.5px; color: var(--faint);
  letter-spacing: .01em;
}

/* The stage: a canvas frame housing the live editor + diagram. */
.lp-stage {
  position: relative; display: flex; flex-direction: column;
  border: 1px solid color-mix(in srgb, var(--iris) 28%, var(--edge));
  border-radius: var(--r-4);
  /* Nearly solid panel + light blur: the 78%-translucent glass and the 80px
     iris glow made the demo read as decoration; a crisp sheet reads as the
     product. */
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-lg), 0 1px 0 rgba(255, 255, 255, .05) inset;
  overflow: hidden;
}
.lp-stage-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-soft);
}
.lp-stage-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); opacity: .8; flex: none; }
.lp-stage-file { font-family: var(--mono); font-size: 11.5px; color: var(--faint); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lp-stage-live { font-family: var(--mono); font-size: 11px; color: var(--d-green); animation: lp-live-in var(--dur-3) var(--ease-out) both; }
[data-ui-theme="light"] .lp-stage-live { color: #0a7d5c; }
@keyframes lp-live-in { from { opacity: 0; } to { opacity: 1; } }
.lp-stage-present {
  font: inherit; font-size: 12.5px; font-weight: 620; color: var(--on-accent);
  background: var(--accent); border: none; border-radius: 999px; padding: 6px 14px;
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px; flex: none;
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--accent) 60%, transparent);
  transition: transform var(--dur-1) var(--ease-spring), filter var(--dur-1) var(--ease-out);
}
.lp-stage-present:hover { filter: brightness(1.08); transform: scale(1.04); }
.lp-stage-present:active { transform: scale(.96); }
.lp-stage-present span { font-size: 10px; }
.lp-stage-panes { display: grid; grid-template-columns: 1fr; }
@media (min-width: 640px) { .lp-stage-panes { grid-template-columns: 236px 1fr; } }
@media (min-width: 1100px) { .lp-stage-panes { grid-template-columns: 290px 1fr; } }
/* Grid/flex children may not force the column wider than the viewport. */
.lp-stage-panes > *, .lp-hero > *, .lp-who > * { min-width: 0; }
.lp-stage-script { position: relative; border-bottom: 1px solid var(--border-soft); }
@media (min-width: 640px) { .lp-stage-script { border-bottom: none; border-right: 1px solid var(--border-soft); } }
.lp-stage-script textarea {
  display: block; width: 100%; height: 100%; min-height: 148px; resize: none;
  background: transparent; border: none; outline: none;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.75; color: var(--ink-2);
  padding: 14px 16px; caret-color: var(--accent);
}
.lp-stage-script textarea:focus { color: var(--text); }
.lp-stage-script:focus-within { box-shadow: 0 0 0 2px var(--accent-ring) inset; border-radius: 4px; }
.lp-stage-script textarea::selection { background: var(--accent-soft); }
.lp-stage-ghost {
  position: absolute; left: 16px; bottom: 10px; pointer-events: none;
  font-family: var(--mono); font-size: 10.5px; color: var(--faint);
}
.lp-stage-canvas {
  position: relative; min-height: 230px; display: flex; align-items: center; justify-content: center;
  background-image: radial-gradient(circle, var(--dot) 1px, transparent 1.2px);
  background-size: 20px 20px;
  padding: 10px 12px;
}
.lp-stage-canvas svg { width: 100%; height: auto; max-height: 300px; display: block; }
.hero-actor-name { fill: var(--text); font-size: 13px; font-weight: 600; font-family: var(--font); }
.hero-lifeline { stroke: var(--faint); stroke-width: 1; stroke-dasharray: 4 4; opacity: .55; }
.hero-msg-text { fill: var(--ink-2); font-size: 11.5px; font-family: var(--mono); }
.hero-note rect { fill: var(--accent-soft); stroke: color-mix(in srgb, var(--accent) 45%, transparent); stroke-width: 1.2; }
.hero-note-text { fill: var(--ink-2); font-size: 11px; font-family: var(--mono); }
.hero-empty-hint { fill: var(--faint); font-size: 13px; font-family: var(--mono); }
/* INK entrance: each .hstep fades/rises in at its --hd delay when .hero-anim runs. */
.hero-anim .hstep { opacity: 0; transform: translateY(5px); animation: hero-step-in .42s var(--ease-out) var(--hd, 0s) forwards; }
@keyframes hero-step-in { to { opacity: 1; transform: none; } }
.hero-new { animation: hero-step-in .42s var(--ease-out) both; }
.hero-hidden { opacity: 0; }
.hero-revealed { opacity: 1; transition: opacity .3s var(--ease-out); }
.lp-stage-progress {
  height: 3px; overflow: hidden;
  /* Step ticks on the track: playback advances through STEPS, and the rail
     should say so — the same sequencing language Present uses. */
  background:
    repeating-linear-gradient(90deg, transparent 0 calc(12.5% - 3px), var(--chrome) calc(12.5% - 3px) 12.5%),
    var(--border-soft);
}
/* Light theme needs a deeper track, or the paper-coloured ticks vanish into
   it (#f5f6fa on #e8eaf4 measured ~1.05:1 — no visible ticks at all). */
[data-ui-theme="light"] .lp-stage-progress {
  background:
    repeating-linear-gradient(90deg, transparent 0 calc(12.5% - 3px), var(--chrome) calc(12.5% - 3px) 12.5%),
    color-mix(in srgb, var(--slate-2) 45%, var(--border-soft));
}
.lp-stage-progress span { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 2px; }
.lp-stage-caption {
  padding: 9px 14px; font-family: var(--mono); font-size: 11px; color: var(--faint);
  border-top: 1px solid var(--border-soft);
}

/* ============ Proof strip — the editor's status bar, telling the truth. ============ */
.lp-proof {
  display: grid; grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--border); border-radius: var(--r-3);
  background: color-mix(in srgb, var(--panel) 62%, transparent);
  margin-top: clamp(40px, 6vh, 64px);
  overflow: hidden;
}
@media (min-width: 720px) { .lp-proof { grid-template-columns: repeat(5, auto); justify-content: space-between; } }
.lp-proof-cell {
  display: flex; flex-direction: column; gap: 4px;
  padding: 20px clamp(18px, 2.6vw, 34px);
  border-top: 1px solid var(--border-soft);
}
.lp-proof-cell:nth-child(-n+2) { border-top: none; }
@media (min-width: 720px) { .lp-proof-cell { border-top: none; } }
@media (max-width: 719.98px) { .lp-proof-cell-wide { grid-column: 1 / -1; } }
.lp-proof-num {
  font-size: 27px; font-weight: 640; letter-spacing: -0.02em; color: var(--text);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.lp-proof-formats { font-size: 16px; font-family: var(--mono); font-weight: 560; letter-spacing: 0; padding-top: 7px; }
.lp-proof-label { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); }

/* ============ Templates — command bar + spreadsheet grid + selection hover. ============ */
/* Spreadsheet grid: tiles share hairlines via 1px gaps over the border color. */
.lp-discover-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  background: var(--border-soft);
  border: 1px solid var(--border-soft); border-radius: var(--r-4);
  overflow: hidden;
}
@media (min-width: 760px) { .lp-discover-grid { grid-template-columns: repeat(auto-fill, minmax(265px, 1fr)); } }
.lp-tpl-card {
  position: relative; display: flex; flex-direction: column; text-align: left; cursor: pointer;
  background: var(--chrome); text-decoration: none; color: inherit;
  transition: background var(--dur-2) var(--ease-out);
}
.lp-tpl-card:hover { background: var(--panel); }
.lp-tpl-thumb { position: relative; aspect-ratio: 16/10; overflow: hidden; }
.lp-tpl-thumb svg { width: 100%; height: 100%; display: block; padding: 12px 16px; transition: transform var(--dur-3) var(--ease-out); }
.lp-tpl-card:hover .lp-tpl-thumb svg { transform: scale(1.04); }
.lp-tpl-body { display: flex; flex-direction: column; gap: 3px; padding: 12px 15px 15px; border-top: 1px solid var(--border-soft); }
.lp-tpl-name { font-size: 14px; font-weight: 570; letter-spacing: -0.01em; color: var(--text); }
.lp-tpl-kind { font-family: var(--mono); font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); }
/* The product's selection UI on hover: bounding box + 8 handles. */
.lp-tpl-card::before {
  content: ""; position: absolute; inset: 7px; z-index: 2; pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--iris) 65%, transparent);
  border-radius: 4px; opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.lp-tpl-card::after {
  content: ""; position: absolute; inset: 4px; z-index: 2; pointer-events: none; opacity: 0;
  background-image:
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px),
    radial-gradient(circle, var(--iris) 0 2.6px, transparent 2.6px);
  background-position: 0 0, 50% 0, 100% 0, 0 50%, 100% 50%, 0 100%, 50% 100%, 100% 100%;
  background-size: 7px 7px; background-repeat: no-repeat;
  transition: opacity var(--dur-1) var(--ease-out);
}
.lp-tpl-card:hover::before, .lp-tpl-card:hover::after,
.lp-tpl-card:focus-visible::before, .lp-tpl-card:focus-visible::after { opacity: 1; }
.lp-discover-more { margin-top: 26px; }

/* ============ The specimen — 26 diagram types. ============ */
#homePage .home-cards {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;
  width: 100%; margin-top: 34px;
}
@media (min-width: 640px) { #homePage .home-cards { grid-template-columns: repeat(auto-fill, minmax(205px, 1fr)); } }
#homePage .home-card {
  position: relative; display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--panel) 72%, transparent);
  border: 1px solid var(--border); border-radius: var(--r-3);
  overflow: hidden; text-decoration: none; color: inherit;
  transition: border-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
#homePage .home-card:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--iris) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
#homePage .hc-preview {
  display: flex; align-items: center; justify-content: center;
  padding: 16px 14px 12px;
  border-bottom: 1px solid var(--border-soft);
}
#homePage .hc-preview svg { width: 100%; height: auto; max-height: 84px; transition: transform var(--dur-3) var(--ease-out); }
#homePage .home-card:hover .hc-preview svg { transform: scale(1.05); }
/* Keyboard gets the same lift the pointer gets. */
#homePage .home-card:focus-visible {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--iris) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
.who-card:focus-visible {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--tint) 55%, var(--border));
}
.lp-tpl-card:focus-visible { background: var(--panel); }
#homePage .hc-name {
  padding: 10px 14px 5px; font-weight: 570; font-size: 13.5px; letter-spacing: -0.01em;
  text-align: left; line-height: 1.3; color: var(--text);
  display: flex; align-items: center; gap: 6px;
}
#homePage .hc-name::after {
  content: "→"; font-weight: 400; color: var(--accent-ink); opacity: 0;
  transform: translateX(-4px); transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
#homePage .home-card:hover .hc-name::after { opacity: 1; transform: none; }
#homePage .hc-continue {
  padding: 0 14px 10px; font-size: 11px; font-weight: 500; color: var(--accent-ink);
  min-height: 14px; font-family: var(--mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}


/* ============ Local-first — the quiet scene. ============ */
.lp-quiet { text-align: center; display: flex; flex-direction: column; align-items: center; }
.lp-quiet .lp-scene-tag { align-self: flex-start; }
.lp-quiet-note { margin-top: 22px; font-size: 13.5px; color: var(--faint); }
.lp-quiet-note .link-btn { color: var(--muted); }
.lp-quiet-note .link-btn:hover { color: var(--accent-ink); }

/* ============ FAQ — native details, hairline rows. ============ */
.lp-faq { max-width: none; display: flex; flex-direction: column; }
.lp-faq-item { border-top: 1px solid var(--border-soft); }
.lp-faq-item:last-child { border-bottom: 1px solid var(--border-soft); }
.lp-faq-item summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 18px;
  font-size: 16.5px; font-weight: 560; letter-spacing: -0.01em; color: var(--text);
  padding: 19px 2px;
  transition: color var(--dur-1) var(--ease-out);
}
.lp-faq-item summary::-webkit-details-marker { display: none; }
.lp-faq-item summary:hover { color: var(--accent-ink); }
.lp-faq-plus { position: relative; width: 14px; height: 14px; flex: none; }
.lp-faq-plus::before, .lp-faq-plus::after {
  content: ""; position: absolute; background: var(--faint); border-radius: 1px;
  transition: transform var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.lp-faq-plus::before { left: 6px; top: 0; width: 2px; height: 14px; }
.lp-faq-plus::after { left: 0; top: 6px; width: 14px; height: 2px; }
.lp-faq-item[open] .lp-faq-plus { transform: rotate(45deg); }
.lp-faq-plus { transition: transform var(--dur-2) var(--ease-out); }
.lp-faq-a { overflow: hidden; }
.lp-faq-a p { font-size: 14.5px; line-height: 1.65; color: var(--muted); max-width: 62ch; padding: 0 2px 20px; }
@supports (interpolate-size: allow-keywords) {
  .lp-faq-item::details-content {
    block-size: 0; overflow-y: clip;
    transition: content-visibility var(--dur-3) allow-discrete, block-size var(--dur-3) var(--ease-out);
  }
  .lp-faq-item[open]::details-content { block-size: auto; }
}

/* ============ Finale. ============ */
.lp-finale { padding: clamp(88px, 12vw, 150px) 0 clamp(64px, 8vw, 110px); text-align: center; }
.lp-finale-title {
  font-size: clamp(34px, 4.8vw, 60px); font-weight: 640; letter-spacing: -0.03em;
  display: flex; align-items: center; justify-content: center; gap: clamp(10px, 1.6vw, 20px);
  flex-wrap: wrap;
}
.lp-cta-center { justify-content: center; margin-top: 38px; }

/* ============ Footer. ============ */
.lp-foot { position: relative; width: 100%; margin-top: clamp(40px, 6vw, 80px); padding: 0 0 34px; }
/* Comfortable touch targets for the link columns on coarse pointers. */
@media (max-width: 760px) {
  .lp-foot-col { gap: 4px; }
  .lp-foot-col a, .lp-foot-col .link-btn { padding-block: 8px; }
}
.lp-foot::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 100vw; border-top: 1px solid var(--border); pointer-events: none;
}
.lp-foot-grid {
  display: grid; grid-template-columns: 1fr; gap: 34px;
  padding: 44px 0 38px;
}
@media (min-width: 760px) { .lp-foot-grid { grid-template-columns: 1.4fr 1.1fr 1fr 1fr 1fr 1fr; gap: 20px; } }
.lp-foot-brandcol { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.lp-foot-mark { width: 34px; height: 34px; color: var(--slate); display: inline-flex; }
.lp-foot-mark svg { width: 34px; height: 34px; display: block; }
.lp-foot-tag { color: var(--muted); font-size: 14px; line-height: 1.5; max-width: 30ch; }
/* The footer carries the SAME lockup as the header (mark + Outfit wordmark),
   one size down, with the tagline under it — not the name set in body text. */
.lp-foot-lockup { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.lp-foot-lockup .wordmark { font-size: 24px; }
.lp-foot-lockup .lp-foot-mark, .lp-foot-lockup .lp-foot-mark svg { width: 32px; height: 32px; }
.lp-foot-col { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.lp-foot-h { font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); font-weight: 600; margin-bottom: 4px; }
.lp-foot-col a, .lp-foot-col .link-btn {
  font-size: 13.5px; color: var(--muted); text-decoration: none; cursor: pointer;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-size: 0% 1px; background-position: 0 100%;
  padding-bottom: 2px;
  transition: color var(--dur-1) var(--ease-out), background-size var(--dur-2) var(--ease-out);
}
.lp-foot-col a:hover, .lp-foot-col .link-btn:hover { color: var(--text); background-size: 100% 1px; }
.lp-foot-col .link-btn { text-decoration: none; }
.lp-foot-base {
  display: flex; align-items: center; justify-content: space-between; gap: 14px 24px; flex-wrap: wrap;
  border-top: 1px solid var(--border-soft); padding-top: 22px;
}
.lp-foot-mono { font-family: var(--mono); font-size: 12px; color: var(--faint); }
/* The maker's credit is its OWN LINE, sitting under the Diagramium lockup.
   It used to be spliced into the middle of the base bar's mono sentence —
   "A product of [logo] DhuRee Labs Inc. · Local-first & private · 2026" — which
   read as a run-on and, at 475px + 382px of links against a 743px bar, wrapped
   into two ragged left-aligned rows while `justify-content: space-between`
   flung them to opposite edges at every width just above the wrap point. One
   short mono line plus one link cluster fits, so the base bar is stable again.
   `width: 100%` is what forces its own row inside the two ROW-flex footers
   (explore + search); in the landing footer's column-flex brand block it is a
   harmless full-width stretch. */
/* Social row — one markup on every footer (index's three + every generated
   page). Colours are INHERITED with opacity, deliberately token-free: the
   footers already set their own ink, and an invented token fails silently to
   its fallback in one theme (CLAUDE.md). */
.lp-foot-social { display: flex; align-items: center; gap: 14px; margin-top: 10px; width: 100%; }
.lp-foot-social a { display: inline-flex; align-items: center; gap: 7px; color: inherit; opacity: .72; font-size: 12.5px; text-decoration: none; }
.lp-foot-social a:hover { opacity: 1; text-decoration: none; }
.lp-foot-social svg { width: 15px; height: 15px; fill: currentColor; flex: none; }

.lp-foot-maker-row {
  width: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: 0 5px;
  font-family: var(--mono); font-size: 12px; color: var(--faint);
}
/* The maker's credit, linked out to DhuRee Labs. The mark is INLINE SVG rather
   than a file for the same reason the Diagramium mark is: the app has to keep
   working offline and inside a single-file export, and a <img src> would be a
   broken box in both. Opens in a new tab — the visitor is mid-task in an
   editor, and navigating the whole page away from unsaved work is hostile. */
.lp-foot-maker { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); text-decoration: none; border-radius: 6px; padding: 2px 4px; margin: 0 -2px; transition: color .14s ease, background .14s ease; }
.lp-foot-maker:hover, .lp-foot-maker:focus-visible { color: var(--text); background: var(--panel-2); }
/* The mark's 64-unit box carries built-in padding (the ink spans roughly
   9..54), so it needs to sit a shade larger than the 12px text beside it to
   read as the same optical weight. Sizing BOTH axes explicitly matters: the
   source file ships width="64" height="64", and an SVG that escapes its CSS
   falls back to those — a 64px logo in a 12px footer row, which is what
   "broken, too big" looks like. */
.lp-foot-maker .dl-mark { width: 16px; height: 16px; display: block; flex: none; }
/* Ink follows the surrounding text, which is already theme-aware — this is
   what the two source files (light/dark) encode by hand. */
.lp-foot-maker .dl-ink { fill: currentColor; }
/* The accent is a real brand value, not a theme colour. Both source variants
   are kept: #f0562b on dark, #e04e1e on light. */
.lp-foot-maker .dl-accent { fill: #f0562b; }
:root[data-ui-theme="light"] .lp-foot-maker .dl-accent { fill: #e04e1e; }
.lp-foot-maker .ext { width: 10px; height: 10px; display: block; flex: none; opacity: .55; }
/* Wraps: this row is the ONE thing that pushed the page wider than a phone —
   382px of nowrap links overflowed a 390px viewport by exactly its padding. */
.lp-foot-links { font-family: var(--mono); font-size: 12px; color: var(--faint); display: inline-flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; }
.lp-foot-links .link-btn { font-family: var(--mono); font-size: 12px; color: var(--faint); background: none; border: none; cursor: pointer; padding: 0; text-decoration: none; }
.lp-foot-links .link-btn:hover { color: var(--accent-ink); }
/* Explore page still uses the simple footer lockup. */
#explorePage .lp-foot { margin-top: 32px; padding: 34px 0 8px; display: flex; align-items: center; justify-content: space-between; gap: 18px 24px; flex-wrap: wrap; }
/* wrap:wrap is what lets .lp-foot-maker-row's width:100% drop to its own line
   under the mark + tagline rather than squeezing in beside them. */
#explorePage .lp-foot-brand { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
#explorePage .lp-foot-meta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* ============ Landing reduced-motion + small screens. ============ */
@media (prefers-reduced-motion: reduce) {
  .home-anim { animation: none; }
  .lp-warm { animation: none; background-position: 0 0; }
  .hero-anim .hstep, .hero-new { animation: none; opacity: 1; transform: none; }
  .lp-cast-animated .lp-cast-line { animation: none; }
  .sr .lq-step, .sr .lq-cloud, .sr .lq-stamp { opacity: 1; transform: none; }
  .sr .lq-edge { stroke-dasharray: none; stroke-dashoffset: 0; }
  .lp-finale-play:hover::after { animation: none; }
  .lp-tpl-thumb svg, .hc-preview svg, .who-banner img { transition: none; }
  #homePage .home-card, .who-card, .lp-sample, .lp-btn, .lp-tbtn, .lp-coll { transition-duration: 0s; }
}
@media (max-width: 600px) {
  .lp-top-inner { padding: 0 14px; }
  /* 42px minimum hit height inside the 60px bar — comfortable thumb targets
     without growing the header. */
  .lp-tbtn { padding: 8px 10px; font-size: 12.5px; min-height: 42px; }
  .lp-brandline { gap: 8px; }
}
/* Last squeeze before 360: everything shaves a little so the primary CTA
   never leaves the screen. Sits AFTER the 600px block on purpose — same
   specificity, so source order is what decides. */
@media (max-width: 380px) {
  .lp-tbtn { font-size: 11.5px; padding: 7px 7px; gap: 5px; }
  .lp-toolbar { gap: 3px; }
  .lp-toolbar > .lp-tbtn-cta { padding-inline: 8px; }
  .lp-top-inner { padding-inline: 8px; }
}
@media (max-width: 430px) {
  .lp-brandline .wordmark { display: none; }
}
@media (max-width: 520px) {
  .lp-proof-cell { padding: 14px 16px; }
  .lp-proof-num { font-size: 21px; }
  .lp-proof-num.lp-proof-formats { font-size: 14px; }
  .lp-stage-script textarea { min-height: 116px; }
  .lp-search-go { display: none; }
  .lp-search-kbd { display: none; }
}
/* Coarse-pointer comfort: collection chips reach ~44px targets. */
@media (max-width: 760px) {
  .lp-coll { padding: 10px 15px; }
}

/* ---- Topbar document menu (New / File / Templates) --------------------
   Folds the document actions behind one trigger so the right-hand controls,
   Export especially, survive a narrow window. Panel sits above the canvas and
   well below modals (3000). */
.tb-menu { position: relative; display: inline-flex; }
.tb-menu-caret { font-size: 10px; opacity: .7; margin-left: 1px; }
.tb-menu-trigger[aria-expanded="true"] { background: var(--chrome-3); }
.tb-menu-panel {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 200;
  min-width: 172px; padding: 6px;
  background: var(--chrome-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 2px;
}
.tb-menu-panel[hidden] { display: none; }
.tb-menu-item {
  appearance: none; background: transparent; border: 0;
  color: var(--text); font: inherit; font-size: 13px; text-align: left;
  padding: 8px 10px; border-radius: 7px; cursor: pointer; white-space: nowrap;
  /* Icon + label on one baseline. The gap is what stops three words in a
     column reading as a list of nothing in particular. */
  display: flex; align-items: center; gap: 9px;
}
.tb-mi-ico { width: 16px; height: 16px; flex: none; color: var(--muted); }
.tb-menu-item:hover .tb-mi-ico { color: #ffffff; }
.tb-menu-item:hover { background: rgba(255, 255, 255, 0.09); }
.tb-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The title is the one elastic thing in a bar of fixed-width buttons, so it is
   what gives when the window narrows. Its WIDTHS now live with the island
   rules (`#topbar #docTitle`, which outranks these one-class media rules) —
   the old clamps here were dead and are gone rather than left to mislead.
   These blocks keep the other things that yield. */
@media (max-width: 980px) {
  #toolChip { display: none; }
}
@media (max-width: 820px) {
  .brand .wordmark { display: none; }
}

/* Below the width where the islands stop fitting, secondary buttons keep
   their icon and drop their word. (Zoom moved to the canvas dock and Help to
   the overflow menu, so neither needs hiding here any more.) */
@media (max-width: 1024px) {
  /* Between the phone squeeze and full desktop the islands are at their
     tightest: labels go, and the optional chrome (tool chip, autosave) with
     them, so the title never has to push a primary control off the bar. */
  #topbar .tb-btn > .tb-lbl { display: none; }
  #topbar #autoSaveWrap { display: none; }
  #topbar #docTitle { max-width: 190px; }
}

/* ---- Present frame guide (js/present-guide.js) ------------------------------
   A dashed box at the aspect Present and the animated exports fit into, drawn
   around the drawing so the empty screen is visible while authoring rather than
   discovered mid-presentation. Pure overlay: no pointer events, never printed,
   never exported, and hidden the moment the show starts. */
#pgFrame {
  position: absolute;
  pointer-events: none;
  z-index: 3;
  border: 1.5px dashed var(--accent-ring, rgba(139, 92, 246, 0.55));
  border-radius: 4px;
  box-shadow: 0 0 0 100vmax rgba(10, 12, 20, 0.035);   /* dims the wasted area */
}
#pgBadge {
  position: absolute;
  left: 0; bottom: 100%; margin-bottom: 6px;
  max-width: 100%;
  padding: 4px 9px;
  border-radius: 7px;
  font: 500 11.5px/1.45 var(--sans, -apple-system, sans-serif);
  white-space: normal;
  background: var(--chrome-3, #1a1d27);
  border: 1px solid var(--border, #2a2f3d);
  color: var(--muted, #8b93a7);
}
#pgBadge.good { color: #34d399; border-color: rgba(52, 211, 153, 0.45); }
#pgBadge.warn { color: #f59e0b; border-color: rgba(245, 158, 11, 0.45); }
#pgBadge.bad  { color: #f87171; border-color: rgba(248, 113, 113, 0.45); }
/* The guide is an authoring aid — the audience must never see it. */
body.presenting #pgFrame, body.recording #pgFrame { display: none !important; }
#btnPresentGuide[aria-pressed="true"] { color: var(--accent-ink, #a78bfa); }

/* ---- The Present button ---------------------------------------------------
   The one action the whole product is named for, so it stops looking like the
   twelve neutral toolbar buttons beside it and reads as the primary thing to
   press. A filled iris pill with a glass hexagon glyph: the same shape family
   as the brand mark, so it belongs to Diagramium rather than to a UI kit.

   It overrides .tb-btn deliberately — that class supplies the toolbar's quiet
   ghost treatment, which is exactly what this button must NOT have. */
.btn-present, #btnPresent.btn-present {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px 6px 10px;
  border-radius: 10px;
  color: var(--on-accent);       /* follows the signal: dark label on the white Studio accent */
  font-weight: 650;
  letter-spacing: -0.01em;
  background: linear-gradient(150deg, var(--iris-bright) 0%, var(--iris) 48%, var(--iris-deep) 100%);
  /* Two shadows doing different jobs: a coloured glow that lifts the pill off
     the chrome, and an inset top highlight that gives the surface a curve
     instead of a flat fill. */
  box-shadow: 0 3px 12px -3px color-mix(in srgb, var(--iris) 70%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, 0.28);
  transition: transform .14s cubic-bezier(.2,.8,.3,1), box-shadow .18s, filter .18s;
}
.btn-present:hover:not(:disabled), #btnPresent.btn-present:hover:not(:disabled) {
  /* The monochrome accent is WHITE: hover must keep the dark label and step
     slightly DARKER — `color:#fff` + brightness() here washed the whole
     button to a blank white pill. */
  background: linear-gradient(150deg, #ffffff 0%, #ececec 60%, #dddddd 100%);
  color: var(--on-accent);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px -4px rgba(0, 0, 0, 0.5),
              inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.btn-present:active:not(:disabled), #btnPresent.btn-present:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: 0 2px 8px -3px color-mix(in srgb, var(--iris) 70%, transparent),
              inset 0 2px 5px rgba(0, 0, 0, 0.22);
}
.btn-present:focus-visible, #btnPresent.btn-present:focus-visible {
  outline: 2px solid var(--iris-bright);
  outline-offset: 2px;
}
.btn-present:disabled, #btnPresent.btn-present:disabled { opacity: .45; box-shadow: none; transform: none; }

/* The glyph: a translucent hexagon with a solid play head, so it reads as one
   layered object rather than two stacked icons. */
.btn-present .bp-glyph { width: 17px; height: 17px; flex: none; overflow: visible; }
.btn-present .bp-hex   { fill: rgba(15, 15, 15, 0.22); }
.btn-present .bp-play  { fill: var(--on-accent); }
.btn-present .bp-label { line-height: 1.2; }
/* A slow breath on the hexagon — enough to catch the eye on an idle canvas,
   far too slow to nag. Stops entirely on hover so it never fights a click. */
@media (prefers-reduced-motion: no-preference) {
  .btn-present .bp-hex { animation: bpBreath 3.6s ease-in-out infinite; transform-origin: 12px 12px; }
  .btn-present:hover .bp-hex { animation: none; fill: rgba(15, 15, 15, 0.32); }
}
@keyframes bpBreath {
  0%, 100% { fill: rgba(255, 255, 255, 0.30); transform: scale(1); }
  50%      { fill: rgba(255, 255, 255, 0.46); transform: scale(1.06); }
}

/* The hero's copy of the button sits on a light stage bar rather than the dark
   toolbar, and carries more weight there — so it keeps the same identity at a
   slightly larger scale. `.lp-stage-present span { font-size: 10px }` used to
   shrink the old "▶" glyph; the label must not inherit that. */
.lp-stage-present.btn-present { font-size: 12.5px; padding: 7px 16px 7px 11px; border-radius: 11px; }
.lp-stage-present.btn-present .bp-glyph { width: 18px; height: 18px; }
.lp-stage-present.btn-present .bp-label { font-size: 12.5px; }

/* ---- "Present" written inline in prose -------------------------------------
   The copy refers to the feature by name a dozen times, and it was spelled with
   a bare "▶" — a glyph that renders differently on every platform and reads as
   a stray arrowhead rather than the product's headline action. This is the
   button's identity shrunk to fit a line of text: same gradient, same hexagon,
   no interaction, because it is a NOUN in a sentence and not something to
   click. Baseline-aligned so it never pushes the line height around. */
.bp-inline {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  vertical-align: baseline;
  padding: 1px 8px 2px 6px;
  margin: 0 1px;
  border-radius: 7px;
  background: linear-gradient(150deg, var(--iris-bright) 0%, var(--iris) 55%, var(--iris-deep) 100%);
  color: #fff;
  font-weight: 640;
  font-size: 0.92em;      /* relative: it has to sit in headlines and body text alike */
  line-height: 1.35;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.26);
}
.bp-inline svg { width: 1em; height: 1em; flex: none; }
.bp-inline .bp-hex  { fill: rgba(255, 255, 255, 0.36); }
.bp-inline .bp-play { fill: #fff; }

/* ---- Step-0 sheet title (js/present-plus.js syncSheetTitle) ----------------
   The opening slide, drawn on the white tile itself. Everything here is inked
   for paper: near-black text, quiet bordered chips, and a PLAIN mark — the
   intro overlay's purple glow square belongs on dark chrome and reads as a
   smudge on white, so it is deliberately absent. The inner column is a fixed
   560px design that JS scales down to fit small sheets. */
#prSheetTitle { display: none; }
body.presenting #prSheetTitle:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  overflow: hidden;
  pointer-events: none;
  z-index: 4;                    /* over the sheet, under spotlight (6) and notes */
}
.pr-st-in {
  width: 560px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  transform-origin: 50% 50%;
}
/* The tile hosts the SAME .pr-brandin animation as the splash — these are
   only the recolours white paper needs. The intro's mark ink (#cdd5e4) and
   wordmark white would both vanish on the sheet. */
.pr-st-brandin { margin-bottom: 2px; }
/* The step-zero sheet follows the Present palette too. `aurora` deliberately
   uses a dark sheet, so paper-only ink literals would make its opening title
   disappear before the diagram even begins. */
#prSheetTitle .pr-intro-mark { color: var(--pr-sheet-ink, #232838); }
#prSheetTitle .pr-brandin-word { color: var(--pr-sheet-ink, #171b26); font-size: 28px; }
#prSheetTitle .pr-bi-l.um { color: var(--iris, #6a5cff); }
/* The sheen is a white light-sweep — invisible noise on a white card. */
#prSheetTitle .pr-brandin-sheen { display: none; }
.pr-st-eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 620;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--iris, #6a5cff);
}
.pr-st-title {
  margin: 2px 0 4px;
  font-family: var(--sans);
  font-weight: 750;
  font-size: 40px;
  line-height: 1.12;
  letter-spacing: -0.025em;
  color: var(--pr-sheet-ink, #10131c);
}
.pr-st-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.pr-st-meta span {
  padding: 5px 13px;
  border: 1px solid color-mix(in srgb, var(--pr-sheet-ink, #10131c) 16%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--pr-sheet-ink, #10131c) 7%, var(--pr-sheet, #fff));
  font-size: 12.5px;
  font-weight: 550;
  color: color-mix(in srgb, var(--pr-sheet-ink, #10131c) 74%, var(--pr-sheet, #fff));
  white-space: nowrap;
}

/* ---- Title card, recomposed as the premium opening slide -------------------
   The animations were always wired (mark draws, dot arcs, letters spring);
   what read as cheap was the composition — a 54px mark orphaned from a
   15px wordmark parked at the bottom. Now it is the FULL lockup, large, with
   the document's facts beneath it. The markup order stays untouched (the
   letter-delay chain is wired to it); flex `order` rebuilds the layout. */
#prTitleCardMark { width: 96px; height: 96px; margin-bottom: 0; order: 0; }
#prTitleCardBrand { order: 1; margin: 0 0 16px; font-size: 30px; opacity: 1; }
#prTitleCardHeader { order: 2; font-family: var(--mono); font-size: clamp(15px, 1.35vw, 22px); font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; }
#prTitleCardTitle { order: 3; }
/* The engagement strip rides directly under the title (the card lays out by
   flex order, so markup position alone would strand it at the top). */
#prTitleCard .eng-strip--title { order: 4; }
#prTitleCardFooter { order: 5; }

/* ---- Master mute (control bar + splash) ------------------------------------
   One switch for every Present sound. The speaker glyph swaps its waves for a
   cross via aria-pressed, so the state is visible at a glance and readable by
   assistive tech from the same attribute. */
#prMuteToggle .mu-off, #prIntroMute .mu-off { display: none; }
#prMuteToggle[aria-pressed="true"] .mu-off, #prIntroMute[aria-pressed="true"] .mu-off { display: block; }
#prMuteToggle[aria-pressed="true"] .mu-on, #prIntroMute[aria-pressed="true"] .mu-on { display: none; }
#prMuteToggle[aria-pressed="true"], #prIntroMute[aria-pressed="true"] { color: #f0546a; }
#prIntroMute { display: inline-flex; align-items: center; gap: 6px; }
#prIntroMute svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
#prIntroMute[aria-pressed="true"]:hover { color: #f0546a; }

/* Order hint in the video export options — states the fixed sequence so the
   controls read as one flow rather than five unrelated checkboxes. */
.exp-hint { margin: 6px 0 2px; font-size: 12px; line-height: 1.55; color: var(--muted); }

/* ================================================================
   Notes panel, premium layout (Present + the video export's twin)
   ----------------------------------------------------------------
   The column is a flex COLUMN with three zones: the header, a body
   that scrolls, and a bottom-anchored "Why this matters" card. The
   note used to size the panel; a long one then pushed the deep-dive
   cards off the bottom and, on the way, overlapped the control band.
   Now the note yields — it scrolls inside its own zone — and the
   card below it always keeps its place. A video has no scrollbar,
   so the export mirrors this by reserving the card's height FIRST
   and clamping the note to what is left (drawNotesPanel).
   ================================================================ */
body.presenting #prNarration {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
body.presenting #prNarrationText {
  flex: 1 1 auto;
  min-height: 0;                 /* without this a flex child refuses to shrink */
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--iris) 55%, transparent) transparent;
}
body.presenting #prNarrationText::-webkit-scrollbar { width: 7px; }
body.presenting #prNarrationText::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--iris) 45%, transparent);
  border-radius: 99px;
}
body.presenting #prNarrationText::-webkit-scrollbar-track { background: transparent; }
/* A scrolled note should look scrollable: the text fades out at the bottom
   edge rather than being guillotined mid-word. */
body.presenting #prNarrationText {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(180deg, #000 calc(100% - 22px), transparent 100%);
}
body.presenting #prNarrationText:not(.pr-scrollable) {
  -webkit-mask-image: none; mask-image: none;
}
/* The deep-dive cards sit at the FOOT of the column, in reading order after
   the note, and never scroll away with it. */
body.presenting #prNoteTech,
body.presenting #prNoteTakeaway { flex: 0 0 auto; margin-top: auto; }
body.presenting #prNoteTech,
body.presenting #prNoteTakeaway { margin-top: 8px; }

/* Editor: the per-step "Why this matters" field, visually subordinate to the
   note it belongs to. */
.pnl-sub {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  color: var(--iris-bright); margin: 9px 0 3px;
}
.pnl-why { min-height: 52px; opacity: .95; }

/* The warm bulb is the one cross-theme importance signal; the surrounding
   Why surface keeps the selected note/theme treatment later in this file. */
.pr-why-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: 0 0 24px; border-radius: 8px;
  background: linear-gradient(135deg, #f59e0b, #fbbf24);
  color: #1a1205;                       /* the glyph, dark on bright amber */
  box-shadow: 0 2px 8px color-mix(in srgb, #f59e0b 45%, transparent);
}
.pr-why-badge svg { width: 15px; height: 15px; }

/* ---- Notes panel: the NOTE gets the room, not the trimmings -------------
   Measured on a 505px panel: the step image took ~250px and the why tile
   ~161px, leaving the note 39px to show 427px of text — a paragraph reduced
   to a scrollbar. The note is the thing being read aloud, so it wins ties.
   The image and the why tile are capped in panel-relative units; the note
   takes everything left over and only scrolls once it truly cannot fit. --- */
body.presenting #prNarrationImg {
  flex: 0 1 auto;
  max-height: 26%;
  object-fit: contain;
  min-height: 0;
}

body.presenting #prNarrationText { flex: 1 1 auto; min-height: 60px; }

/* ---- The focused shape: one animated outline ---------------------------
   The animated trace is the sole focus treatment. The former static rail,
   pulsing node shadow and DOM-lens border produced competing outlines. */
body.presenting #svgHost .pr-focus-glow {
  animation: none;
  filter: none;
}
/* The travelling segment. Brighter and heavier than it was: this ring is the
   only thing marking the narrated shape, and at 2.4px with a 4px shadow it
   read as a faint scratch rather than a lit trace — the same reason the
   export's ring had to be built up (drawFocusRing in app.js; keep the two
   in step, they are the live and recorded halves of one effect). */
body.presenting #svgHost .pr-focus-ring {
  /* One accent, thin and luminous — the Fluent-style progress stroke. Still
     SATURATED (the sheet is white paper; a pale stroke vanishes there), but
     electric indigo now and a single soft halo instead of the stacked
     violet glow. Keep in step with drawFocusRing in app.js — live and
     recorded halves of one effect. The lap duration is set INLINE by
     applyFocusGlow to the step's own estimated length, so the stroke
     travels the perimeter once per step rather than on a fixed clock. */
  stroke: var(--pr-focus, var(--iris, #4f46e5));
  stroke-width: 3;
  /* Without this the stroke is in USER units and a zoomed-out diagram draws
     the ring at half a pixel — present but invisible. */
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-dasharray: 34 66;                 /* pathLength=100: a clear comet */
  opacity: 1;
  pointer-events: none;
  animation: prRingTrace 3.2s linear infinite;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--pr-focus, var(--iris, #4f46e5)) 52%, transparent));
}
#stage[data-pr-sheet-tone="dark"] #svgHost .pr-focus-ring {
  stroke: color-mix(in srgb, var(--pr-focus, var(--iris-bright, #8b80ff)) 72%, #fff);
  stroke-width: 3.25;
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--pr-focus, var(--iris-bright, #8b80ff)) 60%, transparent));
}

/* Transient laptop diagram camera. A slim vertical rail is visible only while
   zoom is actively used; it changes the SVG viewBox, never this DOM layer or
   the guide/Why/title chrome around it. */
#prDesktopZoom {
  position: absolute; top: 50%; z-index: 44; transform: translateY(-50%) translateX(-7px);
  display: grid; grid-template-rows: 36px 58px 36px; place-items: center;
  width: 42px; padding: 4px 0; color: var(--pr-stage-ink, #eef2ff);
  border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 15%, transparent);
  border-radius: 22px; background: color-mix(in srgb, var(--pr-panel, #101a37) 88%, transparent);
  box-shadow: 0 12px 34px rgba(3,7,18,.28); backdrop-filter: blur(14px);
  opacity: 0; pointer-events: none; transition: opacity .16s ease, transform .16s ease;
}
#prDesktopZoom[hidden] { display: none; }
#prDesktopZoom.show { opacity: 1; transform: translateY(-50%); pointer-events: auto; }
#prDesktopZoom::before {
  content: ''; position: absolute; top: 36px; bottom: 36px; left: 50%; width: 1px;
  background: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 24%, transparent);
}
#prDesktopZoom button {
  position: relative; z-index: 1; display: grid; place-items: center; width: 32px; height: 32px;
  padding: 0; border: 0; border-radius: 50%; color: inherit; background: var(--pr-panel, #101a37);
  font: 650 21px/1 var(--sans); cursor: pointer;
}
#prDesktopZoom button:hover { color: #fff; background: color-mix(in srgb, var(--iris) 48%, var(--pr-panel, #101a37)); }
#prDesktopZoom button:disabled { opacity: .36; }
#prDesktopZoom #prDesktopZoomReset { width: 38px; height: 26px; border-radius: 999px; font-size: 9px; letter-spacing: -.02em; }
@media (max-width: 900px), (pointer: coarse) { #prDesktopZoom { display: none !important; } }
@keyframes prRingTrace {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting #svgHost .pr-focus-ring {
    animation: none; stroke-dasharray: none; opacity: .9;
  }
}

/* ---- Present frame: the target size, written on the frame ---------------
   The dashed box already showed the SHAPE to aim for; these show the size.
   Width along the top edge, height down the right — a marquee readout, so
   the author never has to leave the drawing to find out what to aim for. -- */
.pg-dim {
  position: absolute;
  font: 600 10.5px/1 var(--sans, system-ui), system-ui;
  letter-spacing: .04em;
  color: var(--iris-bright, #8b80ff);
  background: color-mix(in srgb, var(--bg, #0f1117) 82%, transparent);
  border: 1px solid color-mix(in srgb, var(--iris, #6a5cff) 40%, transparent);
  border-radius: 5px;
  padding: 3px 6px;
  pointer-events: none;
  white-space: nowrap;
}
.pg-dim-w { top: -11px; left: 50%; transform: translateX(-50%); }
.pg-dim-h { right: -13px; top: 50%; transform: translateY(-50%) rotate(90deg); transform-origin: center; }
.pg-dim[hidden] { display: none; }

/* ---- Panel layout, final word ------------------------------------------
   `#prNarration[data-note-style] #prNarrationText` sets flex:0 1 auto and
   out-specifies a `body.presenting #id` rule (two IDs + an attribute beats
   one ID + one class). That is why the note refused to grow and every spare
   pixel pooled BELOW the why card instead of inside the note. Matching that
   selector is the fix; raising specificity beats fighting with !important.

   The why card has since moved out of this column entirely (it floats over
   the diagram), so the note now grows all the way to the panel floor and the
   bottom padding is the panel's own — symmetric with the top by default
   rather than by arithmetic. ------------------------------------------- */
body.presenting #prNarration:not([data-note-style]) #prNarrationText,
body.presenting #prNarration[data-note-style="corporate"] #prNarrationText {
  flex: 1 1 auto;
  min-height: 72px;
}

/* ---- The step picture ---------------------------------------------------
   Two wrong answers were tried before this one. `object-fit: contain` in a
   fixed box letterboxed a square into a 16:10 slot — most of the "image" was
   empty panel showing as bars. `cover` in the same box filled it edge to edge
   by slicing a third off the top and bottom of every picture, which is worse:
   it silently deletes content.

   The box now has NO aspect of its own. `height: auto` with a max-height lets
   the element take the picture's own proportions, so nothing is cropped and
   nothing is padded — a square renders square, a wide one renders wide, and
   the only limit is how much of the column a picture may claim.
   ---------------------------------------------------------------------- */
body.presenting #prNarration[data-note-style] #prNarrationImg,
body.presenting #prNarrationImg {
  flex: 0 0 auto;
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 34%;
  margin-inline: auto;                  /* a fitted box is often narrower */
  object-fit: contain;                  /* no-op at the natural aspect; a guard */
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
}

/* A restrained pulse gives the importance badge a final storytelling beat;
   the canonical floated card and its leader are defined farther below. */
.pr-why-badge {
  box-shadow: 0 2px 10px color-mix(in srgb, #f59e0b 60%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 45%, transparent);
  animation: prWhyPulse 3.4s ease-in-out infinite;
}
@keyframes prWhyPulse {
  0%, 100% { box-shadow: 0 2px 10px color-mix(in srgb, #f59e0b 45%, transparent),
                         inset 0 1px 0 color-mix(in srgb, #fff 45%, transparent); }
  50%      { box-shadow: 0 2px 16px color-mix(in srgb, #f59e0b 85%, transparent),
                         inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .pr-why-badge { animation: none; } }

/* ---- No stepper, no lane ------------------------------------------------
   The 34px top lane exists only to hold the numbered dots. With the stepper
   off, keeping the lane would move the wasted space rather than reclaim it,
   so it collapses to a gutter and the sheet grows into it. The header still
   carries "Step N of M", which is what the dots were mostly saying. ------ */
body.presenting.pr-no-stepper #canvasWrap { --pr-lane-top: 10px; }
/* REEL MODE (a portrait Explainer scene deck — js/app.js explainerReelMode,
   operator Sep 7 2026): the phone video carries no header. The top nameplate
   leaves and its lane collapses, live and therefore in a live take; the
   export drops the podium's header plate the same way (drawStageFrame). */
body.presenting.pr-reel #prTvHead { display: none !important; }
body.presenting.pr-reel #canvasWrap { --pr-lane-top: 0px; }
/* …and zen's compact title strip (a scene deck normally runs in zen), whose
   layout lane is the padding rule below; the transport dock still returns
   on pointer movement, so nothing is lost but the header. */
body.presenting.pr-reel #prZenTitle { display: none !important; }
body.presenting.pr-reel.pr-zen-title #canvasWrap { padding-top: 0 !important; }

/* ============================================================
   PRESENT GEOMETRY — one grid, measured, symmetric
   ------------------------------------------------------------
   The show is:  gutter | sheet | gutter | notes | gutter
   with the sheet and the notes panel sharing the SAME top and
   bottom lane, so their tiles line up as a pair.

   What was wrong:
   • #zoomLayer carries 34px of padding, so the sheet started 34px
     below and right of the lane the notes panel was pinned to —
     the two tiles could never align, and 34px of stage was lost
     on every edge.
   • The notes panel was pinned `right: 26px` while the canvas
     reserved a FLAT 280px for it, so the two numbers disagreed:
     the sheet ran under the panel on one side and left ~37px of
     dead stage on the other.
   The reserve is now MEASURED from the panel itself (see
   reserveNotesColumn), so the two can no longer drift apart.
   ============================================================ */
body.presenting #canvasWrap {
  --pr-gutter: 18px;
  padding-left: var(--pr-gutter);
  /* padding-right is written by reserveNotesColumn() — it is the panel's real
     footprint plus one gutter, not a guess. */
  overflow: hidden;               /* the sheet always fits, so a scrollbar is
                                     only ever a stray 11px of lost width */
}
body.presenting #zoomLayer { padding: 0; }
/* Filmstrip protects its exact one/two-card viewport so the next card cannot
   peek in. If that viewport is narrower than the audience stage, extend the
   page's real paper color through the remaining plane rather than exposing a
   white seam. The SVG stays centred and unchanged. */
body.presenting.pr-strip-sheet #stage #canvasWrap,
body.presenting.pr-strip-sheet #stage #zoomLayer {
  background-color: var(--pr-strip-paper, var(--pr-sheet, #fff));
}
/* No guide means no side column: centre the protected Filmstrip viewport in
   the complete plane. A visible guide deliberately omits this class and
   retains the established diagram-column alignment beside the notes. */
body.presenting.pr-strip-sheet.pr-strip-centered #stage #zoomLayer {
  display: grid;
  place-items: center;
}
body.presenting #prNarration.pos-right { right: var(--pr-gutter) !important; }
body.presenting #prNarration.pos-left { left: var(--pr-gutter) !important; }

/* ---- Arrival: build the guide in reading order -------------------------
   The panel heading lands first, then the image/text rules above, and finally
   the importance badge. The eye is led through the step instead of receiving
   one sideways-moving slab. --------------------------------------------- */
#prNarration.pr-note-in #prNoteStep,
#prNarration.pr-note-in #prNoteTitle {
  animation: prNoteInR .5s cubic-bezier(.22, 1, .36, 1) both;
}
#prNarration.pos-left.pr-note-in #prNoteStep,
#prNarration.pos-left.pr-note-in #prNoteTitle { animation-name: prNoteInL; }
/* The stagger: title first, picture, then the words, then the why card. */
#prNarration.pr-note-in #prNoteTitle { animation-delay: .04s; }
#prNarration.pr-note-in #prNarrationText { animation-delay: .10s; }
/* The badge lights up as its card lands, so the "important" mark is the last
   thing to arrive rather than something that was always sitting there. */
#prNarration.pr-note-in .pr-why-badge {
  animation: prWhyPop .5s cubic-bezier(.34, 1.56, .64, 1) .3s both,
             prWhyPulse 3.4s ease-in-out 1s infinite;
}
@keyframes prWhyPop {
  from { opacity: 0; transform: scale(.5) rotate(-12deg); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  #prNarration.pr-note-in #prNoteStep,
  #prNarration.pr-note-in #prNoteTitle,
  #prNarration.pr-note-in .pr-why-badge { animation: prNoteFade .25s ease both; }
}

/* ---- Title-slide picture -------------------------------------------------
   One image for the whole diagram, on the opening card. Capped by VIEWPORT
   height rather than pixels so it cannot push the title off a short screen,
   and given the same rounded, shadowed treatment as the step pictures so the
   two read as the same product. ------------------------------------------ */
#prTitleCardImgFrame {
  /* This is a real FIT box, not a forced-height replaced element. The image
     gets both dimensions of a measured region and object-fit contains it,
     so portrait, square and panorama covers all remain whole. The frame is
     the elastic block: it yields before title text ever leaves the card. */
  display: grid;
  place-items: center;
  width: min(86%, 960px);
  height: min(56%, 60vh);
  min-width: 0;
  min-height: 0;
  flex: 1 1 auto;
  margin: 0 auto 18px;
  animation: prTitleImgIn .7s cubic-bezier(.22, 1, .36, 1) .12s both;
}
#prTitleCardImgFrame[hidden] { display: none; }
#prTitleCardImg {
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  object-fit: contain;
  border-radius: 16px;
  filter: drop-shadow(0 20px 22px rgba(0, 0, 0, .42));
}
/* ---- The cover BESIDE the words -----------------------------------------
   Stacked, the picture competes with the title and the brand for the card's
   HEIGHT, so `max-height: 34vh` above draws a 448px cover at ~306px on a
   900px-tall screen while more than half the card's width sits empty next to
   it. Standing them side by side spends that width instead and roughly
   doubles the picture.

   A grid, not a row of flex items, because the card's children are a flat
   list (mark, header, img, title, footer, brand) with no wrapper to group the
   text half — column 2 collects them in source order while the picture holds
   column 1 across every row.

   `pr-cover-side` is set by maybeShowTitleCard, and only on the same two
   conditions the export's card uses (a picture no wider than about 4:3, a
   landscape stage) so the show and the recording open on the same shape.

   The HEIGHT is set rather than capped on purpose: an <img> at width/height
   auto draws at its natural 448px and a `max-height` can only ever make that
   smaller. Expressing the bound in vw as well as vh is what keeps a square
   from ever needing max-width — at 40vw its width equals its height, so the
   clamp that would distort a forced-height image can never engage. */
/* Stacked, the two groups just sit in the card's own column and the gap
   between them matches the gap inside them, so the order and spacing are
   exactly what the flat list produced: mark, header, picture, title, footer,
   brand. */
#prTitleCardLead, #prTitleCardTail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
#prTitleCard.pr-cover-side {
  display: grid;
  /* Rows spelled out. `grid-row: 1 / -1` looks like the obvious way to make
     the picture span the text, and it silently does NOT work here: -1 resolves
     against the EXPLICIT grid, and with no explicit rows that collapses to a
     single row — the picture then shares row 1 with the first text block,
     stretches it to the picture's height, and shoves everything else off the
     bottom of the card. Two named rows, one per group, and the span is
     unambiguous. */
  /* 1fr rows, not auto. The picture's height is a PERCENTAGE, and a percentage
     on a grid item resolves against its grid area — which for auto rows is
     sized by the content it is trying to be measured against, so it collapses
     to something arbitrary (it came out at 328px, smaller than the stacked
     card it was meant to beat). Two equal fractions of a card that has a
     definite height make the area definite, and the percentage means what it
     says. It also puts the row boundary on the card's centre line, which is
     what `align-self` below hangs the two text groups from. */
  grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr);
  grid-template-rows: 1fr 1fr;
  align-items: center;
  align-content: center;
  justify-items: center;
  column-gap: clamp(20px, 3.5vw, 56px);
  row-gap: 10px;
}
#prTitleCard.pr-cover-side > .pr-brandin-glow { grid-area: 1 / 1; }
#prTitleCard.pr-cover-side #prTitleCardLead { grid-column: 2; grid-row: 1; align-self: end; }
#prTitleCard.pr-cover-side #prTitleCardTail { grid-column: 2; grid-row: 2; align-self: start; }
#prTitleCard.pr-cover-side #prTitleCardImgFrame {
  grid-column: 1;
  grid-row: 1 / 3;
  align-self: center;
  justify-self: stretch;
  height: 86%;
  width: 100%;
  max-width: 100%;
  max-height: 86%;
  margin: 0;
}
@keyframes prTitleImgIn {
  from { opacity: 0; transform: scale(.94) translateY(14px); filter: blur(8px); }
  60%  { opacity: 1; filter: blur(0); }
  to   { opacity: 1; transform: none; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  #prTitleCardImgFrame { animation: prNoteFade .25s ease both; }
}

@keyframes prWhyIn { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }

/* The bottom band is ONE thing to a viewer. With "Bottom subtitles" off the
   karaoke strip AND the step-name caption both stay away — the caption is a
   separate feature with its own toggle, but leaving it alone down there put a
   chip in exactly the place the user had just cleared, which reads as the
   subtitle they turned off. present-plus.js syncSubsBand owns this class. */
body.pr-no-subs #prCaption,
body.presenting.pr-no-subs #prCaption { display: none; }

/* ==========================================================================
   Narrated samples — the landing row, and the Present-only lock
   --------------------------------------------------------------------------
   Seven fully-produced tours open straight into Present from `?present=<id>`
   (js/sample-present.js). They are published at the `pro` tier, so the point
   of the lock is that a visitor can watch the whole show without being able
   to take it: no editor, no canvas, no way back except home.
   ========================================================================== */

.lp-sample-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1rem;
}

.lp-sample {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border-soft);
  border-radius: 16px;
  background: var(--chrome);
  text-decoration: none;
  color: inherit;
  transition: transform .22s cubic-bezier(.22, 1, .36, 1), box-shadow .22s ease,
    border-color .18s ease;
}

.lp-sample:hover,
.lp-sample:focus-visible {
  transform: translateY(-3px);
  border-color: var(--iris-bright, #8b80ff);
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .55);
}

/* The card art is the diagram's own title image. It only becomes visible once
   the image has actually decoded (`has-img`), so a slow catalogue shows the
   emoji rather than an empty frame. */
.lp-sample-art {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(124, 108, 248, .16), transparent 70%),
    var(--panel-2);
  overflow: hidden;
}

.lp-sample-art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 10px;
  box-sizing: border-box;
  object-fit: contain;
  opacity: 0;
  transition: opacity .3s ease, filter .35s ease;
}

.lp-sample-art.has-img img { opacity: 1; }
.lp-sample-art.has-img .lp-sample-emoji { opacity: 0; }
.lp-sample:hover .lp-sample-art.has-img img { filter: saturate(1.06) brightness(1.03); }

.lp-sample-emoji {
  font-size: 2.4rem;
  line-height: 1;
  transition: opacity .25s ease;
}

/* The play badge is the whole affordance: these cards do not open an editor,
   they start a show. */
.lp-sample-play {
  position: absolute;
  top: calc(16 / 10 * 100% / 2);
  left: 50%;
  transform: translate(-50%, -50%) scale(.92);
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: rgba(12, 14, 22, .62);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
  opacity: 0;
  transition: opacity .2s ease, transform .25s cubic-bezier(.22, 1, .36, 1);
  pointer-events: none;
}

.lp-sample-play svg { width: 1.35rem; height: 1.35rem; margin-left: 2px; }

.lp-sample:hover .lp-sample-play,
.lp-sample:focus-visible .lp-sample-play {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.lp-sample-body {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .85rem .95rem 1rem;
  border-top: 1px solid var(--border-soft);
}

.lp-sample-name {
  font-weight: 620;
  font-size: 1rem;
  letter-spacing: -0.01em;
  color: var(--text);
  /* Two-line ceiling on both text blocks: rows of cards keep one height, so
     the grid never staggers on a long title. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

.lp-sample-blurb {
  font-size: .85rem;
  line-height: 1.45;
  color: var(--muted);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* ---- The lock ----------------------------------------------------------
   While a sample is playing there is no editor to reach: the canvas chrome,
   the toolbars and every save/export path are gone. sample-present.js sends
   both exits (button and Escape) home, so this is belt AND braces rather
   than styling standing in for behaviour. */
/* `.present-link` is any ?present=<id> arrival; `.sample-locked` is the subset
   that must also stay out of the editor. They were the same class, so an
   UNLOCKED share link presented inside the editor chrome — palette and
   inspector still laid out, the stage squeezed to a strip beside them, which
   is not what someone who followed a shared link came to see.
   Locking governs the EXIT (js/sample-present.js); this governs the LAYOUT,
   and every ?present= arrival wants the full-screen show. */
body.sample-locked #topbar,   body.present-link #topbar,
body.sample-locked #sidebar,  body.present-link #sidebar,
body.sample-locked #inspector, body.present-link #inspector,
body.sample-locked #hintBar,  body.present-link #hintBar,
body.sample-locked #btnExport, body.present-link #btnExport,
body.sample-locked #fileMenuBtn, body.present-link #fileMenuBtn,
body.sample-locked #prNarrationEditBtn, body.present-link #prNarrationEditBtn,
body.sample-locked #prScriptGen, body.present-link #prScriptGen { display: none !important; }
/* The two flex siblings of #stage. `body.presenting` only DIMS these
   (opacity .45, line ~2113) because presenting from inside the editor keeps
   its furniture; a shared link has no editor to return to mid-show, and
   leaving them laid out squeezed the stage to a 36px strip between a 212px
   palette and a 292px inspector. Measured, not guessed. */
body.sample-locked #palette, body.present-link #palette,
body.sample-locked #side,    body.present-link #side { display: none !important; }

/* Nothing on the canvas is interactive under the lock — a stray drag must not
   modify a diagram the visitor is not allowed to keep. */
body.sample-locked:not(.presenting) #canvasWrap { pointer-events: none; }

/* ============================================================
   /embed/<id> — Present Mode inside somebody else's page.
   ------------------------------------------------------------
   THE LOOK IS NOT REDEFINED HERE. Everything below SUBTRACTS: the site
   chrome, the editor, the account controls, the ways out. The show itself —
   the stage bezel, the notes panel, the focus ring, the title and closing
   slides, the audience skins — is the same CSS a show on diagramium.com
   runs, which is the whole point of embedding the real player instead of
   shipping a second one.

   `body.embed-mode` is the layout lock and it is NOT `sample-locked`: that
   class force-disables Loop (js/present-plus.js's finale skips looping for a
   locked sample so its return-home can fire), which would make `loop=1`
   silently do nothing. The three option classes — embed-no-controls,
   embed-brand-minimal, embed-notes-* — are set from the URL by js/embed.js.

   Everything is `display: none`, never removal: js/app.js has 67 top-level
   `$('#id').addEventListener(...)` calls that throw on a missing element, so
   an embed has to be the full document with the furniture switched off.
   ============================================================ */

/* `notes=hidden` was set on the body by js/embed.js and implemented NOWHERE —
   the class existed, the option was documented, and the panel stayed on
   screen. embed.js calls setNotesVisible(false) in applyPreEnter, but
   enterPresent runs afterwards and shows the panel again, so the JS toggle
   lost a race it could not win. Measured on a 900x520 frame: the panel came
   back at 854px wide and canvasWrap kept an 86px bottom reserve, so a
   publisher who asked for no notes still paid for them.

   Fixed in CSS for the same reason `body.pr-no-subs` hides #prCaption rather
   than chasing every code path that sets .hidden: the class is the single
   authority, and no later JS can undo it. Hiding the panel also zeroes the
   reserve for free — reserveNotesColumn measures the panel's REAL rect, and
   a display:none panel measures 0, so the padding it pays becomes 0 without
   this rule having to know the arithmetic. */
body.embed-mode.embed-notes-hidden #prNarration,
body.embed-mode.embed-notes-hidden #prWhyDock { display: none !important; }

/* ---- the site: gone -------------------------------------------------- */
body.embed-mode #topbar,
body.embed-mode #palette,
body.embed-mode #side,
body.embed-mode #hintBar,
body.embed-mode #emptyState,
body.embed-mode #miLauncher,
body.embed-mode #commentPane,
body.embed-mode #commentConnectors,
body.embed-mode #homePage,
body.embed-mode #explorePage,
body.embed-mode #searchPage,
body.embed-mode #rolesPage,
body.embed-mode #toasts,
body.embed-mode .modal-backdrop,
body.embed-mode #prBrand,
body.embed-mode #pgFrame,
/* canvas-kit appends its chrome to document.body, OUTSIDE #stage, and the
   rules that normally hide it are keyed on body.presenting / body.watching.
   That is fine for a show — and wrong for the two states where the embed
   never reaches Present: the loading veil and the unavailable panel. The
   rulers were visibly framing the "This presentation is unavailable" card
   before this line existed. */
body.embed-mode #ckToolbar,
body.embed-mode #ckMenu,
body.embed-mode #ckLayers,
body.embed-mode #ckMinimap,
body.embed-mode #ckRulerH,
body.embed-mode #ckRulerV,
body.embed-mode #ckGuides,
body.embed-mode #ckOrderBar,
body.embed-mode #ckPalette,
body.embed-mode #sideExpand { display: none !important; }

/* ---- the editor, the account, the exits: gone ------------------------
   Behaviour is locked in JS too (js/embed.js no-ops exitPresent and swallows
   every accelerator), so this is the second of two locks rather than the
   only one. #prExit / #prEndEdit / #prEndExplore are the three doors that
   would drop a viewer onto a bare editor canvas holding a diagram they are
   only allowed to watch. */
/* Zen is publisher-owned in an embed. js/embed.js mounts the fixed,
   sheet-native presentation with setEmbedPresentZen; setPresentZen still
   refuses viewer toggles, so this retires the button rather than leaving a
   dead control beside it. */
body.embed-mode #prZenToggle,
body.embed-mode #prExit,
body.embed-mode #prEndEdit,
body.embed-mode #prEndExplore,
body.embed-mode #prEndQa,
body.embed-mode #prQa,
body.embed-mode #prNarrationEditBtn,
body.embed-mode #prScriptGen,
body.embed-mode #btnExport,
body.embed-mode #prMore,
body.embed-mode #prPin,
body.embed-mode #prToolLaser,
body.embed-mode #prToolPen { display: none !important; }

/* Engagement is not collected in an embed (js/embed.js pins
   Privacy.allowed() false), so nothing may offer to record one either — and
   the share controls would fail silently anyway: clipboard-write and
   web-share are not delegated to a cross-origin frame. */
body.embed-mode #prLikeBtn,
body.embed-mode .eng-strip,
body.embed-mode #prEndShare,
body.embed-mode #prSharePop,
body.embed-mode #prRecordPop { display: none !important; }

/* The frame IS the viewport. No page scroll, and nothing interactive on the
   canvas until the show is up — a stray drag must not edit a diagram the
   viewer is not allowed to keep. */
body.embed-mode { overflow: hidden; }
body.embed-mode:not(.presenting) #canvasWrap { pointer-events: none; }

/* ---- controls=0 ------------------------------------------------------
   Hiding #presentBar is not enough on its own. present-plus.js's
   syncBottomBand falls back to BAND_FALLBACK (66px) whenever the bar has no
   height, and writes that to --pr-band as an INLINE custom property on
   #canvasWrap and #stage — which feeds --pr-lane-bottom, the caption offset
   and the notes panel's bottom. So a chrome-less embed would reserve a
   control bar's worth of empty stage. `!important` is what beats the inline
   value; it is the only way to win against an element style. */
body.embed-mode.embed-no-controls #presentBar,
body.embed-mode.embed-no-controls #prSegBar,
body.embed-mode.embed-no-controls #prStepper,
body.embed-mode.embed-no-controls #prProgress { display: none !important; }
body.embed-mode.embed-no-controls #canvasWrap,
body.embed-mode.embed-no-controls #stage { --pr-band: 10px !important; }

/* ---- branding=minimal -----------------------------------------------
   Quieter, never anonymous: the nameplate keeps the mark so a viewer can
   still tell what they are looking at, and the wordmark, the title-slide
   lockup and the closing sign-off step back.

   NOTE THE ONE THAT IS NOT HERE. `#prSheetTitle` is the step-0 opening
   SLIDE — eyebrow, the document's own H2 title and the meta line — of which
   `.pr-st-brandin` is only one child. Hiding the container took the
   diagram's own opening slide off screen, which is CONTENT, not branding:
   `branding=minimal` was silently deleting the title of the thing being
   presented. Only the brand lockup inside it goes. */
body.embed-mode.embed-brand-minimal .pr-tv-word,
body.embed-mode.embed-brand-minimal #prTitleCardBrand,
body.embed-mode.embed-brand-minimal #prTitleCardMark,
body.embed-mode.embed-brand-minimal #prSheetTitle .pr-st-brandin,
body.embed-mode.embed-brand-minimal .pr-end-mark,
body.embed-mode.embed-brand-minimal .pr-end-brand { display: none !important; }

/* THE THIN HEADER — the sleek treatment, applied to the nameplate.
   `branding=minimal` removed the wordmark and stopped there, so the plate
   itself stayed 45px tall with a purple gradient, a bottom border and a 22px
   mark: the single heaviest object in a 520px-tall figure, and the first
   thing a reader saw above the diagram they came for.

   Same decision as the sleek export podium — small, no filled ground, one
   brand-coloured accent left doing the identifying — but reached through
   `--pr-plate` rather than by setting a height. That variable is the top
   lane's own measurement (styles.css:677 pads the stage by it), so lowering
   it thins the plate AND hands the reclaimed pixels to the diagram in one
   move; overriding `height` alone would have shrunk the bar and left the
   gap. Measured on a 900x520 frame: 45px plate, canvas starting at y=60.

   The variable is set on #stage, NOT on body: `body.presenting #stage`
   re-declares `--pr-plate: 45px` for its own subtree, so a body-level value
   is shadowed for every descendant and the plate stays 45px while the token
   still reads 26px on body — what a custom property always does when it is
   set on the wrong ancestor, and it fails silently. Two classes plus the id
   out-specify `body.presenting #stage` without relying on source order. */
body.embed-mode.embed-brand-minimal #stage { --pr-plate: 26px; }
body.embed-mode.embed-brand-minimal #prTvHead {
  background: none;
  border-bottom: 0;
  border-radius: 0;
  padding: 0 10px;
  gap: 7px;
}
body.embed-mode.embed-brand-minimal #prTvHead svg { width: 14px; height: 14px; }
body.embed-mode.embed-brand-minimal #prTvTitle { font-size: 12px; }
body.embed-mode.embed-brand-minimal #prStepTime,
body.embed-mode.embed-brand-minimal #prTvStep { font-size: 11px; }
/* The nav pill supplies its own chrome, which reads as a second bar once the
   plate behind it is gone. Keep the buttons, drop the slab. */
body.embed-mode.embed-brand-minimal #prTvNav {
  background: none;
  height: 22px;
  padding: 0;
}
body.embed-mode.embed-brand-minimal #prTvNav button svg { width: 13px; height: 13px; }

/* ---- the unavailable state ------------------------------------------
   Built by js/embed.js and appended to #stage, following the rule that every
   Present overlay lives inside the stage so it survives full screen. Dark in
   both themes, like the rest of the Present chrome and like #watchBoot, so a
   failed embed still reads as a player rather than as a broken page. */
#embedNotice {
  position: absolute; inset: 0; z-index: 30;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 28px; text-align: center;
  background: radial-gradient(60rem 40rem at 50% -10%, #171a2c, #0b0d14 70%);
  color: #e9ecff;
}
#embedNotice .embed-notice-mark { width: 52px; height: 52px; color: rgba(233, 236, 255, .82); }
#embedNotice .embed-notice-mark svg { width: 100%; height: 100%; }
#embedNotice .embed-notice-title { font-size: 17px; font-weight: 650; letter-spacing: .01em; }
#embedNotice .embed-notice-body {
  font-size: 13.5px; line-height: 1.55; max-width: 42ch;
  color: rgba(233, 236, 255, .68);
}

/* A sample that is not published yet: shown, named, and clearly not clickable
   — the row must read the same before and after the publish lands. */
.lp-sample.is-pending { cursor: default; opacity: .72; }
.lp-sample.is-pending:hover { transform: none; border-color: var(--border-soft); box-shadow: none; }
.lp-sample.is-pending .lp-sample-play { display: none; }
.lp-sample-soon {
  position: absolute;
  left: 50%;
  bottom: .7rem;
  transform: translateX(-50%);
  padding: .18rem .6rem;
  border-radius: 999px;
  font-size: .7rem;
  font-weight: 620;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #e9e6ff;
  background: rgba(12, 14, 22, .72);
  border: 1px solid rgba(255, 255, 255, .16);
}
/* The badge now lives inside the art box, so it centres on the picture. */
.lp-sample-play { top: 50%; }
/* The body inherits the card's own --chrome; do NOT give it a background of its
   own. The trap here is INVENTED TOKENS: --panel-bg/--text-strong/--text-muted
   do not exist in this stylesheet, so `var(--panel-bg, #171a24)` silently
   serves the hardcoded fallback in BOTH themes — it looks right in dark and
   only in dark. Worse, --canvas-bg is real but it is the DRAWING SURFACE
   (#d9dcea), light in both themes, so using it for a card put light text on a
   light slab at 1.19 contrast. The real tokens are --chrome/--panel/--panel-2,
   --text/--muted/--faint, --border-soft. */

/* Hover matches the template cards: the surface lifts to --panel. */
.lp-sample:not(.is-pending):hover { background: var(--panel); }

/* ---- Explore: active-filter chips --------------------------------------
   Uses the real tokens (--chrome/--panel/--text/--muted/--border-soft); see
   the note by .lp-sample-body about invented ones. */
.mkt-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 12px;
}

.mkt-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 4px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 520;
  line-height: 1.3;
  cursor: pointer;
  transition: background var(--dur-2, .18s) var(--ease-out, ease),
    border-color var(--dur-2, .18s) var(--ease-out, ease);
}

.mkt-chip:hover,
.mkt-chip:focus-visible { background: var(--panel); border-color: var(--border); }

.mkt-chip-x {
  font-size: 10px;
  color: var(--faint);
  transition: color var(--dur-2, .18s) var(--ease-out, ease);
}

.mkt-chip:hover .mkt-chip-x { color: var(--text); }

/* ---- Beta badge --------------------------------------------------------
   Sits beside the wordmark everywhere the wordmark appears. Deliberately
   quiet: it is an honesty signal, not a decoration, and it should read as a
   note on the product rather than a feature of it. Uses the real tokens (see
   the note by .lp-sample-body about invented ones). */
.beta-badge {
  align-self: center;
  margin-left: .45rem;
  padding: .1rem .38rem;
  border: 1px solid var(--border-soft);
  border-radius: 5px;
  background: var(--panel-2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.5;
  white-space: nowrap;
  /* The brand is a flex row; without this the badge stretches to its height. */
  flex: none;
}

/* ---- Sample card states ------------------------------------------------
   Three, and they must look different at a glance: available, sold, not ready.
   All use the real tokens (see the note by .lp-sample-body). */

/* Sold. The card stays fully legible — a locked sample only sells if you can
   see what you are missing — so this dims nothing and only adds the label. */
.lp-sample.is-locked .lp-sample-play { display: none; }
.lp-sample-lock,
.lp-sample-free {
  position: absolute;
  left: 50%;
  bottom: .7rem;
  transform: translateX(-50%);
  padding: .18rem .6rem;
  border-radius: 999px;
  font-size: .7rem;
  font-weight: 620;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
}
.lp-sample-lock {
  color: #f5f3ff;
  background: rgba(124, 108, 248, .92);
  border-color: rgba(255, 255, 255, .18);
}
.lp-sample.is-locked:hover .lp-sample-lock { background: rgba(124, 108, 248, 1); }

/* Free to watch: quieter than the paid chip on purpose — it is a reassurance,
   not a call to action. The play button is the call to action. */
.lp-sample-free {
  color: #d7ffe9;
  background: rgba(6, 42, 28, .72);
  border-color: rgba(120, 255, 200, .28);
}

/* ---- /search — one box, ranked tiles -----------------------------------
   Real tokens only (--chrome/--panel/--panel-2, --text/--muted/--faint,
   --border/--border-soft) — see the note by .lp-sample-body about invented
   ones. The hero floats at ~30vh while the box is empty and docks to the top
   the moment results exist, which is what makes it read as a search page
   rather than a form. */
#searchPage {
  /* Fixed overlay like #homePage/#explorePage — these views sit ON TOP of the
     editor, which is always mounted underneath. In normal flow the editor's
     toolbar showed above the search box, which read as the editor bleeding
     into a page that is supposed to have no chrome at all. */
  position: fixed;
  inset: 0;
  z-index: 60;
  min-height: 100vh;
  background: var(--chrome);
  color: var(--text);
  overflow-y: auto;
  overflow-x: hidden;
}

.srch-wrap {
  max-width: 860px;
  margin: 0 auto;
  padding: 30vh 20px 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: padding-top .28s cubic-bezier(.22, 1, .36, 1);
}

/* With results on screen the page becomes a gallery: the wrap lets go of its
   860px reading measure and the GRID takes the whole viewport. The controls
   keep their own caps below (.srch-box 620) so the search
   cluster stays a coherent centred column inside the wide page. */
#searchPage.has-results .srch-wrap {
  padding-top: 34px;
  max-width: none;
  padding-left: clamp(20px, 4vw, 64px);
  padding-right: clamp(20px, 4vw, 64px);
}

/* Quiet accent atmosphere behind the whole page — two soft washes of the
   signal colour falling from the top corners. color-mix against transparent
   keeps it token-driven: it follows the visitor's accent AND both themes.
   #searchPage is a fixed overlay with z-index 60 (see its base rule), which
   already makes it a stacking context — so z-index -1 here paints above the
   page's own background and under every child, and NOTHING may re-position
   the page into normal flow (that is the editor-toolbar-bleeds-through bug
   its base rule documents). */
#searchPage::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(52rem 30rem at 16% -6%, color-mix(in srgb, var(--iris) 13%, transparent), transparent 62%),
    radial-gradient(60rem 34rem at 86% -10%, color-mix(in srgb, var(--iris-bright) 9%, transparent), transparent 60%);
}

.srch-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  margin-bottom: 26px;
}
.srch-brand .brand-mark svg { width: 34px; height: 34px; display: block; }
.srch-brand .wordmark { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; }

.srch-box {
  position: relative;
  width: 100%;
  max-width: 620px;
}
.srch-glass {
  position: absolute;
  left: 18px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  color: var(--faint);
  pointer-events: none;
}
#srchInput {
  width: 100%;
  padding: 15px 46px 15px 48px;
  font-size: 16px;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  outline: none;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .12);
  transition: border-color var(--dur-2, .18s) ease, box-shadow var(--dur-2, .18s) ease;
}
#srchInput:focus { border-color: var(--accent); box-shadow: 0 8px 32px rgba(0, 0, 0, .18); }
#srchInput::-webkit-search-cancel-button { display: none; }

.srch-clear {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 1;
  color: var(--muted);
  display: grid;
  place-items: center;
}
.srch-clear:hover { background: var(--panel-2); color: var(--text); }

.srch-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 18px;
}
.srch-chips button {
  padding: 6px 13px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  background: var(--panel);
  color: var(--muted);
  font-size: 12.5px;
  transition: color var(--dur-2, .18s) ease, border-color var(--dur-2, .18s) ease;
}
.srch-chips button:hover { color: var(--text); border-color: var(--border); }

.srch-status {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}
.srch-status a { color: var(--accent); }

.srch-result-tools {
  width: 100%; margin-top: 22px; padding: 11px 13px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border: 1px solid var(--border-soft); border-radius: 12px;
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  box-shadow: var(--shadow-sm);
}
.srch-result-tools[hidden] { display: none; }
.srch-sort { display: inline-flex; align-items: center; gap: 8px; color: var(--faint); font: 650 11px/1 var(--sans); white-space: nowrap; }
.srch-sort select {
  min-height: 34px; padding: 0 30px 0 10px; color: var(--text); background: var(--panel-2);
  border: 1px solid var(--border-soft); border-radius: 8px; font: 600 12px/1 var(--sans);
}

.srch-grid {
  width: 100%;
  margin-top: 18px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}

.srch-pagination {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; width: 100%; margin: 26px 0 2px;
}
.srch-pagination[hidden] { display: none; }
.srch-pagination button {
  min-width: 38px; height: 38px; padding: 0 11px; border: 1px solid var(--border-soft);
  border-radius: 9px; color: var(--muted); background: var(--panel); font: 650 12px/1 var(--sans); cursor: pointer;
}
.srch-pagination button:hover:not(:disabled) { color: var(--text); border-color: var(--accent); }
.srch-pagination button[aria-current="page"] { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.srch-pagination button:disabled { opacity: .35; cursor: default; }

.srch-tile {
  display: flex;
  flex-direction: column;
  text-align: left;
  border: 1px solid var(--border-soft);
  border-radius: 16px;
  /* A faint top-light on the card surface — reads as depth, not colour. */
  background: linear-gradient(180deg, color-mix(in srgb, var(--panel-2) 55%, var(--panel)), var(--panel) 52%);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  padding: 0 0 14px;
  transition: transform .2s cubic-bezier(.22, 1, .36, 1), border-color .15s ease, box-shadow .2s ease;
}
.srch-tile:hover, .srch-tile:focus-visible {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border-soft));
  box-shadow: 0 0 0 3px var(--accent-ring), var(--shadow-lg);
}
.srch-thumb svg { transition: transform .25s cubic-bezier(.22, 1, .36, 1); }
.srch-tile:hover .srch-thumb svg { transform: scale(1.045); }

.srch-thumb {
  position: relative;
  aspect-ratio: 15 / 9;
  display: grid;
  place-items: center;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 10px;
  overflow: hidden;
}
/* One-touch Edit / Present, mirroring Explore's tile overlay. */
.srch-hover {
  position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  background: color-mix(in srgb, var(--paper) 46%, transparent); opacity: 0; transition: opacity .16s ease;
}
.srch-tile:hover .srch-hover, .srch-tile:focus-within .srch-hover { opacity: 1; }
.srch-hover button {
  font: inherit; font-size: 12.5px; font-weight: 650; cursor: pointer; padding: 7px 14px; border-radius: 9px; min-width: 106px; text-align: center;
  transform: translateY(6px); transition: transform .16s ease, filter .12s;
}
.srch-tile:hover .srch-hover button, .srch-tile:focus-within .srch-hover button { transform: translateY(0); }
.srch-edit { color: var(--on-accent); background: var(--accent); border: 1px solid var(--accent); }
.srch-edit:hover { filter: brightness(1.05); }
.srch-present { color: #241a06; background: var(--marigold); border: 1px solid var(--marigold-deep); }
.srch-present:hover { filter: brightness(1.05); }
.srch-thumb svg { width: 100%; height: 100%; padding: 8px 12px; }
.srch-thumb-mode {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--faint);
}

.srch-name {
  padding: 0 14px;
  font-size: 14.5px;
  font-weight: 620;
  letter-spacing: -0.01em;
  line-height: 1.35;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.srch-meta {
  padding: 4px 14px 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}

@media (max-width: 560px) {
  .srch-wrap { padding-top: 18vh; }
  .srch-status { align-self: center; }
  .srch-result-tools { align-items: flex-start; flex-direction: column; gap: 9px; }
  .srch-sort { width: 100%; justify-content: space-between; }
}

/* ---- /search: chrome + footer ------------------------------------------ */

/* Footer pinned to the bottom on short pages: the page is a flex column and
   the search column takes the slack. */
#searchPage { display: flex; flex-direction: column; }
#searchPage .srch-wrap {
  flex: 1 0 auto;
  position: relative;
  z-index: 1;
  /* The page is a flex column, and a flex child with `margin: 0 auto` gives up
     cross-axis stretch — the wrap shrink-wrapped to its widest chip and the
     result grid collapsed to one narrow column. Ask for the width back;
     max-width still caps it and the auto margins still centre it. */
  width: 100%;
  /* No min-height: the empty page must fit ONE viewport with no scrollbar.
     The wrap flexes to (viewport − footer), so the slim base bar sits at the
     bottom edge of the first screen — this was written the other way when the
     footer was the five-column grid, which deserved to be below the fold; the
     base bar does not. Results grow the wrap and the page scrolls then. */
}
#searchPage .lp-foot {
  position: relative;
  z-index: 1;
  margin-top: 0;
  /* The landing footer sits inside .home-inner, which insets it by this same
     clamp; here the footer is a bare flex child, so without it the base bar
     ran edge to edge — text hard against the viewport on both sides. */
  padding: 0 clamp(18px, 4vw, 64px) 22px;
}

.srch-home {
  position: fixed;   /* #searchPage is the fixed box; this pins to its viewport */
  top: 14px;
  left: 14px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  color: var(--text);
  text-decoration: none;
  transition: background var(--dur-2, .18s) ease, transform var(--dur-2, .18s) ease;
}
.srch-home svg { width: 30px; height: 30px; display: block; }
.srch-home:hover { background: var(--panel-2); transform: scale(1.06); }

/* Sits beside the mark, same fixed top-left cluster — the search page's only
   other chrome. Pilled rather than iconic because "Explore" has no glyph
   everyone reads the same way, and the word is the affordance. */
.srch-explore {
  position: fixed;
  top: 14px;
  left: 66px;                    /* clears .srch-home (14 + 44 + 8 gutter) */
  z-index: 2;
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 16px;
  border-radius: 12px;
  border: 1px solid var(--border-soft);
  background: var(--chrome-2);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
  transition: background var(--dur-2, .18s) ease, border-color var(--dur-2, .18s) ease;
}
.srch-explore:hover { background: var(--panel-2); border-color: var(--accent); }

/* `hidden` must always win: these carry their own display values, and an
   author display beats the UA's [hidden] rule in some engines. */
.srch-chips[hidden], .srch-grid[hidden] { display: none; }

/* The Present lockup on a light page. Present's chrome is dark in both themes
   and .pr-brandin-word hardcodes white for it — invisible here. Re-ink under
   the page's own scope; the animation itself is untouched. */
.srch-logo { margin-bottom: 26px; }
/* Bigger here than in Present's splash. The base 31px is tuned for a full-bleed
   dark stage where the wordmark is the only thing on screen; on this page it
   sits under a 74px mark with a search box beneath it, and at 31px it read as
   a caption for the logo rather than the name of the product.
   SCOPED to .srch-logo on purpose — .pr-brandin-word is shared with the Present
   intro, and resizing it there would move an animation that is timed to it. */
.srch-logo .pr-brandin-word { color: var(--text); font-size: 41px; }
/* The mark inherits .pr-intro-mark's #cdd5e4 — near-white ink for Present's
   dark chrome, a ghost on this page. Same re-ink as the word. */
.srch-logo .pr-intro-mark { color: var(--text); }
.srch-logo .pr-brandin-sheen {
  /* A white sweep cannot read over a light page — tint it with the accent,
     which carries in both themes. */
  background: linear-gradient(100deg, transparent,
    color-mix(in srgb, var(--accent) 55%, transparent), transparent);
}

.srch-theme {
  position: fixed; top: 14px; right: 104px; z-index: 2; height: 44px;
  border: 1px solid var(--border-soft); background: var(--chrome-2); color: var(--text);
}
.srch-theme .glyph { font-size: 17px; line-height: 1; }
@media (max-width: 620px) {
  .srch-theme { right: 72px; width: 44px; padding: 0; }
  .srch-theme .tb-lbl { display: none; }
}

/* ============================================================
   ACCENT PALETTE — the whole site's signal colour, in one place
   ------------------------------------------------------------
   111 accent usages across this stylesheet read six tokens, so re-pointing
   them repaints everything — buttons, links, focus rings, the Present
   spotlight ring, the brand dot, chart series — with no component touched.

   Chosen with <html data-accent="…"> (persisted by js/accent.js). No
   attribute = iris, the default defined at :root.

   EACH PALETTE NEEDS TWO RAMPS, and they are not the same colour lightened.
     --iris        the signal, and ALSO link/label text on a LIGHT ground —
                   so the light ramp must clear 4.5:1 on white. That is why
                   every light value here is a deep shade, never the vivid one.
     --iris-ink    the accent used as text on --paper. On the dark ground it
                   must be LIGHT; on the light ground, DARK. It is the token
                   that inverts, and the one most easily got wrong.
     --iris-bright hovers, glows, the brand dot
     --iris-deep   pressed states, gradient far end
     --iris-soft   tinted fills — near-black on dark, near-white on light
   ============================================================ */

/* ---- the picker ---- */
.accent-btn { position: relative; }
.accent-dot {
  display: inline-block; width: 13px; height: 13px; border-radius: 50%;
  background: var(--iris); box-shadow: 0 0 0 1px var(--border-soft) inset;
  vertical-align: -2px;
}
.accent-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 200;
  display: grid; grid-template-columns: repeat(6, 30px); gap: 8px;
  padding: 12px; border: 1px solid var(--border);
  border-radius: 12px; background: var(--panel);
  box-shadow: 0 14px 40px rgba(0,0,0,.35);
}
.accent-pop[hidden] { display: none; }
.accent-sw {
  width: 30px; height: 30px; border-radius: 8px; padding: 0;
  border: 2px solid transparent; cursor: pointer;
  transition: transform .14s ease, border-color .14s ease;
}
.accent-sw:hover { transform: scale(1.12); }
.accent-sw[aria-pressed="true"] { border-color: var(--text); }

/* ---- "these are samples" caveat ----------------------------------------
   Stated where the diagrams are actually browsed (Explore, /search) rather
   than buried in the legal pages: a caveat nobody reads at the moment it
   matters is decoration. Quiet by design — informative, not alarming. */
.sample-note {
  margin: 0 0 14px;
  padding: 9px 12px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--iris);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.55;
  /* 68ch is the readable measure for a PARAGRAPH; this is a two-line notice,
     and the narrower measure only bought it two extra lines of height. */
  max-width: 88ch;
}
.sample-note strong { color: var(--text); font-weight: 570; }
.sample-note[hidden] { display: none; }
#searchPage .sample-note { margin-top: 18px; align-self: flex-start; }

/* The word "Note" as a small lead-in tag, so the block reads as a notice at a
   glance rather than as another paragraph. Inline, not floated: it has to sit
   on the first line of the sentence it introduces and wrap with it. */
.sample-note-tag {
  display: inline-block;
  margin-right: 7px;
  padding: 1px 7px;
  border-radius: 5px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 10.5px;
  font-weight: 640;
  letter-spacing: .05em;
  text-transform: uppercase;
  vertical-align: 1px;
}
/* The link that reaches the page which actually governs. It is the note's one
   action, so it gets a nudge of space rather than running into the sentence. */
.sample-note .link-btn {
  margin-left: 4px;
  color: var(--accent-ink);
  font-size: inherit;
  white-space: nowrap;
}

/* Home: the whole .lp-discover section is centred, so the note is too — and it
   sits under the grid as the section's closing line rather than above it. */
.sample-note--home {
  margin: 22px auto 0;
  text-align: left;
}

/* Visually hidden, still announced and still crawled. Used by the editor's
   route heading (#editorHeading): the toolbar has nowhere to put a visible
   title, but a page with no h1 is a page a crawler cannot categorise.
   clip-path + 1px box is the technique that survives every engine; display:none
   and visibility:hidden would remove it from the accessibility tree too. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}


/* ============ Editor premium chrome (2026-08) ============ */
/* Side panel collapse: width to zero, canvas takes the room (flex does the
   rest). The fixed re-opener survives the overflow clip. */
#side.collapsed { width: 0 !important; border-left: none; overflow: hidden; }
#sideCollapse {
  margin-left: auto; width: 26px; height: 26px; border-radius: 7px;
  color: var(--muted); font-size: 13px; flex: none;
}
#sideCollapse:hover { background: rgba(128, 128, 128, .15); color: var(--text); }
#sideExpand {
  position: fixed; right: 8px; top: 50%; transform: translateY(-50%);
  z-index: 30; width: 26px; height: 52px; border-radius: 8px 0 0 8px;
  background: var(--panel, rgba(128,128,128,.12)); border: 1px solid var(--border);
  border-right: none; color: var(--muted); font-size: 13px;
}
#sideExpand:hover { color: var(--text); }
body.presenting #sideExpand, body.recording #sideExpand, body.watching #sideExpand { display: none; }

/* Hand tool button active state */
#btnHand.active { background: var(--iris, #6d7cff); color: #fff; }

/* The hint bar earns a few seconds, then leaves. Pointer-events were always
   none; now the residency is temporary too. */
#hintBar.hint-fade { animation: hintFade 7s ease forwards; }
@keyframes hintFade { 0%, 78% { opacity: 1; } 100% { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { #hintBar.hint-fade { animation: none; opacity: 0; visibility: hidden; } }


/* Present-order mode banner */
#ckOrderBar {
  position: fixed; z-index: 45; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-radius: var(--r-2, 10px);
  background: var(--glass-bg, rgba(20, 22, 32, .9));
  -webkit-backdrop-filter: var(--glass-blur, blur(10px)); backdrop-filter: var(--glass-blur, blur(10px));
  border: 1px solid var(--border); box-shadow: var(--shadow-sm, 0 8px 24px rgba(0,0,0,.3));
  font-size: 12.5px; color: var(--text);
}
#ckOrderBar[hidden] { display: none; }
#ckOrderBar .ck-order-msg b { color: var(--iris-bright, #8b95ff); }

/* ==========================================================================
   Adaptive Step Guide layout (body.pr-notes-bottom, app.js resolvedNotesLayout)
   --------------------------------------------------------------------------
   Wide documents — timelines, roadmaps, horizontal processes — waste a tall
   side column: the panel moves to the BOTTOM as a compact horizontal band
   (illustration · step text · why insight, side by side) and the diagram
   takes the full width above it. The reserve mechanism is unchanged:
   reserveNotesColumn measures the panel's REAL rect and hands it to the
   layout as canvasWrap padding — bottom mode simply pays with paddingBottom
   instead of paddingRight. Tall or compact documents keep the side panel.
   ======================================================================== */
body.pr-notes-bottom #prNarration {
  left: var(--pr-gutter, 18px) !important;
  right: var(--pr-gutter, 18px) !important;
  top: auto !important;
  /* The same control-bar lane the side panel respects — a band pinned to the
     screen edge slid UNDER the floating dock and its last line of text
     vanished behind the buttons. */
  bottom: var(--pr-lane-bottom, calc(var(--pr-band, 66px) + 12px)) !important;
  width: auto !important;
  min-width: 0 !important;
  height: clamp(180px, 24vh, 240px);
  max-height: 28vh;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 30%);
  /* FOUR rows: head / step chip / title / note. The chip and the title used
     to share row 2 with the title nudged down by margin-top — margins of
     grid items in the same cell don't separate them, so "STEP 6 OF 16"
     rendered THROUGH the title's first line. Rows, not margins. */
  grid-template-rows: auto auto auto 1fr;
  column-gap: 18px;
  align-items: start;
}
body.pr-notes-bottom #prNarrationHead { grid-column: 1 / -1; grid-row: 1; }
body.pr-notes-bottom #prNarrationImg {
  grid-column: 1; grid-row: 2 / 5;
  height: 100%; width: auto; max-width: 30vw;
  align-self: stretch; object-fit: contain;
}
body.pr-notes-bottom #prNoteStep { grid-column: 2; grid-row: 2; }
body.pr-notes-bottom #prNoteTitle { grid-column: 2; grid-row: 3; margin-top: 2px; }
body.pr-notes-bottom #prNarrationText { grid-column: 2; grid-row: 4; overflow-y: auto; max-height: 100%; }
body.pr-notes-bottom #prNoteIcon, body.pr-notes-bottom #prNoteTakeaway { grid-column: 2; grid-row: 4; align-self: end; }
/* "Why this matters" lives at the FOOT of the Step Guide — its ONE home in
   both layouts. A quiet premium card: soft amber-tinted surface, hairline border,
   small outlined chip, no glow. */
#prWhyDock { display: none; }
body.presenting #prNarration:not([data-note-style]) #prWhyDock:not([hidden]),
body.presenting #prNarration[data-note-style="corporate"] #prWhyDock:not([hidden]) {
  display: block;
  margin-top: auto;              /* the flex column pushes it to the foot */
  padding: 11px 13px;
  border-radius: 12px;
  background: rgba(245, 158, 11, .06);
  border: 1px solid rgba(180, 83, 9, .16);
  font-size: 13.5px;
  line-height: 1.45;
}
#prWhyDock .pr-whyd-head {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 6px;
}
#prWhyDock .pr-whyd-chip {
  flex: none; display: grid; place-items: center;
  width: 20px; height: 20px; border-radius: 6px;
  background: rgba(245, 158, 11, .12);
  border: 1px solid rgba(180, 83, 9, .22);
  color: #b45309;
}
#prWhyDock .pr-whyd-chip svg { width: 12px; height: 12px; }
#prWhyDock .pr-why-label {
  font-size: 10px; font-weight: 700; letter-spacing: .11em;
  text-transform: uppercase; color: #b45309;
}
#prWhyDock.pr-whyd-in { animation: prWhyIn .3s cubic-bezier(.22, 1, .36, 1) both; }
@media (prefers-reduced-motion: reduce) { #prWhyDock.pr-whyd-in { animation: none; } }
/* Bottom band: the same card becomes the band's third column. */
body.pr-notes-bottom #prWhyDock:not([hidden]) {
  grid-column: 3; grid-row: 2 / 5;
  align-self: stretch;
  margin-top: 0;
  overflow-y: auto;
}

/* Next / Last stand down while the title card owns the stage. */
body.pr-title-hold #prNext, body.pr-title-hold #prLast {
  opacity: .38; pointer-events: none;
}
/* Collapsed bottom band: a slim reopen rail across the bottom. */
body.pr-notes-bottom.pr-guide-collapsed #prNarration {
  height: 40px; min-height: 40px; width: auto !important;
  grid-template-rows: auto; overflow: hidden; cursor: pointer;
}
body.pr-notes-bottom.pr-guide-collapsed .pr-nh-label { writing-mode: horizontal-tb; }
body.pr-notes-bottom.pr-guide-collapsed #prNarrationHead { flex-direction: row; }
@media (max-width: 900px) {
  body.pr-notes-bottom #prNarration { grid-template-columns: auto minmax(0, 1fr); }
  body.pr-notes-bottom #prWhyDock:not([hidden]) { display: none; }
}

/* ==========================================================================
   Present on tablets and phones
   --------------------------------------------------------------------------
   resolvedNotesLayout already answers "bottom band" for viewports ≤ 1024px;
   these rules make the chrome earn the smaller box: tighter gutters, a
   shorter band, a dock with real tap targets that sheds its specialist
   tools, and a slimmer progress strip. Rotation re-lays through the
   debounced resize hook in app.js.
   ======================================================================== */
@media (max-width: 1024px) {
  body.presenting #canvasWrap { --pr-gutter: 10px; }
  body.pr-notes-bottom #prNarration {
    height: clamp(150px, 26vh, 210px);
    column-gap: 12px;
  }
  body.presenting #prSegBar { max-width: 86vw; top: max(6px, env(safe-area-inset-top)); }
  /* 44px CSS: Apple HIG floor; 48dp Android is met by the 4px gap. */
  #presentBar .pr-btn { min-width: 44px; min-height: 44px; }
}
@media (max-width: 700px) {
  /* PHONES render the show LIGHTWEIGHT: the diagram is the content, so the
     chrome slims to a whisper — 6px gutters, no cover art on the title card
     (the words carry it), a compact nameplate without the doc title or the
     running clock, and the Step Guide starts COLLAPSED (present-plus's
     guideEffectiveCollapsed) so the sheet takes almost the whole screen.
     One tap on the rail brings the notes back. */
  body.presenting #canvasWrap { --pr-gutter: 6px; }
  body.presenting #prTitleCardImgFrame { display: none !important; }
  body.presenting #prTvTitle, body.presenting #prTvHead #prStepTime { display: none; }
  .pr-tv-word { font-size: 13px; }
  body.presenting #prTvHead svg { width: 18px; height: 18px; }
  /* The specialist tools stand down on a phone (their hiding now lives in
     the bar-diet breakpoints above); the dock keeps transport, sound,
     voice, settings, zen and exit — the controls a viewer actually reaches
     for mid-show. */
  body.presenting #prSegBar { gap: 2px; padding: 3px 5px; }
  #prSegBar .pr-seg { min-width: 6px; }
  body.pr-notes-bottom #prNarration {
    height: clamp(132px, 30vh, 190px);
    grid-template-columns: minmax(0, 1fr);
  }
  /* body.presenting joins the selector to out-specify the panel's own
     `:not([hidden])` display rule — same trap CLAUDE.md documents for the
     notes text. */
  body.presenting.pr-notes-bottom #prNarrationImg { display: none !important; }
  /* Author-only placement mode temporarily restores the picture the compact
     viewer normally omits. This is the direct-manipulation handle, so hiding
     it while instructing the author to drag would be a dead-end UI. */
  body.presenting.pr-image-placement-mode.pr-notes-bottom #prNarrationImg:not([hidden]) {
    display: block !important;
    max-height: 104px;
  }
  #presentBar { flex-wrap: wrap; max-width: 96vw; }
}

/* Phones are touch-first players. The whole bottom control console (and any
   popover opened from it) leaves the viewport; left/right stage halves remain
   the transport, while the fixed title/counter keeps orientation. This also
   applies inside blog embeds because the iframe evaluates its own width. */
@media (max-width: 760px), (max-height: 560px) and (max-width: 1024px) {
  body.presenting #presentBar,
  body.presenting .pr-pop,
  body.presenting #prShortcuts { display: none !important; }
  body.presenting #canvasWrap,
  body.presenting #stage { --pr-band: 10px !important; }
  body.presenting #prSubtitle { bottom: max(12px, env(safe-area-inset-bottom)); }
}

/* ---- Premium supporting pane: compact, content-led ---------------------
   The diagram remains the primary pane. The guide is a genuinely supporting
   surface: one slim measured gutter, a quiet outer shell, then image → note
   → insight as one reading group. Previously the 18px canvas gap + 22px
   panel padding + 16–18px note-card padding made a 25% panel feel much wider
   than it was and stranded the insight at the far foot of a mostly empty
   column. This keeps every authored piece visible without spending pixels on
   nested frames. */
body.presenting #canvasWrap { --pr-gutter: 10px; }
body.presenting #prNarration {
  padding: clamp(12px, 1.25vw, 16px);
  border-radius: 12px;
  border-color: rgba(255, 255, 255, .12) !important;
  background:
    linear-gradient(155deg, rgba(255, 255, 255, .055), transparent 38%),
    rgba(13, 16, 28, .96) !important;
  box-shadow: -14px 18px 42px -30px rgba(0, 0, 0, .82) !important;
}
body.presenting #prNarrationHead {
  margin: 0 2px 8px;
  font-size: 11px;
}
body.presenting #prNarrationImg {
  width: 100%;
  max-width: none;
  max-height: min(28%, 190px);
  margin: 0 0 10px;
  object-fit: contain;
  background: rgba(255, 255, 255, .035);
  border-radius: 10px;
  box-shadow: none;
}
body.presenting #prNarration[data-note-style] #prNarrationText,
body.presenting #prNarrationText {
  flex: 0 1 auto;
  min-height: 0;
  max-height: 43%;
  margin: 0;
  padding: 12px 14px;
  border-radius: 10px;
}
body.presenting #prWhyDock:not([hidden]) {
  flex: 0 1 auto;
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  box-shadow: none;
}
body.presenting #prWhyDock .pr-whyd-head { margin-bottom: 4px; }

/* ---- Cinema finish: premium present mode --------------------------------
   The stage uses one restrained night palette. The diagram remains paper and
   therefore the brightest, clearest object; controls and guidance sit one
   depth behind it. Motion is tied to entry/step changes, never a constant
   peripheral spectacle, so it adds anticipation without competing with the
   diagram or narration. Audience skins and Zen deliberately keep their own
   visual language. */
body.presenting:not(.pr-zen):not(.pr-aud-kids):not(.pr-aud-tween) #stage {
  background:
    radial-gradient(900px 520px at 12% -18%, rgba(111, 82, 255, .22), transparent 62%),
    radial-gradient(720px 440px at 104% 110%, rgba(41, 204, 189, .12), transparent 66%),
    linear-gradient(145deg, #090b15 0%, #111225 52%, #080a12 100%);
  background-size: 112% 112%, 118% 118%, 100% 100%;
  animation: pr-stage-aura 18s ease-in-out infinite alternate;
}
@keyframes pr-stage-aura {
  from { background-position: 0% 0%, 100% 100%, 0 0; }
  to { background-position: 8% 5%, 92% 94%, 0 0; }
}
body.presenting:not(.pr-zen) #prTvHead {
  background:
    linear-gradient(90deg, rgba(124, 108, 248, .22), rgba(23, 26, 47, .74) 43%, rgba(56, 205, 190, .10)),
    rgba(10, 12, 23, .82);
  border-color: rgba(164, 151, 255, .30);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .08) inset, 0 12px 30px -24px #000;
}
body.presenting #prTvTitle {
  font-size: clamp(12.5px, 1.05vw, 15px);
  font-weight: 580;
  color: rgba(245, 247, 255, .82);
}
body.presenting #prTvStep {
  font-size: 12px;
  color: rgba(255, 255, 255, .92);
}
/* The authored title is still the document's title, just presented with a
   deliberate light surface rather than the flat grey pill that read as an
   editor control. This applies only while watching; exported/editing SVGs
   retain their authored appearance. */
body.presenting:not(.pr-zen):not(.pr-aud-kids):not(.pr-aud-tween)
  #svgHost g[data-role="doc-title"] rect {
  fill: #f7f5ff !important;
  stroke: rgba(100, 78, 216, .38) !important;
  stroke-width: 1.25 !important;
}
body.presenting:not(.pr-zen) #svgHost g[data-role="doc-title"] text {
  font-weight: 800;
  letter-spacing: -.018em;
}
body.presenting #prNarration {
  color: #f2f4ff !important;
  background:
    linear-gradient(155deg, rgba(158, 145, 255, .13), transparent 34%),
    linear-gradient(180deg, rgba(20, 23, 42, .98), rgba(10, 12, 23, .98)) !important;
  border-color: rgba(190, 183, 255, .17) !important;
}
body.presenting #prNoteStep:not([hidden]) {
  color: #bcb2ff;
  font-size: 10px;
  letter-spacing: .16em;
  margin-bottom: 8px;
}
body.presenting #prNoteTitle:not([hidden]) {
  font-size: clamp(18px, 1.45vw, 22px);
  line-height: 1.18;
  letter-spacing: -.022em;
  margin-bottom: 9px;
}
body.presenting #prNarrationImg {
  background:
    radial-gradient(circle at 50% 0%, rgba(150, 137, 255, .16), transparent 65%),
    rgba(4, 6, 15, .62);
  border: 1px solid rgba(207, 201, 255, .14);
  box-shadow: 0 12px 28px -22px #000;
}
body.presenting #prNarration[data-note-style] #prNarrationText,
body.presenting #prNarrationText {
  font-size: calc(17px * var(--pr-text-k, 1));
  line-height: 1.58;
  color: #edf0ff;
  background: rgba(255, 255, 255, .055);
  border: 1px solid rgba(255, 255, 255, .08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
}
body.presenting #prWhyDock:not([hidden]) {
  background: linear-gradient(135deg, rgba(245, 158, 11, .17), rgba(245, 158, 11, .055));
  border-color: rgba(251, 191, 36, .28);
  color: #fff3d6;
}
body.presenting #prWhyDock.pr-whyd-in {
  animation: pr-why-arrive .42s cubic-bezier(.22, 1, .36, 1) both;
}
@keyframes pr-why-arrive {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
/* One coordinated beat when the panel receives a new step: the visual moves
   first, then the reading surfaces settle. Existing entrance classes are
   preserved; this simply gives their final state more depth. */
body.presenting #prNarration.pr-note-in #prNarrationImg {
  animation: pr-note-media-arrive .52s cubic-bezier(.22, 1, .36, 1) both;
}
@keyframes pr-note-media-arrive {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting:not(.pr-zen):not(.pr-aud-kids):not(.pr-aud-tween) #stage { animation: none; }
  body.presenting #prWhyDock.pr-whyd-in,
  body.presenting #prNarration.pr-note-in #prNarrationImg { animation: none; }
}

/* ---- Visual Step Guide -------------------------------------------------
   The guide is not a second narration document. It is a compact visual
   companion to the diagram: identify the current step, show its image, then
   give the step number and the one insight worth carrying forward. Matching
   the media width for image, counter and insight makes this a composed card
   rather than a vertical list of unrelated panels. */
body.presenting #prNarration {
  --pr-guide-media-w: min(100%, 340px);
  align-items: stretch;
  padding: 8px;
  border-radius: 10px;
  color: var(--pr-sheet-ink) !important;
  background: var(--pr-sheet) !important;
  border-color: color-mix(in srgb, var(--pr-sheet-ink) 8%, transparent) !important;
  box-shadow: -8px 12px 28px -26px rgba(21, 24, 40, .32) !important;
}
body.presenting #prNarrationHead,
body.presenting #prNoteIcon,
body.presenting #prNoteTakeaway,
body.presenting #prNoteTech { display: none !important; }
body.presenting #prNoteTitle:not([hidden]) {
  order: 1;
  display: block;
  margin: 2px 2px 12px;
  color: var(--pr-sheet-ink);
  font: 760 clamp(18px, 1.5vw, 23px)/1.15 var(--sans);
  letter-spacing: -.028em;
}
body.presenting #prNarrationImg:not([hidden]) {
  order: 2;
  align-self: center;
  width: var(--pr-guide-media-w);
  max-width: var(--pr-guide-media-w);
  max-height: min(34%, 230px);
  margin: 0 0 8px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 12px;
  box-shadow: 0 14px 28px -24px rgba(25, 31, 49, .48);
}
body.presenting #prNoteStep:not([hidden]) {
  order: 3;
  align-self: center;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  margin: 0;
  padding: 7px 10px 8px;
  border-top: 1px solid rgba(94, 76, 192, .20);
  color: #5a48ba;
  font: 750 10px/1.1 var(--sans);
  letter-spacing: .13em;
  text-align: center;
  text-transform: uppercase;
}
/* The authored note is the explanation, not optional decoration. Keep it in
   the same measured column as the image and counter, with a quiet reading
   surface rather than the old nested card and its wasted border space. */
body.presenting #prNarration #prNarrationText {
  order: 4;
  display: block !important;
  align-self: center;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  max-height: min(32%, 240px);
  margin: 2px 0 0;
  padding: 0 2px;
  overflow-y: auto;
  color: var(--pr-sheet-ink) !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
  font-size: calc(15px * var(--pr-text-k, 1));
  font-weight: 550;
  line-height: 1.48;
}
/* The step title earns a gentle header of its own, so the guide reads as one
   composed panel: current step → image → explanation → takeaway. */
body.presenting #prNarration #prNoteTitle:not([hidden]) {
  align-self: stretch;
  box-sizing: border-box;
  width: auto;
  margin: -8px -8px 12px;
  padding: 11px 14px;
  color: var(--pr-sheet-ink);
  background: color-mix(in srgb, var(--iris) 5%, var(--pr-sheet));
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--iris) 12%, transparent);
  border-radius: 9px 9px 0 0;
  box-shadow: none;
}
body.presenting #prWhyDock:not([hidden]) {
  order: 5;
  align-self: center;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  margin: 12px 0 0;
  padding: 11px 12px 12px;
  color: #49330c;
  background: linear-gradient(135deg, #fff7df, #fff0c8);
  border: 1px solid rgba(211, 150, 31, .32);
  border-left: 3px solid #d89822;
  border-radius: 0 11px 11px 0;
  box-shadow: 0 10px 22px -20px rgba(119, 75, 8, .52);
}
/* Out-specifies the legacy "push to the foot" rule: the insight belongs
   directly below its note, never stranded at the bottom of an empty panel. */
body.presenting #prNarration #prWhyDock:not([hidden]) { margin-top: 10px; }
body.presenting #prWhyDock .pr-whyd-head { margin-bottom: 5px; }
body.presenting #prWhyDock .pr-why-label { color: #9a6511; }
body.presenting #prWhyDock .pr-whyd-chip {
  width: 19px;
  height: 19px;
  color: #7e4d04;
  background: rgba(216, 152, 34, .16);
  border-color: rgba(190, 122, 16, .25);
}
/* The normal title bar uses the actual sheet palette. Its border and the
   violet step control provide the hierarchy; no dark band sits above a light
   diagram anymore. */
body.presenting:not(.pr-zen) #prTvHead {
  color: var(--pr-sheet-ink);
  background: var(--pr-sheet) !important;
  border-color: color-mix(in srgb, var(--iris) 32%, transparent);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .72) inset, 0 8px 22px -22px rgba(21, 24, 40, .6);
}
body.presenting:not(.pr-zen) .pr-tv-word { color: var(--pr-sheet-ink); }
body.presenting:not(.pr-zen) #prTvTitle { color: var(--pr-sheet-ink); font-weight: 700; }
body.presenting:not(.pr-zen) #prTvTitle:not(:empty)::before { color: color-mix(in srgb, var(--pr-sheet-ink) 55%, transparent); }
body.presenting:not(.pr-zen) #prStepTime { color: color-mix(in srgb, var(--pr-sheet-ink) 62%, transparent); }
body.presenting:not(.pr-zen) #prTvNav {
  background: color-mix(in srgb, var(--pr-sheet) 84%, var(--iris));
  border-color: color-mix(in srgb, var(--pr-sheet-ink) 13%, transparent);
}
body.presenting:not(.pr-zen) #prTvStep,
body.presenting:not(.pr-zen) #prTvNav button { color: var(--pr-sheet-ink); }

/* ---- Engagement strip on the Present nameplate (.eng-strip--present) ----
   Views · watch time · like, riding the dark TV chrome during a show — same
   element the tiles use, so counts and the like state stay one system. */
#prTvHead .eng-strip--present {
  margin: 0 10px 0 auto;
  padding: 0;
  border-top: 0;
  font-size: 11.5px;
  color: rgba(233, 236, 255, .62);
  gap: 9px;
}
#prTvHead .eng-strip--present .eng-like,
#prTvHead .eng-strip--present .eng-share {
  color: rgba(233, 236, 255, .62);
  margin-left: 0;
}
#prTvHead .eng-strip--present .eng-like:hover,
#prTvHead .eng-strip--present .eng-share:hover {
  color: #fff;
  background: rgba(233, 236, 255, .1);
}
#prTvHead .eng-strip--present .eng-like.is-on { color: var(--iris-bright, #8b80ff); }
@media (max-width: 700px) {
  /* Phones keep the strip but shed the share button — the end slide carries
     sharing, and the slim nameplate has exactly this much room. */
  #prTvHead .eng-strip--present .eng-share { display: none; }
  #prTvHead .eng-strip--present { font-size: 11px; gap: 7px; }
}


/* ---- Engagement on the TITLE SLIDE (.eng-strip--title) ------------------
   Views · watch time · like · share, centered right under the heading — the
   same live element the tiles carry, dressed for the card's light ground.
   The dock's own thumb (#prLikeBtn) keeps liking one tap away for the whole
   run on every device. */
#prTitleCard .eng-strip--title {
  margin: 14px 0 2px;
  padding: 6px 14px;
  border-top: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--pr-sheet-ink, currentColor) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--pr-sheet-ink, currentColor) 14%, transparent);
  justify-content: center;
  align-self: center;
  width: max-content;
  font-size: 14.5px;
  font-weight: 600;
  color: color-mix(in srgb, var(--pr-sheet-ink, currentColor) 76%, transparent);
  gap: 16px;
}
#prTitleCard .eng-strip--title svg { width: 17px; height: 17px; }
#prTitleCard .eng-strip--title .eng-like,
#prTitleCard .eng-strip--title .eng-share {
  margin-left: 0;
  color: color-mix(in srgb, var(--pr-sheet-ink, currentColor) 68%, transparent);
  pointer-events: auto;
}
#prTitleCard .eng-strip--title .eng-like:hover,
#prTitleCard .eng-strip--title .eng-share:hover {
  color: var(--pr-sheet-ink, currentColor);
  background: color-mix(in srgb, var(--pr-sheet-ink, currentColor) 11%, transparent);
}
#prTitleCard .eng-strip--title .eng-like.is-on { color: var(--iris-bright, var(--iris-deep, #5546e6)); }

#prLikeBtn .pr-like-count { font-size: 10.5px; font-weight: 700; margin-left: 2px; }
#prLikeBtn.is-on { color: var(--iris-bright, #8b80ff); }
#prLikeBtn.is-on svg { fill: color-mix(in srgb, var(--iris-bright, #8b80ff) 25%, transparent); }

/* ============================================================
   Diagrams by role  (/roles)  — js/roles.js + js/role-profiles.js
   ------------------------------------------------------------
   Tokens only, and only ones that EXIST: --chrome / --panel / --panel-2,
   --text / --muted / --faint, --border / --border-soft, --accent, --iris-*.
   An unknown custom property fails silently to its fallback and looks perfect
   in dark while staying wrong in light, which is the trap CLAUDE.md documents.
   Both themes are exercised here; the light one is the one nobody screenshots.
   ============================================================ */
#rolesPage {
  position: fixed; inset: 0; z-index: 60; overflow-y: auto; overscroll-behavior: contain;
  background: var(--chrome); color: var(--text);
}
/* One bar. Free-floating fixed controls let the sticky rail scroll underneath
   them, which read as chips sliding behind the account button. */
.roles-topbar {
  position: sticky; top: 0; z-index: 4; display: flex; align-items: center; gap: 14px;
  height: 56px; padding: 0 20px;
  background: var(--chrome); border-bottom: 1px solid var(--border-soft);
}
.roles-home {
  flex: 0 0 auto; width: 30px; height: 30px; display: grid; place-items: center;
  color: var(--text); opacity: .82; transition: opacity .18s ease;
}
.roles-home:hover { opacity: 1; }
.roles-home svg { width: 100%; height: 100%; }
.roles-explore {
  font-size: 13px; font-weight: 550; color: var(--muted);
  text-decoration: none; letter-spacing: -0.01em;
}
.roles-explore:hover { color: var(--text); }

/* ---- hero ---- */
.roles-hero { max-width: 780px; margin: 0 auto; padding: 54px 24px 26px; text-align: center; }
.roles-eyebrow {
  display: inline-block; font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 14px;
}
.roles-title {
  margin: 0 0 12px; font-size: clamp(28px, 4.6vw, 44px); line-height: 1.08;
  letter-spacing: -0.028em; font-weight: 620; color: var(--text);
}
.roles-sublede { margin: 0 auto; max-width: 620px; font-size: 15.5px; line-height: 1.62; color: var(--muted); }

/* ---- role picker: a searchable combobox ----
   A dropdown rather than a scrolling chip rail — the role list is meant to
   grow, and a horizontal scroller hides everything past the fourth item. */
.roles-pickwrap {
  position: sticky; top: 56px; z-index: 3;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 14px 24px 14px;
  background: color-mix(in srgb, var(--chrome) 94%, transparent);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--border-soft);
}
.roles-pick { position: relative; width: min(460px, 100%); }
.roles-pick-emoji {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  font-size: 17px; line-height: 1; pointer-events: none;
}
.roles-pick-input {
  width: 100%; box-sizing: border-box; padding: 11px 38px 11px 40px;
  border-radius: 11px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text);
  font: inherit; font-size: 14.5px; font-weight: 540; letter-spacing: -0.012em;
  transition: border-color .16s ease, background .16s ease;
}
.roles-pick-input::placeholder { color: var(--faint); font-weight: 450; }
.roles-pick-input:focus { outline: none; border-color: var(--accent); background: var(--panel-2); }
.roles-pick.open .roles-pick-input { border-color: var(--accent); border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.roles-pick-caret {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 24px; height: 24px; display: grid; place-items: center;
  background: none; border: 0; cursor: pointer; color: var(--faint); padding: 0;
}
.roles-pick-caret svg { width: 18px; height: 18px; transition: transform .18s ease; }
.roles-pick.open .roles-pick-caret svg { transform: rotate(180deg); }

.roles-pick-list {
  position: absolute; left: 0; right: 0; top: calc(100% - 1px); z-index: 5;
  margin: 0; padding: 5px; list-style: none; max-height: 330px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--accent); border-top: 0;
  border-radius: 0 0 11px 11px; box-shadow: 0 18px 40px rgba(0,0,0,.28);
}
.roles-pick-opt {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px;
  border-radius: 8px; cursor: pointer;
}
.roles-pick-opt.active, .roles-pick-opt:hover { background: var(--panel-2); }
.roles-pick-opt.current { box-shadow: inset 2px 0 0 var(--accent); }
.roles-pick-oe { font-size: 16px; line-height: 1.3; flex: 0 0 auto; }
.roles-pick-ot { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.roles-pick-on { font-size: 13.5px; font-weight: 560; color: var(--text); }
.roles-pick-od { font-size: 12px; color: var(--muted); line-height: 1.4; }
.roles-pick-empty { padding: 14px 10px; font-size: 13px; color: var(--faint); text-align: center; }
.roles-pick-count { font-size: 12px; color: var(--faint); white-space: nowrap; }

/* ---- body ---- */
.roles-body { max-width: 1180px; margin: 0 auto; padding: 34px 24px 96px; }

/* identity */
.roles-identity { display: flex; align-items: flex-start; gap: 18px; margin-bottom: 20px; }
.roles-id-mark {
  flex: 0 0 auto; width: 58px; height: 58px; display: grid; place-items: center;
  font-size: 30px; line-height: 1; border-radius: 16px;
  background: var(--panel-2); border: 1px solid var(--border-soft);
}
.roles-id-name { margin: 2px 0 4px; font-size: 27px; font-weight: 620; letter-spacing: -0.024em; color: var(--text); }
.roles-id-tag { margin: 0; font-size: 15px; color: var(--muted); line-height: 1.5; }
.roles-also { margin-top: 7px; font-size: 12.5px; color: var(--faint); }

.roles-measured {
  position: relative; margin: 0 0 22px; padding: 16px 18px 16px 20px;
  border-left: 3px solid var(--accent); border-radius: 0 12px 12px 0;
  background: var(--panel);
}
.roles-measured-label {
  display: block; font-family: var(--mono, ui-monospace, monospace); font-size: 10px;
  letter-spacing: .13em; text-transform: uppercase; color: var(--accent); margin-bottom: 5px;
}
.roles-measured p { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--text); }

.roles-inds { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-bottom: 40px; }
.roles-sub { font-size: 12px; color: var(--faint); margin-right: 3px; }
.roles-ind {
  font-size: 12px; padding: 4px 10px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border-soft); color: var(--muted);
}

/* sections */
.roles-sec { margin-bottom: 46px; }
.roles-h2 { margin: 0 0 5px; font-size: 19px; font-weight: 600; letter-spacing: -0.02em; color: var(--text); }
.roles-lede { margin: 0 0 18px; font-size: 13.5px; color: var(--muted); }

/* ceremonies */
.roles-cers { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.roles-cer {
  padding: 15px 17px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--border-soft);
}
.roles-cer-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 5px; }
.roles-cer-name { font-size: 14.5px; font-weight: 570; color: var(--text); }
.roles-cadence {
  font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent);
  padding: 3px 8px; border-radius: 999px; background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.roles-cer-purpose { margin: 0 0 7px; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.roles-cer-brings { margin: 0; font-size: 13px; line-height: 1.5; color: var(--text); opacity: .92; }
.roles-cer-brings span { color: var(--accent); margin-right: 4px; }

/* phases */
.roles-phases {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); gap: 10px;
}
.roles-phase {
  position: relative; display: flex; flex-direction: column; gap: 5px;
  padding: 15px 16px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--border-soft);
}
.roles-phase-n {
  width: 22px; height: 22px; display: grid; place-items: center; border-radius: 999px;
  font-size: 11px; font-weight: 640; color: var(--on-signal, #fff); background: var(--accent);
}
.roles-phase-name { font-size: 14px; font-weight: 570; color: var(--text); }
.roles-phase-what { font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.roles-phase-draws { font-size: 12px; line-height: 1.5; color: var(--faint); border-top: 1px solid var(--border-soft); padding-top: 7px; margin-top: 2px; }

/* the diagram cards */
.roles-needs { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 12px; }
.roles-need {
  display: flex; flex-direction: column; gap: 7px; text-align: left; cursor: pointer;
  padding: 16px 17px 14px; border-radius: 13px;
  background: var(--panel); border: 1px solid var(--border-soft); color: inherit;
  font: inherit; transition: border-color .16s ease, background .16s ease, transform .16s ease;
}
.roles-need:hover { border-color: var(--accent); background: var(--panel-2); transform: translateY(-2px); }
.roles-need-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.roles-mode {
  font-family: var(--mono, ui-monospace, monospace); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--accent);
}
.roles-freq { font-size: 11px; color: var(--faint); }
.roles-need-title { margin: 0; font-size: 14.5px; font-weight: 575; line-height: 1.35; letter-spacing: -0.012em; color: var(--text); }
.roles-need-why { margin: 0; font-size: 12.8px; line-height: 1.52; color: var(--muted); flex: 1 1 auto; }
.roles-need-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 5px; padding-top: 10px; border-top: 1px solid var(--border-soft);
}
.roles-cta { font-size: 12.5px; font-weight: 550; color: var(--muted); }
.roles-need:hover .roles-cta { color: var(--text); }
.roles-cta.ready { color: var(--accent); }
.roles-badge {
  font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent);
}

@media (max-width: 640px) {
  .roles-hero { padding: 40px 18px 20px; }
  .roles-body { padding: 26px 16px 72px; }
  .roles-pickwrap { padding: 12px 16px; }
  .roles-pick-count { display: none; }
  .roles-identity { gap: 13px; }
  .roles-id-mark { width: 48px; height: 48px; font-size: 25px; }
  .roles-id-name { font-size: 22px; }
  .roles-needs { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .roles-need, .roles-home, .roles-pick-input, .roles-pick-caret svg { transition: none; }
  .roles-need:hover { transform: none; }
}
/* The by-role entry sits in the subject row but is a different KIND of browse
   — job, not topic — so it carries the accent rather than blending in. */
.lp-coll-roles { border-color: color-mix(in srgb, var(--accent) 45%, transparent); color: var(--text); }
.lp-coll-roles:hover { border-color: var(--accent); }
/* The sample sketch on a role card. A real template shows its own icon_svg; an
   unbuilt one shows the SHAPE of its diagram type, which is what answers
   "what am I about to get?" before the click. */
.roles-thumb {
  display: block; margin: -4px -5px 9px; border-radius: 9px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border-soft);
  aspect-ratio: 150 / 90;
}
.roles-thumb-svg { width: 100%; height: 100%; display: block; padding: 9px 11px; box-sizing: border-box; }
/* Sketches are line art in the muted ink, with one accent element for focus. */
.roles-thumb-sketch { color: var(--muted); opacity: .85; }
.roles-thumb-sketch .a { stroke: var(--accent); }
.roles-need:hover .roles-thumb-sketch { opacity: 1; color: var(--text); }
/* A real template's artwork carries its own colours — do not tint it. */
.roles-thumb.is-real { background: var(--chrome); }
.roles-thumb.is-real .roles-thumb-svg { padding: 6px 8px; }
@media (prefers-reduced-motion: reduce) { .roles-thumb-sketch { transition: none; } }
/* Role matches on /search — a shortcut above the diagram grid, not a competing
   result set, so it is capped at three and styled as rows rather than tiles. */
.srch-roles { display: grid; gap: 6px; margin: 0 auto 22px; max-width: 720px; width: 100%; }
.srch-roles-head {
  margin: 0 0 2px; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.srch-role {
  display: flex; align-items: center; gap: 11px; padding: 11px 14px;
  border-radius: 11px; text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--border-soft);
  transition: border-color .16s ease, background .16s ease;
}
.srch-role:hover { border-color: var(--accent); background: var(--panel-2); }
.srch-role-emoji { font-size: 19px; line-height: 1; flex: 0 0 auto; }
.srch-role-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.srch-role-name { font-size: 14px; font-weight: 570; color: var(--text); }
.srch-role-tag { font-size: 12.3px; color: var(--muted); line-height: 1.4; }
.srch-role-n {
  flex: 0 0 auto; font-size: 11.5px; font-weight: 560; color: var(--accent);
  padding: 3px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
@media (max-width: 640px) { .srch-role-n { display: none; } }

/* ============================================================
   Open a diagram — the recall path (js/open-diagram.js)
   Tokens copied from .lp-tpl-card, the reference card: --chrome / --panel /
   --panel-2, --text / --muted / --faint, --border / --border-soft, --accent.
   Never invent a custom property here — an unknown one fails SILENTLY to its
   fallback and looks correct in exactly one theme (CLAUDE.md).
   ============================================================ */
/* Lives inside .lp-hero-copy, so it takes the column's width rather than
   centring itself in the page. */
.od-resume {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 14px; margin: 18px 0 0; padding: 14px 16px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--chrome);
}
.od-resume-copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 320px; }
.od-resume-head { font-size: 14.5px; font-weight: 560; letter-spacing: -0.01em; color: var(--text); }
.od-resume-sub { font-size: 13px; line-height: 1.6; color: var(--muted); font-weight: 400; }
.od-resume-sub b { color: var(--text); font-weight: 560; }
/* SOFT accent treatment, deliberately a step below .lp-btn-primary: two
   filled accent buttons in the same viewport read as two primary actions,
   and "Start creating" is the one this page leads with. --accent-ink on
   --accent-soft is the pairing built for exactly this (see .lp-tbtn:hover),
   and it survives every accent palette — the old accent-filled version
   hardcoded #fff, which fails on the amber/lime/sky accents. */
.od-resume-btn {
  flex: 0 0 auto; font: inherit; font-size: 14px; font-weight: 570; cursor: pointer;
  color: var(--accent-ink); background: var(--accent-soft);
  border: 1px solid var(--accent-ring);
  border-radius: 10px; padding: 10px 18px;
  transition: filter var(--dur-2) var(--ease-out), background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.od-resume-btn:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 24%, transparent); }
.od-resume-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (max-width: 640px) { .od-resume { margin-inline: 16px; } .od-resume-btn { width: 100%; } }

#odDialog { position: fixed; inset: 0; z-index: 9000; display: flex;
  align-items: center; justify-content: center; padding: 24px; }
#odDialog[hidden] { display: none; }
#odScrim { position: absolute; inset: 0; background: rgba(6, 8, 14, .62); backdrop-filter: blur(2px); }
.od-panel {
  position: relative; width: min(560px, 100%); max-height: min(78vh, 680px);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--chrome); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
}
.od-head { position: relative; padding: 20px 22px 14px; border-bottom: 1px solid var(--border-soft); }
.od-head h2 { margin: 0 0 5px; font-size: 18px; font-weight: 660; letter-spacing: -0.015em; color: var(--text); }
.od-head p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--muted); padding-right: 30px; }
.od-close { position: absolute; top: 14px; right: 14px; width: 30px; height: 30px;
  font: inherit; font-size: 21px; line-height: 1; cursor: pointer; color: var(--faint);
  background: transparent; border: 1px solid transparent; border-radius: 8px; }
.od-close:hover { color: var(--text); border-color: var(--border); }
.od-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.od-list { list-style: none; margin: 0; padding: 8px; overflow-y: auto; flex: 1; }
.od-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; font: inherit; text-align: left; cursor: pointer;
  padding: 11px 13px; border: 1px solid transparent; border-radius: 10px;
  background: transparent; color: inherit;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out); }
.od-row:hover { background: var(--panel); border-color: var(--border-soft); }
.od-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.od-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.od-row-title { font-size: 14.5px; font-weight: 570; letter-spacing: -0.01em; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.od-row-tool { font-family: var(--mono); font-size: 10.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--faint); }
.od-row-go { flex: 0 0 auto; font-size: 12.5px; font-weight: 600; color: var(--accent); opacity: 0; }
.od-row:hover .od-row-go, .od-row:focus-visible .od-row-go { opacity: 1; }

.od-empty { margin: 0; padding: 26px 22px; font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.od-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 10px; padding: 13px 18px; border-top: 1px solid var(--border-soft); background: var(--panel-2); }
.od-foot-note { font-size: 12px; color: var(--faint); }
.od-foot-btn { font: inherit; font-size: 13px; font-weight: 570; cursor: pointer;
  color: var(--text); background: transparent; border: 1px solid var(--border);
  border-radius: 9px; padding: 7px 13px; }
.od-foot-btn:hover { border-color: var(--accent); }
.od-foot-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
body.od-open { overflow: hidden; }

/* The top-bar entry — always reachable, not only after scrolling the hero. */
.od-top-btn[hidden] { display: none; }
.od-last {
  display: inline-block; margin-left: 8px; vertical-align: 1px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--accent); border: 1px solid var(--accent);
  border-radius: 999px; padding: 1px 7px;
}

/* ========================================================================
   Zen-first Present quick rail + visual themes
   ------------------------------------------------------------------------
   The default show is deliberately content-first. The rail keeps only the
   actions someone reaches for while speaking: step, focus, guide/narration,
   palette, more and leave. Specialist ink tools, audience skins and timing
   remain available in More without taking over the screen.
   ======================================================================== */
body.presenting #stage {
  background: var(--pr-stage, #0b0d14);
}
body.presenting #presentBar {
  gap: 6px;
  padding: 6px 8px;
  background: color-mix(in srgb, var(--pr-panel, #121625) 92%, transparent);
  border-color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 14%, transparent);
  box-shadow: 0 14px 34px -18px color-mix(in srgb, var(--pr-stage, #0b0d14) 82%, #000);
}
body.presenting #prRestart,
body.presenting #prFirst,
body.presenting #prLast,
body.presenting #prSpeedCycle,
body.presenting .prc-status,
body.presenting #prLikeBtn,
body.presenting #prMuteToggle,
body.presenting #prCaptionToggle,
body.presenting #prSmartToggle,
body.presenting #prAudienceCycle,
body.presenting #prToolLaser,
body.presenting #prToolPen,
body.presenting #prToolSpot,
body.presenting #prPin,
body.presenting #prZenToggle { display: none; }
body.presenting #prFocusToggle.on,
body.presenting #prFocusToggle[aria-pressed="true"] {
  color: var(--pr-stage-ink, #e9ecff);
  background: color-mix(in srgb, var(--pr-focus, var(--iris)) 32%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-focus, var(--iris)) 50%, transparent) inset,
              0 0 14px -7px var(--pr-focus, var(--iris));
}
body.presenting #prThemeToggle {
  color: color-mix(in srgb, var(--iris-bright) 82%, var(--pr-stage-ink, #e9ecff));
}
body.presenting #prVoiceToggle[aria-pressed="true"],
body.presenting #prNarrationToggle.on {
  color: var(--pr-stage-ink, #e9ecff);
}

/* The quick palette sits in the same visual language as the compact rail,
   but remains a real radio group for keyboard and assistive-tech users. */
body.presenting .pr-pop {
  color: var(--pr-stage-ink, #e9ecff);
  background: color-mix(in srgb, var(--pr-panel, #121625) 94%, transparent);
  border-color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 14%, transparent);
}
body.presenting .pr-pop-h,
body.presenting .pr-pop .pr-check,
body.presenting .pr-pop .pr-slider-row { color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 84%, transparent); }
body.presenting .pr-pop .pr-mini,
body.presenting .pr-pop select,
body.presenting .pr-pop .pr-voice-row select {
  color: var(--pr-stage-ink, #e9ecff);
  background: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 7%, transparent);
  border-color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 15%, transparent);
}
.pr-theme-pop { width: min(312px, calc(100% - 28px)); }
.pr-visual-theme-grid { display: grid; gap: 7px; }
.pr-visual-theme {
  display: flex; align-items: center; gap: 11px; width: 100%; padding: 9px;
  color: inherit; text-align: left; font: inherit; cursor: pointer;
  background: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 11%, transparent);
  border-radius: 11px;
  transition: transform .16s var(--ease-out), background .16s var(--ease-out), border-color .16s var(--ease-out);
}
.pr-visual-theme:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 9%, transparent); }
.pr-visual-theme.on {
  border-color: color-mix(in srgb, var(--iris-bright) 70%, transparent);
  background: color-mix(in srgb, var(--iris) 20%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--iris) 28%, transparent) inset;
}
.pr-visual-theme > span:last-child { display: grid; gap: 2px; min-width: 0; }
.pr-visual-theme b { font-size: 12.5px; font-weight: 680; }
.pr-visual-theme small { color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 62%, transparent); font-size: 11px; line-height: 1.3; }
.pr-theme-subhead { padding: 7px 2px 6px; }
.pr-doc-theme-shortcut {
  margin-bottom: 3px;
  border-color: color-mix(in srgb, #b18a3d 48%, transparent);
  background: linear-gradient(135deg,
    color-mix(in srgb, #742d38 22%, transparent),
    color-mix(in srgb, #b18a3d 12%, transparent));
}
.pr-doc-theme-shortcut.on {
  border-color: #b18a3d;
  box-shadow: 0 0 0 1px color-mix(in srgb, #b18a3d 28%, transparent) inset;
}
.pr-doc-theme-shortcut b em,
.tc6-new {
  display: inline-block; margin-left: 4px; padding: 1px 5px;
  border-radius: 999px; font-style: normal; font-size: 8.5px;
  font-weight: 800; line-height: 1.35; letter-spacing: .06em;
  text-transform: uppercase; vertical-align: .12em;
  color: #fff8e8; background: #742d38;
}
.pr-vt-swatch {
  width: 34px; height: 30px; flex: none; border-radius: 8px;
  border: 1px solid rgba(255,255,255,.20); box-shadow: inset 0 1px rgba(255,255,255,.28);
}
.pr-vt-current { background: linear-gradient(135deg, #eef2ff 0 47%, #6366f1 48% 68%, #1f2937 69%); }
.pr-vt-notebook {
  background:
    linear-gradient(90deg, transparent 0 11%, rgba(116,45,56,.35) 12% 13%, transparent 14%),
    repeating-linear-gradient(0deg, #fbf6e8 0 6px, #d7ddec 7px 8px);
  box-shadow: inset 4px 0 #742d38, inset 0 1px rgba(255,255,255,.6);
}
.pr-vt-aurora { background: linear-gradient(135deg, #0e1330 0 45%, #8b5cf6 46% 65%, #22d3ee 66%); }
.pr-vt-gallery { background: linear-gradient(135deg, #fbf8f1 0 45%, #b8912f 46% 66%, #2b2517 67%); }
.pr-theme-note { margin: 10px 1px 0; color: color-mix(in srgb, var(--pr-stage-ink, #e9ecff) 60%, transparent); font-size: 11px; line-height: 1.45; }

/* Zen remains one continuous canvas — a stage theme colours the small control
   surfaces, while the diagram, title, splash and end card retain the chosen
   sheet as their shared background. The focus lens intentionally uses the
   same sheet-aware treatment above; Zen must not reintroduce a dark curtain. */
body.pr-zen.presenting #stage { background: var(--pr-sheet, #fff); }

@media (max-width: 760px), (max-height: 560px) and (max-width: 1024px) {
  /* Keep only the actual on-stage controls on a phone: guide/notes is still
     one tap away, while voice, palette and full-screen live in More. */
  body.presenting #prNarrationToggle,
  body.presenting #prFocusToggle { display: inline-flex !important; }
  body.presenting #prVoiceToggle,
  body.presenting #prThemeToggle,
  body.presenting #prFull { display: none !important; }
}

/* ========================================================================
   Zen guide — one calm reading composition
   ------------------------------------------------------------------------
   The guide's footprint is deliberately still measured by app.js: that is
   what keeps the SVG and panel from ever overlapping.  These are only the
   contents of that measured space.  Earlier iterations used a flex column
   and several competing note-style cards, which made a short note look like
   a card stranded in a tall empty drawer.  The final layer makes the title,
   picture, step tag, authored narration and insight explicit grid regions.
   Empty image/Why regions are published by updatePresentNarration(), so a
   sparse step gives its room back to the content that actually exists.
   ======================================================================== */
body.presenting:not(.pr-guide-collapsed) #prNarration {
  /* One shared measure keeps image, count, narration and insight visually
     locked together; only the title deliberately reaches the panel edge. */
  /* The image, narrative and insight share one actual reading measure.  The
     old 356px cap made artwork look like a thumbnail in a roomy guide while
     the explanation continued much wider beside it. */
  --pr-guide-media-w: calc(100% - 28px);
  display: grid !important;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto auto auto auto;
  grid-template-areas:
    "title"
    "media"
    "step"
    "note"
    "presenter"
    "why";
  align-content: start;
  align-items: start;
  box-sizing: border-box;
  gap: 0;
  padding: 0 !important;
  overflow: hidden;
  color: var(--pr-sheet-ink) !important;
  background: var(--pr-sheet) !important;
  border: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
}
/* Keep the structural visibility contracts ahead of this visual override.
   The guide is deliberately absent in a no-notes Zen show, a hidden embed or
   during recording even though its normal composition uses `display:grid`. */
body.presenting #prNarration[hidden],
body.pr-zen.presenting:not(.pr-zen-notes) #prNarration,
body.embed-mode.embed-notes-hidden.presenting #prNarration,
body.recording #prNarration { display: none !important; }
/* These are editor/presenter affordances, not part of the live reading grid.
   Keeping them explicitly out of grid auto-placement is important: a stale
   editor list must never manufacture an implicit row
   between an authored title and its image.  Collapsed mode restores only its
   small guide head below. */
body.presenting:not(.pr-guide-collapsed) #prNarrationHead,
body.presenting:not(.pr-guide-collapsed) #prNoteIcon,
body.presenting:not(.pr-guide-collapsed) #prNoteTakeaway,
body.presenting:not(.pr-guide-collapsed) #prNoteTech,
body.presenting:not(.pr-guide-collapsed) #prNarrationEdit,
body.presenting:not(.pr-guide-collapsed) #prNarrationEditBtns,
body.presenting:not(.pr-guide-collapsed) #prNarrationList { display: none !important; }
/* A side guide is part of the sheet rather than a raised slab.  The one
   hairline is enough to separate reading context from the diagram. */
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration.pos-right {
  border-left: 1px solid color-mix(in srgb, var(--pr-sheet-ink) 11%, transparent) !important;
}
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration.pos-left {
  border-right: 1px solid color-mix(in srgb, var(--pr-sheet-ink) 11%, transparent) !important;
}
body.presenting:not(.pr-guide-collapsed) #prNarration #prNoteTitle:not([hidden]) {
  grid-area: title;
  display: block;
  align-self: stretch;
  box-sizing: border-box;
  width: auto;
  margin: 0 !important;
  padding: clamp(11px, 1.45vw, 15px) clamp(14px, 1.7vw, 20px);
  color: var(--pr-sheet-ink);
  background: color-mix(in srgb, var(--iris) 6%, var(--pr-sheet));
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--iris) 15%, transparent);
  border-radius: 0;
  box-shadow: none;
  font: 740 clamp(17px, 1.45vw, 22px)/1.18 var(--sans);
  letter-spacing: -.024em;
}
body.presenting:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  grid-area: media;
  display: block;
  justify-self: center;
  align-self: center;
  box-sizing: border-box;
  /* The picture stands on its own — no back tile. `width: auto` with the two
     max bounds shrink-wraps the element to the image's fitted size (replaced
     elements keep their aspect inside max-w/max-h), so `contain` never
     letterboxes and there are no filler bands for a tile to show through.
     Generated art (448-640px sources) always exceeds the ~340px measure, so
     the tiny-intrinsic-thumbnail hazard the width forcing guarded against
     does not bite; a rare smaller picture renders at its honest size. */
  width: auto;
  max-width: var(--pr-guide-media-w);
  height: auto;
  max-height: min(31vh, 280px);
  margin: 12px 14px 7px !important;
  padding: 0;
  object-fit: contain;
  background: transparent;
  border: 0;
  border-radius: 10px;
  box-shadow: none;
}
/* This needs the data-note-style selector too: an earlier legacy rule with
   two IDs otherwise restores `width:auto` and turns a full reading image into
   a tiny intrinsic thumbnail.  Side-guide artwork deliberately shares the
   narration measure, giving the panel one calm, aligned column. */
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]),
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  width: auto !important;
  max-width: var(--pr-guide-media-w) !important;
  height: auto !important;
  max-height: min(39vh, 320px) !important;
  margin: 12px 14px 7px !important;
}
/* No back tile behind the picture (viewer feedback, Aug 2026): the legacy
   note-style rules carry two-ID selectors, so the fill/shadow/hairline must
   be cleared at guide strength or they win the cascade. The default
   (corporate) style is fully frameless; kids/classroom/tech keep their
   character borders — which now hug the shrink-wrapped picture instead of
   framing a padded slab. */
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]) {
  background: transparent;
  box-shadow: none;
}
body.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style="corporate"] #prNarrationImg:not([hidden]) {
  border: 0;
}
/* The small count stays under the picture and uses its same reading measure,
   so it never looks like a detached toolbar control. */
body.presenting:not(.pr-guide-collapsed) #prNarration #prNoteStep:not([hidden]) {
  grid-area: step;
  justify-self: center;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  margin: 0 !important;
  padding: 7px 3px 8px;
  color: color-mix(in srgb, var(--iris) 76%, var(--pr-sheet-ink));
  background: transparent;
  border-top: 1px solid color-mix(in srgb, var(--iris) 18%, transparent);
  border-bottom: 0;
  border-radius: 0;
  font: 730 10px/1.1 var(--sans);
  letter-spacing: .13em;
  text-align: left;
  text-transform: uppercase;
}
body.presenting:not(.pr-guide-collapsed) #prNarration #prNarrationText {
  grid-area: note;
  display: block !important;
  justify-self: center;
  align-self: start;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  min-height: 0;
  max-height: min(23vh, 208px) !important;
  margin: 0 !important;
  padding: 2px 2px 0 !important;
  overflow-y: auto;
  color: var(--pr-sheet-ink) !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
  font-size: calc(15px * var(--pr-text-k, 1));
  line-height: 1.5;
}
#prStoryPresenterNotes { display: none; }
body.watching #prStoryPresenterNotes,
body.embed-mode #prStoryPresenterNotes { display: none !important; }
body.presenting:not(.pr-guide-collapsed) #prStoryPresenterNotes:not([hidden]) {
  grid-area: presenter;
  display: block;
  justify-self: center;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  max-height: min(15vh, 116px);
  margin: 9px 0 0;
  padding: 9px 11px 10px;
  overflow-y: auto;
  color: var(--pr-sheet-ink);
  background: color-mix(in srgb, var(--iris) 7%, var(--pr-sheet));
  border: 1px dashed color-mix(in srgb, var(--iris) 34%, transparent);
  border-radius: 9px;
  font-size: calc(12px * var(--pr-text-k, 1));
  line-height: 1.38;
}
body.presenting:not(.pr-guide-collapsed) #prStoryPresenterNotes .pr-story-presenter-label {
  margin-bottom: 4px;
  color: color-mix(in srgb, var(--iris) 77%, var(--pr-sheet-ink));
  font: 760 9px/1.1 var(--sans);
  letter-spacing: .11em;
  text-transform: uppercase;
}
/* The insight is a real supporting tile, not a second brand colour.  It
   inherits the selected Present palette through the sheet/iris tokens and
   remains visible in every note-style preset. */
body.presenting:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  grid-area: why;
  display: block !important;
  justify-self: center;
  align-self: start;
  box-sizing: border-box;
  width: var(--pr-guide-media-w);
  max-height: min(18vh, 150px);
  margin: 11px 0 14px !important;
  padding: 10px 12px 11px !important;
  overflow-y: auto;
  color: var(--pr-sheet-ink);
  background: color-mix(in srgb, var(--iris) 8%, var(--pr-sheet)) !important;
  border: 1px solid color-mix(in srgb, var(--iris) 22%, transparent) !important;
  border-left: 3px solid color-mix(in srgb, var(--iris) 80%, var(--pr-sheet-ink)) !important;
  border-radius: 0 10px 10px 0;
  box-shadow: none !important;
  font-size: calc(12.5px * var(--pr-text-k, 1));
  line-height: 1.42;
}
body.presenting:not(.pr-guide-collapsed) #prWhyDock .pr-whyd-head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 5px;
}
body.presenting:not(.pr-guide-collapsed) #prWhyDock .pr-whyd-chip {
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  color: color-mix(in srgb, var(--iris) 80%, var(--pr-sheet-ink));
  background: color-mix(in srgb, var(--iris) 13%, var(--pr-sheet));
  border: 1px solid color-mix(in srgb, var(--iris) 25%, transparent);
  border-radius: 6px;
}
body.presenting:not(.pr-guide-collapsed) #prWhyDock .pr-why-label {
  color: color-mix(in srgb, var(--iris) 77%, var(--pr-sheet-ink));
  font: 720 9.5px/1.1 var(--sans);
  letter-spacing: .115em;
  text-transform: uppercase;
}
body.presenting:not(.pr-guide-collapsed) #prWhyDockText { color: var(--pr-sheet-ink); }

/* A bottom guide becomes a single compact card: title across the top, image
   on the left, explanation in the centre and the insight at the right.  The
   step tag and its note intentionally share one vertical column. */
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration {
  grid-template-columns: minmax(136px, .76fr) minmax(0, 1.46fr) minmax(196px, .88fr);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "title title title"
    "media step why"
    "media note why"
    "media presenter why";
  align-content: stretch;
  align-items: stretch;
  height: clamp(160px, 24vh, 220px);
  max-height: 28vh;
  border: 1px solid color-mix(in srgb, var(--pr-sheet-ink) 10%, transparent) !important;
  border-radius: 12px;
  box-shadow: 0 12px 28px -28px color-mix(in srgb, var(--pr-sheet-ink) 58%, transparent) !important;
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNoteTitle:not([hidden]) {
  padding: 9px 14px 8px;
  font-size: clamp(15.5px, 1.65vw, 20px);
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  grid-area: media;
  justify-self: stretch;
  align-self: stretch;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0 !important;
  padding: 10px 11px 11px;
  border: 0;
  border-right: 1px solid color-mix(in srgb, var(--pr-sheet-ink) 8%, transparent);
  border-radius: 0;
  box-shadow: none;
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNoteStep:not([hidden]) {
  justify-self: stretch;
  align-self: end;
  width: auto;
  margin: 0 14px !important;
  padding: 9px 0 4px;
  text-align: left;
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNarrationText {
  justify-self: stretch;
  align-self: stretch;
  width: auto;
  max-height: none !important;
  margin: 0 14px 11px !important;
  padding: 3px 0 0 !important;
  font-size: calc(14px * var(--pr-text-k, 1));
  line-height: 1.42;
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prStoryPresenterNotes:not([hidden]) {
  justify-self: stretch;
  width: auto;
  max-height: 72px;
  margin: 0 14px 10px;
  padding: 7px 9px 8px;
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  justify-self: stretch;
  align-self: stretch;
  width: auto;
  max-height: none;
  margin: 8px 12px 10px 0 !important;
  padding: 9px 10px 10px !important;
  font-size: calc(11.5px * var(--pr-text-k, 1));
  line-height: 1.36;
}
/* No empty media or insight columns: grid selection follows actual authored
   fields rather than whether a particular template happened to include art. */
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="0"][data-pr-guide-why="1"] {
  grid-template-columns: minmax(0, 1.46fr) minmax(196px, .88fr);
  grid-template-areas:
    "title title"
    "step why"
    "note why"
    "presenter why";
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="1"][data-pr-guide-why="0"] {
  grid-template-columns: minmax(136px, .76fr) minmax(0, 1.46fr);
  grid-template-areas:
    "title title"
    "media step"
    "media note"
    "media presenter";
}
body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="0"][data-pr-guide-why="0"] {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "title"
    "step"
    "note"
    "presenter";
}

/* At compact desktop/tablet widths all authored pieces remain available: the
   image/insight columns tighten before narration type shrinks. */
@media (max-width: 900px) {
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration {
    grid-template-columns: minmax(118px, .69fr) minmax(0, 1.33fr) minmax(164px, .82fr);
    height: clamp(148px, 25vh, 204px);
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="0"][data-pr-guide-why="1"] {
    grid-template-columns: minmax(0, 1.33fr) minmax(164px, .82fr);
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="1"][data-pr-guide-why="0"] {
    grid-template-columns: minmax(118px, .69fr) minmax(0, 1.33fr);
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
    display: block !important;
  }
}
/* Phones intentionally surrender the optional picture (the existing phone
   rule does that) but retain both words and Why in two clean reading cells. */
@media (max-width: 700px) {
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
    display: none !important;
  }
  body.presenting.pr-image-placement-mode.pr-notes-bottom:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
    display: block !important;
    max-height: 104px;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration,
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="0"][data-pr-guide-why="1"],
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="1"][data-pr-guide-why="0"] {
    grid-template-columns: minmax(0, 1.16fr) minmax(124px, .84fr);
    grid-template-rows: auto auto minmax(0, 1fr) auto;
    grid-template-areas:
      "title title"
      "step why"
      "note why"
      "presenter why";
    height: clamp(132px, 30vh, 190px);
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-why="0"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "title"
      "step"
      "note"
      "presenter";
  }
  /* Image placement deliberately restores the draggable guide image on a
     phone. Give that temporary authoring surface a real grid area instead of
     letting `grid-area: media` manufacture an implicit, clipped track. */
  body.presenting.pr-image-placement-mode.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration {
    grid-template-columns: minmax(104px, .62fr) minmax(0, 1.38fr);
    grid-template-rows: auto auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      "title title"
      "media step"
      "media note"
      "presenter presenter"
      "why why";
    height: min(260px, 45vh);
    max-height: 45vh;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNoteTitle:not([hidden]) {
    padding: 7px 10px;
    font-size: clamp(13.5px, 4.3vw, 16px);
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNoteStep:not([hidden]) {
    margin: 0 9px !important;
    padding: 6px 0 3px;
    font-size: 8.8px;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNarrationText {
    margin: 0 9px 7px !important;
    padding-top: 2px !important;
    font-size: calc(13px * var(--pr-text-k, 1));
    line-height: 1.35;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
    margin: 5px 7px 7px 0 !important;
    padding: 7px 8px 8px !important;
    font-size: calc(10.7px * var(--pr-text-k, 1));
    line-height: 1.28;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock .pr-whyd-head { margin-bottom: 3px; }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock .pr-whyd-chip {
    width: 16px;
    height: 16px;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prWhyDock .pr-why-label {
    font-size: 8px;
    letter-spacing: .08em;
  }
}
/* A rotated phone is wide only on paper: the browser chrome and transport
   leave very little height. Keep the guide as a compact bottom transcript,
   give artwork back to the focused diagram, and allow the copy to scroll. */
@media (max-height: 560px) and (max-width: 1024px) {
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
    display: none !important;
  }
  body.presenting.pr-image-placement-mode.pr-notes-bottom:not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
    display: block !important;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration,
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="0"][data-pr-guide-why="1"],
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-image="1"][data-pr-guide-why="0"] {
    grid-template-columns: minmax(0, 1.25fr) minmax(150px, .75fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas: "title title" "note why" "presenter why";
    height: min(124px, 35vh);
    max-height: 124px;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration[data-pr-guide-why="0"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "title" "note" "presenter";
  }
  body.presenting.pr-image-placement-mode.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration {
    grid-template-columns: minmax(96px, .55fr) minmax(0, 1.2fr) minmax(120px, .75fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas: "title title title" "media note why" "media presenter why";
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNoteStep:not([hidden]) {
    display: none !important;
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prNarration #prNarrationText {
    overflow-y: auto;
    margin: 4px 10px 7px !important;
    font-size: calc(12.5px * var(--pr-text-k, 1));
  }
  body.presenting.pr-notes-bottom:not(.pr-guide-collapsed) #prStoryPresenterNotes:not([hidden]) {
    max-height: 38px;
    margin: 1px 10px 5px;
    padding: 4px 7px 5px;
  }
}
/* Collapsed mode is deliberately a real rail, not an empty, grid-sized box.
   It remains a one-tap return to the guide without stealing stage space. */
body.presenting.pr-guide-collapsed #prNarration {
  display: flex !important;
  align-items: center;
  justify-content: center;
  padding: 0 !important;
  color: var(--pr-sheet-ink) !important;
  background: color-mix(in srgb, var(--iris) 5%, var(--pr-sheet)) !important;
  border-color: color-mix(in srgb, var(--pr-sheet-ink) 11%, transparent) !important;
  box-shadow: none !important;
}
body.presenting.pr-guide-collapsed #prNarrationHead {
  display: flex !important;
  margin: 0 !important;
  color: color-mix(in srgb, var(--iris) 72%, var(--pr-sheet-ink));
  opacity: 1;
}
/* Zen uses the exact same sheet-native surfaces — no dark panel comes back
   when a presenter chooses to keep their notes visible. */
body.pr-zen.presenting:not(.pr-guide-collapsed) #prNarration {
  background: var(--pr-sheet) !important;
  box-shadow: none !important;
}

/* Zen side guide: this is the reading view, so its authored narration owns
   the available height rather than stopping at an arbitrary short-card cap.
   The image and title establish the step; the note then grows into the calm
   sheet space that remains, with its own scroll only when the writing truly
   exceeds the audience's view. */
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration {
  grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
  align-content: stretch;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  max-height: min(29vh, 260px);
}
/* The legacy data-note-style image rule has two IDs, so repeat the aligned
   measure at this Zen-specific layer.  Zen keeps a slightly shorter media
   cap to protect the reading area below it. */
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]),
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  width: var(--pr-guide-media-w) !important;
  max-width: var(--pr-guide-media-w) !important;
  max-height: min(29vh, 260px) !important;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration #prNarrationText {
  align-self: stretch;
  max-height: none !important;
  padding: 5px 2px 2px !important;
  font-size: calc(17px * var(--pr-text-k, 1));
  line-height: 1.58;
}
/* Why is an insight marker in Zen, not another boxed panel.  Its small
   illuminated spine, haloed glyph and open-sided copy make it feel like a
   thought that has emerged from the note, while the sheet stays continuous. */
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  display: grid !important;
  grid-template-columns: 28px minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: 9px;
  row-gap: 2px;
  position: relative;
  align-self: end;
  max-height: min(22vh, 180px);
  margin: 10px 0 8px !important;
  padding: 10px 4px 10px 0 !important;
  overflow-y: auto;
  background: linear-gradient(90deg, color-mix(in srgb, var(--iris) 9%, var(--pr-sheet)), transparent 78%) !important;
  border: 0 !important;
  border-left: 0 !important;
  border-radius: 0;
  box-shadow: none !important;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock::before {
  content: '';
  position: absolute;
  top: 10px;
  bottom: 10px;
  left: 13px;
  width: 1px;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--iris-bright) 76%, var(--iris)) 18%, color-mix(in srgb, var(--iris) 43%, transparent) 78%, transparent);
  pointer-events: none;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock .pr-whyd-head {
  display: contents;
  margin: 0;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock .pr-whyd-chip {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  z-index: 1;
  width: 26px;
  height: 26px;
  color: color-mix(in srgb, var(--iris-bright) 76%, var(--pr-sheet-ink));
  background: color-mix(in srgb, var(--iris) 16%, var(--pr-sheet));
  border: 1px solid color-mix(in srgb, var(--iris) 38%, transparent);
  border-radius: 50%;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--iris) 7%, transparent),
              0 7px 16px -12px color-mix(in srgb, var(--iris) 88%, transparent);
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock .pr-whyd-chip svg {
  width: 13px;
  height: 13px;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock .pr-why-label {
  grid-column: 2;
  grid-row: 1;
  align-self: end;
  color: color-mix(in srgb, var(--iris) 82%, var(--pr-sheet-ink));
  font-size: 9px;
  letter-spacing: .14em;
}
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDockText {
  grid-column: 2;
  grid-row: 2;
  padding-bottom: 1px;
  color: var(--pr-sheet-ink);
  font-size: calc(13px * var(--pr-text-k, 1));
  line-height: 1.43;
}
/* With no step art, the auto-sized media row collapses and the note already
   owns the flexible track above Why.  Spend that genuinely free rail on a
   calmer, larger reading measure; the insight then lands flush with the rail
   rather than leaving a stranded band of blank sheet below it. */
body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed)
  #prNarration[data-pr-guide-image="0"] #prWhyDock:not([hidden]) {
  margin-bottom: 0 !important;
}
@media (min-width: 900px) and (min-height: 680px) {
  body.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed)
    #prNarration[data-pr-guide-image="0"] #prNarrationText {
    padding-top: 11px !important;
    font-size: calc(18px * var(--pr-text-k, 1));
    line-height: 1.62;
  }
}

/* Mobile runner chrome ---------------------------------------------------
   The phone is a touch player, not a squeezed desktop control console. The
   transport bar is already removed at this breakpoint; these two 44px title
   actions keep sound and the few stage choices reachable without giving the
   diagram another bottom toolbar. */
.pr-mobile-head-btn,
.pr-mobile-menu { display: none; }
@media (max-width: 760px), (max-height: 560px) and (max-width: 1024px) {
  body.pr-zen-title #prZenTitle {
    min-height: 48px;
    height: 48px;
    padding: 2px 6px;
  }
  body.pr-zen-title.presenting #canvasWrap {
    padding-top: 48px !important;
    touch-action: none;
    overscroll-behavior: contain;
    cursor: grab;
  }
  body.pr-zen-title.presenting #canvasWrap:active { cursor: grabbing; }
  body.pr-zen-notes.pr-zen-title:not(.pr-notes-bottom) #prNarration { top: 48px !important; }
  #prZenMark {
    left: max(8px, env(safe-area-inset-left));
    width: 28px;
    height: 28px;
  }
  .pr-mobile-head-btn {
    position: absolute;
    z-index: 2;
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    color: color-mix(in srgb, var(--pr-sheet-ink, #1b1b22) 82%, var(--iris));
    background: transparent;
    border: 0;
    border-radius: 12px;
    pointer-events: auto;
  }
  .pr-mobile-head-btn:active,
  .pr-mobile-head-btn[aria-expanded="true"] {
    background: color-mix(in srgb, var(--iris) 13%, transparent);
  }
  .pr-mobile-head-btn:focus-visible { outline: 2px solid var(--iris); outline-offset: -3px; }
  .pr-mobile-head-btn svg { width: 20px; height: 20px; }
  #prMobileMenuToggle { left: max(44px, calc(env(safe-area-inset-left) + 44px)); }
  #prMobileMute { right: max(6px, env(safe-area-inset-right)); }
  #prMobileMute .mu-off { display: none; }
  #prMobileMute[aria-pressed="true"] .mu-on { display: none; }
  #prMobileMute[aria-pressed="true"] .mu-off { display: inline; }
  #prZenStep {
    right: max(52px, calc(env(safe-area-inset-right) + 52px));
    min-width: 44px;
    padding: 4px 6px;
    font-size: 10px;
  }
  #prZenTitleText {
    max-width: calc(100% - 226px);
    font-size: clamp(16px, 5vw, 20px);
  }
  /* The compact camera already interpolates the SVG viewBox on every frame.
     A second half-second CSS glide made the focus lens chase that moving
     target and visibly lag beside the card on iOS. Snap geometry to the live
     DOM shape. On phones the exact renderer-attached trace is the focus cue;
     suppress the redundant broad lens so it can never chase a moving camera
     frame beside the card. */
  body.presenting #prSpotlight { display: none !important; transition: none; }
  #prMobileMenu.pr-mobile-menu:not([hidden]) {
    position: absolute;
    z-index: 10;
    top: 46px;
    left: max(8px, env(safe-area-inset-left));
    display: grid;
    width: min(330px, calc(100vw - 16px - env(safe-area-inset-left) - env(safe-area-inset-right)));
    box-sizing: border-box;
    gap: 10px;
    padding: 10px;
    color: var(--pr-stage-ink, #eef2ff);
    background: color-mix(in srgb, var(--pr-panel, #101a37) 96%, transparent);
    border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 16%, transparent);
    border-radius: 14px;
    box-shadow: 0 18px 48px rgba(3, 7, 18, .34);
    -webkit-backdrop-filter: blur(18px) saturate(1.08);
    backdrop-filter: blur(18px) saturate(1.08);
    pointer-events: auto;
  }
  .pr-mobile-menu-row {
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
    color: inherit;
    font: 650 14px/1 var(--sans);
    background: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 12%, transparent);
    border-radius: 11px;
  }
  .pr-mobile-menu-row b { color: var(--iris-bright); font-size: 12px; }
  .pr-mobile-menu-label {
    padding: 1px 2px 0;
    color: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 64%, transparent);
    font: 700 10px/1 var(--sans);
    letter-spacing: .11em;
    text-transform: uppercase;
  }
  .pr-mobile-zoom-row {
    display: grid;
    grid-template-columns: 54px minmax(0, 1fr) 54px;
    gap: 7px;
  }
  .pr-mobile-zoom-row button {
    min-height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    color: inherit;
    font: 700 23px/1 var(--sans);
    background: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 13%, transparent);
    border-radius: 11px;
  }
  .pr-mobile-zoom-row button:active { background: color-mix(in srgb, var(--iris) 20%, transparent); }
  .pr-mobile-zoom-row button:disabled { opacity: .35; }
  #prMobileZoomReset { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
  #prMobileZoomReset small {
    color: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 58%, transparent);
    font: 650 9px/1 var(--sans);
    letter-spacing: .08em;
    text-transform: uppercase;
  }
  .pr-mobile-theme-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .pr-mobile-theme-row button {
    min-height: 44px;
    padding: 7px 5px;
    color: inherit;
    font: 650 12px/1 var(--sans);
    background: color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pr-stage-ink, #eef2ff) 12%, transparent);
    border-radius: 10px;
  }
  .pr-mobile-theme-row button.on {
    color: #fff;
    background: color-mix(in srgb, var(--iris) 48%, transparent);
    border-color: color-mix(in srgb, var(--iris-bright) 70%, transparent);
  }
}

/* ============================================================
   LIQUID WORKSPACE — full-bleed canvas, floating surfaces (2026-08)
   ------------------------------------------------------------
   The editor's three fixed columns became one full-viewport canvas with
   floating islands over it: two top control islands (inside #topbar, which
   keeps its id so every presenting/watching/embed hide rule still applies),
   a floating component library (#palette), a floating inspector (#side) and
   a bottom canvas dock (#edDock). Geometry contract:

   • The CANVAS never resizes when chrome collapses — #canvasWrap always
     fills #main, so zoom, scroll and diagram coordinates are stable through
     every panel toggle. Collapsing a panel only REVEALS canvas.
   • #zoomLayer's padding places the sheet in the free region between the
     floating panels. It is CONSTANT per breakpoint (never tracks collapse
     state) for the same stability reason. app.js measures it (svgHost
     offsets) rather than assuming 34px.
   • --shell-* vars describe the chrome footprint for anything that must
     stay clear of it (canvas dock centring, rulers, canvas-kit toolbar).
     They DO track collapse state — chrome may glide, content may not.
   ============================================================ */

body {
  --shell-gap: 12px;
  --shell-top: 62px;              /* islands: 10px margin + ~44px tall + 8px  */
  --lib-w: 268px;
  --insp-w: 300px;
  /* ---- Liquid-glass surface recipe (scoped here, NOT in the TOKENS block —
     build_pages.py copies that block into generated pages). One recipe for
     every MAJOR floating container: islands, panels, dock, popovers. Inputs
     stay off the glass — they use the ordinary chrome tokens. Three-level
     hierarchy: workspace canvas (lowest) < glass chrome < opaque page. ---- */
  /* STUDIO-FLAT (Aug 2026, YouTube-Studio-inspired): opaque neutral panels,
     hairline borders, no glass blur, whisper shadows — simple, clear, crisp.
     The workspace ground goes near-black so the white sheet reads as CONTENT
     the way thumbnails read in Studio. */
  --lw-surface: #1c1c1c;
  --lw-surface-border: rgba(255, 255, 255, 0.085);
  --lw-blur: none;
  --lw-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
  --lw-canvas: #141414;
  --lw-canvas-dot: rgba(255, 255, 255, 0.055);
  --lw-page-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
                    0 12px 34px rgba(0, 0, 0, 0.5);
  /* LITERAL px on purpose: canvas-kit.js parseFloat()s these off body's
     computed style, and a custom property keeps its calc() unresolved there. */
  --shell-left: 292px;            /* library footprint: 268 + 12 * 2 */
  --shell-right: 324px;           /* inspector footprint: 300 + 12 * 2 */
  --canvas-left: 326px;           /* sheet inset: 292 + 34 — static per breakpoint */
}
[data-ui-theme="light"] body {
  --lw-surface: rgba(248, 250, 255, 0.84);
  --lw-surface-border: rgba(255, 255, 255, 0.72);
  --lw-shadow: 0 16px 45px rgba(31, 45, 78, 0.10), 0 2px 8px rgba(31, 45, 78, 0.06);
  --lw-canvas: #ccd2e6;
  --lw-canvas-dot: rgba(31, 45, 78, 0.15);
  --lw-page-shadow: 0 1px 2px rgba(31, 45, 78, 0.10),
                    0 10px 26px rgba(31, 45, 78, 0.10),
                    0 34px 70px -18px rgba(31, 45, 78, 0.22);
}
body.lib-collapsed { --shell-left: 72px; }                       /* rail: 48 + 24 */
body:has(#side.collapsed) { --shell-right: 12px; }
body:has(#side.code-mode:not(.collapsed)) { --shell-right: 454px; }

/* ---- top islands ---- */
#topbar {
  position: absolute; top: 0; left: 0; right: 0; height: auto;
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--shell-gap); padding: 10px var(--shell-gap) 0;
  background: none; border-bottom: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  pointer-events: none; z-index: 42;
}
.tb-island {
  pointer-events: auto; min-height: 44px; min-width: 0;
  display: flex; align-items: center; gap: 5px;
  padding: 4px 6px; border-radius: 16px;
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border);
  box-shadow: var(--lw-shadow);
}
#topbar .brand { padding: 2px 6px 2px 2px; }
#topbar .brand-mark, #topbar .brand-mark svg { width: 30px; height: 30px; }
#topbar .beta-badge { display: none; }        /* the island is dense; Beta still shows on home */
/* Save status is a small pill, clearly separate from the Save COMMAND.
   The state colours are re-picked for the translucent island: the old
   #d97706 / #16a34a were tuned for the opaque topbar and measured ~3:1 once
   the glass composited over the light canvas. These clear 4.5:1 there. */
#topbar .save-state { margin-right: 0; font-size: 11px; font-weight: 650; padding: 3px 8px; gap: 5px; }
#topbar .save-state .ss-dot { width: 6px; height: 6px; }
#topbar .save-state.is-dirty { color: #ffffff; border-color: rgba(255, 255, 255, 0.35); }
#topbar .save-state.is-saved { color: #aaaaaa; border-color: var(--edge); }
[data-ui-theme="light"] #topbar .save-state.is-dirty { color: #92400e; border-color: color-mix(in srgb, #92400e 40%, var(--edge)); }
[data-ui-theme="light"] #topbar .save-state.is-saved { color: #15803d; border-color: color-mix(in srgb, #15803d 40%, var(--edge)); }
/* The title is the island's one elastic block: it grows into free room up
   to a cap, truncates with an ellipsis (full text in the tooltip), and can
   never push the primary controls off screen. */
#topbar #docTitle {
  flex: 1 1 auto; width: auto; min-width: 80px; max-width: 340px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Present stays the one filled action; Export steps down to a quiet secondary. */
#topbar #btnExport {
  background: none; color: var(--text); font-weight: 600;
  border: 1px solid var(--border); box-shadow: none;
  padding: 7px 13px; border-radius: 10px;
  transition: background var(--dur-1), border-color var(--dur-1);
}
#topbar #btnExport:hover { background: var(--chrome-3); border-color: var(--accent); filter: none; transform: none; }

/* ---- full-bleed stage ---- */
#main { position: relative; }
#stage { min-width: 0; }
/* Level 1 — the workspace ground: a cool grey-blue a step deeper than the
   old near-panel pale, so the glass chrome and the opaque page both read
   against it. Presenting rules still win (they are more specific). */
body:not(.presenting) #canvasWrap {
  background: var(--lw-canvas);
  background-image: radial-gradient(var(--lw-canvas-dot) 1px, transparent 1px);
  background-size: 22px 22px;
}
/* Level 3 — the page: opaque, and the one surface with a real drop shadow. */
body:not(.presenting) #svgHost svg { box-shadow: var(--lw-page-shadow); }
/* The sheet lives CENTRED in the free region between the visible panels.
   The padding IS the usable-area definition (fitWorkspace in app.js measures
   it), and it now TRACKS panel state — collapse a panel and the region
   grows; the padding transition makes the sheet glide there rather than
   jump. Presenting/zen rules keep winning (body.presenting #zoomLayer
   { padding: 0 } is more specific).
   inline-flex, NOT flex: the layer must keep shrink-wrapping past 100% when
   the zoomed sheet overflows (a block-level flex box clamps to the scroller
   and the far-side padding falls out of the scroll range). margin:auto on
   the host centres while there is room and resolves to 0 in overflow, which
   is exactly the old anchored behaviour. */
#zoomLayer {
  padding: calc(var(--shell-top) + 26px) calc(var(--shell-right) + 22px) 112px calc(var(--shell-left) + 22px);
}
/* The padding glide is EDITOR-ONLY, and the opt-out must be explicit.
   A transition is chosen from the AFTER-change style: with the property
   declared unconditionally, adding body.presenting animated the editor
   padding down to 0 over 200ms — and enterPresent synchronously measures
   #zoomLayer's computed padding (stageBox), which at t=0 still reports the
   editor's ~660px, so the whole show fitted to a stage a third of its real
   size. Declaring it only while NOT presenting means entering the show has
   no transition to run and the padding is 0 the moment it is read. */
body:not(.presenting) #zoomLayer { transition: padding var(--dur-2) var(--ease-out); }
body.presenting #zoomLayer, body.watching #zoomLayer, body.recording #zoomLayer { transition: none !important; }
body:not(.presenting) #zoomLayer { display: inline-flex; }
body:not(.presenting) #svgHost { margin: auto; flex: none; }
#emptyState {
  padding: calc(var(--shell-top) + 26px) calc(var(--shell-right) + 22px) 112px calc(var(--shell-left) + 22px);
}
body:not(.presenting) #emptyState { transition: padding var(--dur-2) var(--ease-out); }
/* Stacked above the toast lane so a hint and a message never overlap. */
#hintBar { bottom: calc(var(--toast-lift, 40px) + 62px); }

/* ---- floating component library (left) ---- */
#palette {
  position: absolute; z-index: 40;
  top: var(--shell-top); left: var(--shell-gap);
  bottom: auto; max-height: calc(100% - var(--shell-top) - 14px);
  width: var(--lib-w);
  border-right: none; border: 1px solid var(--lw-surface-border); border-radius: 16px;
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  box-shadow: var(--lw-shadow);
  padding: 10px;
  transition: width var(--dur-2) var(--ease-out);
}
.lib-head { display: flex; align-items: center; gap: 6px; }
.lib-search {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px;
  background: var(--chrome-2); border: 1px solid var(--border);
  border-radius: 9px; padding: 0 9px; height: 32px;
}
.lib-search svg { width: 14px; height: 14px; color: var(--muted); flex: none; }
.lib-search input {
  flex: 1; min-width: 0; background: none; border: none; outline: none;
  color: var(--text); font-size: 12.5px; height: 100%;
}
.lib-search input::placeholder { color: var(--muted); }
.lib-search:focus-within { border-color: var(--accent); }
#libCollapse {
  flex: none; width: 30px; height: 30px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--muted);
}
#libCollapse svg { width: 15px; height: 15px; }
#libCollapse:hover { background: var(--chrome-3); color: var(--text); }
.lib-tabs {
  display: flex; gap: 2px; padding: 2px;
  background: var(--chrome-2); border: 1px solid var(--border-soft); border-radius: 9px;
}
.lib-tab {
  flex: 1; padding: 6px 4px; border-radius: 7px; font-size: 12px; font-weight: 600;
  color: var(--muted); text-align: center;
  transition: background var(--dur-1), color var(--dur-1);
}
.lib-tab:hover { color: var(--text); }
.lib-tab.active { background: var(--chrome-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }
.lib-empty { font-size: 12px; color: var(--muted); padding: 10px 2px; }
/* Dense list presentation: the two-column cards became one-column rows —
   icon, name, and a grip that appears on hover as the drag affordance.
   Scoped to the palette so kanban/swimlane reuse of .pal-grid elsewhere is
   untouched. */
#palGroups .pal-grid { grid-template-columns: 1fr; gap: 1px; }
#palGroups .pal-item {
  flex-direction: row; align-items: center; justify-content: flex-start;
  text-align: left; gap: 10px; min-height: 40px; padding: 6px 8px;
  background: none; border: none; border-radius: 9px; position: relative;
  transition: background var(--dur-1), color var(--dur-1);
}
#palGroups .pal-item:hover { background: var(--accent-soft); transform: none; }
#palGroups .pal-item:active { background: var(--accent-soft); }
#palGroups .pal-glyph {
  flex: none; width: 24px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; color: var(--muted);
}
#palGroups .pal-glyph svg { width: 20px; height: 20px; }
#palGroups .pal-item:hover .pal-glyph { color: var(--accent-ink); }
#palGroups .pal-name { font-size: 12.5px; color: var(--text); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* drag grip — visible on hover/focus only */
#palGroups .pal-item::after {
  content: ""; flex: none; width: 7px; height: 14px; opacity: 0; margin-left: 4px;
  background-image: radial-gradient(currentColor 1px, transparent 1.2px);
  background-size: 4px 5px; color: var(--muted);
  transition: opacity var(--dur-1);
}
#palGroups .pal-item:hover::after, #palGroups .pal-item:focus-visible::after { opacity: .8; }
/* Any remaining emoji glyphs read as one quiet family; hover previews color. */
.pal-glyph { filter: grayscale(1) opacity(.85); transition: filter var(--dur-1), color var(--dur-1); }
.pal-item:hover .pal-glyph { filter: none; }
/* While a search is live every matching group shows its items, without
   writing details.open (which would fire toggle events app.js persists).
   The UA rule this overrides is `details:not([open]) > *:not(summary)`. */
body.lib-filtering #palGroups .pal-group:not([open]) > .pal-group-body { display: flex; }
body.lib-filtering #palGroups .pal-group > summary .pal-chevron { transform: rotate(90deg); }
/* group summaries: quieter headings, roomier list */
.pal-group > summary { padding: 9px 4px; }
.pal-group { border-bottom: none; padding-bottom: 2px; }

/* collapsed rail */
body.lib-collapsed #palette { width: 48px; padding: 6px; overflow: hidden; }
body.lib-collapsed #palette :is(.lib-head, .lib-tabs, #palGroups, .pal-footer) { display: none; }
body.lib-collapsed #libRailBtn { display: flex; }
#libRailBtn {
  flex: 1; width: 100%; border-radius: 10px;
  display: none; flex-direction: column; align-items: center; gap: 10px;
  padding-top: 12px; color: var(--muted);
}
#libRailBtn svg { width: 18px; height: 18px; flex: none; }
#libRailBtn span { writing-mode: vertical-rl; font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
#libRailBtn:hover { background: var(--chrome-2); color: var(--text); }

/* ---- floating inspector (right) ---- */
#side {
  position: absolute; z-index: 40;
  top: var(--shell-top); right: var(--shell-gap);
  bottom: auto; max-height: calc(100% - var(--shell-top) - 14px);
  border-left: none; border: 1px solid var(--lw-surface-border); border-radius: 16px;
  width: var(--insp-w);
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  box-shadow: var(--lw-shadow);
  overflow: hidden;             /* the radius must clip the scrolling pane */
  transition: width var(--dur-2) var(--ease-out);
}
#side.collapsed { border: none; box-shadow: none; }
/* The text editor wants a tall column — content-height would collapse it to
   #codeWrap's 220px floor. Code mode pins the full working height. */
#side.code-mode:not(.collapsed) { height: calc(100% - var(--shell-top) - 14px); }
#tabs { padding: 8px 10px 0; }
.tab-note {
  padding: 7px 12px 9px; color: var(--muted); font-weight: 600; font-size: 12.5px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--dur-1);
}
.tab-note:hover { color: var(--text); }
.tab-note.on { color: var(--text); border-bottom-color: var(--accent); }
#sideExpand {
  top: auto; bottom: 76px; transform: none;
  right: var(--shell-gap); width: 34px; height: 40px;
  border-radius: 10px; border-right: 1px solid var(--lw-surface-border);
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  box-shadow: var(--lw-shadow);
}
/* The floating notes editor keeps clear of the floating inspector. */
body:not(.presenting):has(#side:not(.collapsed)) #prNarration.show.pos-right {
  right: var(--shell-right) !important;
}

/* ---- bottom canvas dock ---- */
#edDock {
  position: absolute; z-index: 41; bottom: 14px;
  left: calc(var(--shell-left) + (100% - var(--shell-left) - var(--shell-right)) / 2);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 3px;
  padding: 5px; border-radius: 16px;
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border);
  box-shadow: var(--lw-shadow);
  transition: left var(--dur-2) var(--ease-out);
}
.dock-btn {
  min-width: 36px; height: 36px; padding: 0 8px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  color: var(--muted); font-size: 14px; line-height: 1;
  transition: background var(--dur-1), color var(--dur-1);
}
.dock-btn svg { width: 17px; height: 17px; }
.dock-btn:hover { background: var(--chrome-3); color: var(--text); }
.dock-btn.active, .dock-btn[aria-pressed="true"]:not(#dockGrid) { background: var(--accent-soft); color: var(--accent-ink); }
#dockGrid[aria-pressed="true"] { color: var(--text); }
#edDock .zoom-label { font-size: 12px; }
#btnHand.active { background: var(--accent); color: var(--on-accent); }
.dock-sep { width: 1px; height: 20px; background: var(--border); margin: 0 3px; flex: none; }
.dock-lbl { font-size: 12.5px; font-weight: 650; }
/* #miLauncher keeps its id (app.js binds it) but sheds the old round-FAB
   costume — inside the dock it is a labeled pill like its neighbours. */
#edDock #miLauncher {
  position: static; width: auto; height: 36px; border-radius: 10px;
  background: var(--accent-soft); color: var(--accent-ink);
  box-shadow: none;
}
#edDock #miLauncher:hover { transform: none; box-shadow: none; filter: brightness(1.12); }
#edDock #miLauncher svg { width: 16px; height: 16px; }
.dock-sheet-btn { display: none; }
body.no-canvas-grid #canvasWrap { background-image: none; }
/* PLAIN MEANS PLAIN: a document whose Canvas is Plain shows a clean world —
   no editing dots — unless the dock's grid button asked for them this
   session (grid-forced). A theme's own paper (world-patterned: Blueprint's
   grid, Mission Control's stars) is the document's texture and still shows.
   (1,4,1) ties the coarse-grid rule above and comes later, so it wins. */
body.world-plain:not(.grid-forced):not(.world-patterned):not(.presenting) #zoomLayer { background-image: none; }

/* The canvas-kit rulers adapt to the floating chrome. The horizontal ruler
   slides below the top islands (moving its TOP changes no x tick); the
   vertical ruler must NOT move (moving its top would shift every y tick), so
   the stretch that runs behind the islands is clipped away instead. Both are
   clipped out of the panel zones so they stop ghosting through the glass,
   and both lose the heavy fill — the workspace has no fixed dividers now. */
body:not(.embed-mode) #ckRulerH {
  top: var(--shell-top) !important;
  transition: top var(--dur-2) var(--ease-out), clip-path var(--dur-2) var(--ease-out);
  clip-path: inset(0 calc(var(--shell-right) - 6px) 0 calc(var(--shell-left) - 6px));
  background: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border-bottom: none;
}
body:not(.embed-mode) #ckRulerV {
  left: calc(var(--shell-left) - 10px) !important;
  transition: left var(--dur-2) var(--ease-out), clip-path var(--dur-2) var(--ease-out);
  clip-path: inset(calc(var(--shell-top) + 22px) 0 66px 0);
  background: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border-right: none;
}

/* Every mode that hides the old chrome hides the dock too. */
body.presenting #edDock, body.watching #edDock, body.recording #edDock,
body.embed-mode #edDock, body.sample-locked #edDock, body.present-link #edDock { display: none !important; }

/* A left-docked comment pane owns the left edge: the library glides away
   while the pane is open (same idea as watch mode, scoped by :has). */
body:has(#stage.cp-left #commentPane:not([hidden])) #palette { transform: translateX(calc(-100% - 20px)); opacity: 0; pointer-events: none; }
#palette { transition: width var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out); }

/* ---- medium widths: one expanded panel at a time (js/editor-shell.js
   enforces the exchange; these are the sizes) ---- */
@media (max-width: 1150px) {
  body { --canvas-left: 98px; }   /* legacy var, still read by nothing critical */
}

/* ---- small screens: canvas stays full-bleed, panels become bottom sheets ---- */
@media (max-width: 760px) {
  body, body:has(#side.code-mode:not(.collapsed)), body:has(#side.collapsed), body.lib-collapsed {
    --shell-top: 58px; --canvas-left: 16px; --shell-left: 8px; --shell-right: 8px;
  }
  #zoomLayer { padding: calc(var(--shell-top) + 10px) 16px 96px 16px; }
  #emptyState { padding: calc(var(--shell-top) + 10px) 16px 96px 16px; }
  #topbar { padding: 8px 8px 0; }
  .tb-island { min-height: 42px; border-radius: 13px; }
  #topbar .save-state, #topbar #autoSaveWrap, #topbar #btnCommentPane { display: none; }
  #topbar #btnExport { padding: 7px 10px; }
  #topbar #docTitle { min-width: 56px; max-width: 120px; }

  /* sheets */
  #palette, #side {
    position: fixed; z-index: 60; left: 0; right: 0; bottom: 0; top: auto;
    width: auto !important; max-height: 68dvh;
    border-radius: 18px 18px 0 0; border-bottom: none;
    transform: translateY(105%);
    transition: transform var(--dur-2) var(--ease-out);
    box-shadow: var(--shadow-lg);
  }
  body.sheet-lib-open #palette { transform: none; }
  body.sheet-insp-open #side { transform: none; }
  /* Desktop collapse state has no meaning for a bottom sheet — reset every
     part of it, including the overflow that made the sheet unscrollable and
     the comment-pane glide that parked it off-screen. */
  body.lib-collapsed #palette { width: auto !important; padding: 10px; overflow-y: auto; }
  body:has(#stage.cp-left #commentPane:not([hidden])) #palette { transform: none; opacity: 1; pointer-events: auto; }
  body.lib-collapsed #palette :is(.lib-head, .lib-tabs, #palGroups, .pal-footer) { display: revert; }
  body.lib-collapsed #palette #palGroups { display: flex; }
  body.lib-collapsed #libRailBtn { display: none; }
  #side.collapsed { width: auto !important; border: 1px solid var(--border); overflow: hidden; }
  #libCollapse, #sideCollapse, #sideExpand { display: none !important; }
  .dock-sheet-btn { display: inline-flex; }
  .dock-sheet-btn[aria-expanded="true"] { background: var(--accent-soft); color: var(--accent-ink); }
  #dockMinimap, #dockSelect { display: none; }   /* touch: no minimap, selection is implicit */
  #edDock { left: 50%; bottom: max(10px, env(safe-area-inset-bottom)); max-width: calc(100vw - 16px); overflow-x: auto; }
  .dock-btn { min-width: 44px; height: 44px; }
  .tab, .tab-note { min-height: 44px; }
  .pal-item { min-height: 44px; }
  /* Touch floors for everything inside the bottom sheets and popovers. */
  .lib-tab { min-height: 44px; }
  .sw-trigger, .style-trigger { min-height: 44px; }
  .sw-pop .swatch, .sw-pop .swatch-custom, .sw-recent-chip { width: 30px; height: 30px; }
  #topbar .tb-btn, #topbar .btn-primary, #topbar .btn-present { min-height: 40px; }
}

/* ---- motion discipline ---- */
@media (prefers-reduced-motion: reduce) {
  #palette, #side, #edDock, .tb-island, #zoomLayer, #emptyState,
  body:not(.embed-mode) #ckRulerH, body:not(.embed-mode) #ckRulerV { transition: none; }
}

/* ---- compact Style controls + popovers (theme picker, quick decoration) ---- */
.style-trigger {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; border-radius: 9px;
  background: var(--chrome-2); border: 1px solid var(--border);
  color: var(--text); font-size: 12.5px; text-align: left;
  transition: border-color var(--dur-1), background var(--dur-1);
}
.style-trigger:hover { border-color: var(--accent); background: var(--chrome-3); }
.style-trigger[aria-expanded="true"] { border-color: var(--accent); }
.style-trigger-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.style-caret { font-size: 10px; color: var(--muted); flex: none; }
.dp-cur-swatch {
  width: 14px; height: 14px; flex: none; border-radius: 4px;
  border: 1px solid var(--accent); background: var(--accent-soft);
}
.style-pop {
  position: fixed; z-index: 210;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 10px; border-radius: 14px;
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border);
  box-shadow: var(--lw-shadow);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
/* Topbar dropdown panels share the recipe (major popovers only). */
#topbar .tb-menu-panel {
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border-color: var(--lw-surface-border);
  box-shadow: var(--lw-shadow);
  border-radius: 12px;
}
.style-pop[hidden] { display: none; }
.style-pop-h {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); padding: 0 2px 8px;
}
/* Bigger theme previews inside the popover: the theme's own sheet with two
   node chips and its arrow ink — a miniature of the look, not a color dot. */
.style-pop-themes .theme-grid { grid-template-columns: 1fr 1fr 1fr; }
.style-pop-themes .theme-card { flex-direction: column; align-items: stretch; gap: 6px; padding: 6px; }
.theme-prev {
  display: flex; align-items: center; justify-content: center; gap: 3px;
  height: 40px; border-radius: 6px; border: 1px solid rgba(0, 0, 0, .12);
}
.theme-prev i { width: 13px; height: 10px; border-radius: 2.5px; border: 1px solid transparent; }
.theme-prev u { width: 9px; height: 1.5px; border-radius: 1px; }
.theme-card-name { font-size: 11px; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.theme-card.active .theme-card-name { font-weight: 700; }
#dpPop .dp-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
@media (prefers-reduced-motion: reduce) { .style-pop { animation: none; } }

/* The editor-mode notes column starts below the floating top islands and
   picks up the floating-surface look (present mode is untouched — these are
   body:not(.presenting) scoped). */
body:not(.presenting):not(.watching) #prNarration.show {
  top: var(--shell-top);
  border-radius: 14px 14px 0 0;
  box-shadow: var(--shadow-sm);
}

/* Touch widths: the authoring rulers (and their stage bands) are a desktop
   aid — on a phone they cut a tick strip through the middle of the canvas. */
@media (max-width: 760px) {
  #ckRulerH, #ckRulerV, #ckGuides { display: none !important; }
}

/* Phone squeeze: one row of islands, no horizontal overflow. Every hidden
   control keeps a living twin — Save lives in Menu → File, sign-in on the
   home header, Present keeps its icon, zoom keeps pinch + Fit. */
@media (max-width: 560px) {
  #topbar #btnSaveDoc { display: none; }
  #topbar #btnPresent .bp-label { display: none; }
  #topbar #btnPresent { padding: 6px 9px; }
  #topbar .tb-island { gap: 3px; }
}
@media (max-width: 430px) {
  /* The title stays EDITABLE — a document must be nameable on a phone; it
     just gives up its spare width. */
  #topbar #docTitle { min-width: 44px; max-width: 90px; }
  #edDock { gap: 1px; padding: 4px; }
  #edDock #btnZoomOut, #edDock #btnZoomIn, #edDock .dock-lbl { display: none; }
  .dock-sep { margin: 0 1px; }
}

/* present-guide.js mounts its frame toggle beside #btnZoomFit, which now
   lives in the dock — dress the mounted .tb-btn as a dock button. */
#edDock #btnPresentGuide {
  min-width: 36px; height: 36px; padding: 0 8px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 15px;
}
#edDock #btnPresentGuide:hover { background: var(--chrome-3); color: var(--text); }
#edDock #btnPresentGuide[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-ink); }
@media (max-width: 760px) {
  #edDock #btnPresentGuide { min-width: 44px; height: 44px; }
}

/* ---- inspector typography & rhythm (8px system) ----
   Field labels drop the all-caps treatment — section headers keep a QUIET
   small-caps voice, so the two levels finally read as two levels. Scoped to
   the side panel so modal forms elsewhere keep their look. */
#side .field > label {
  text-transform: none; letter-spacing: 0;
  font-size: 12px; font-weight: 600; color: var(--muted);
}
#side .tabpane { padding: 12px 14px 16px; gap: 12px; }
#side .cs-grp { margin: 20px 0 2px; }
#side .cs-grp:first-child { margin-top: 2px; }
#side .cs-grp span { font-size: 11px; }
#side .field input[type="text"], #side .field input[type="number"], #side .field input[type="date"],
#side .field input:not([type]), #side .field select, #side .field textarea { padding: 6px 9px; }
#side .seg-btn { padding: 5px 4px; }
/* Advanced groups: whole sections fold behind a quiet disclosure. */
.cs-adv { border: 1px solid var(--border-soft); border-radius: 10px; }
.cs-adv > summary {
  list-style: none; cursor: pointer; user-select: none; -webkit-user-select: none;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; font-size: 12.5px; font-weight: 600; color: var(--muted);
  border-radius: 10px;
  transition: color var(--dur-1), background var(--dur-1);
}
.cs-adv > summary::-webkit-details-marker { display: none; }
.cs-adv > summary:hover { color: var(--text); background: var(--chrome-2); }
.cs-adv > summary .cs-adv-chev { margin-left: auto; transition: transform var(--dur-1); font-size: 10px; }
.cs-adv[open] > summary .cs-adv-chev { transform: rotate(90deg); }
.cs-adv-body { display: flex; flex-direction: column; gap: 12px; padding: 4px 11px 12px; }
@media (prefers-reduced-motion: reduce) { .cs-adv > summary .cs-adv-chev { transition: none; } }

/* Side-docked comment pane: clear the floating top islands so its own header
   row stays reachable (bottom dock keeps its own clearance). */
body:not(.presenting):not(.watching) #stage.cp-right #commentPane,
body:not(.presenting):not(.watching) #stage.cp-left  #commentPane {
  margin-top: var(--shell-top);
  border-radius: 14px 14px 0 0;
  border-top: 1px solid var(--border);
}

/* ---- compact colour control (swatchesHTML rows) ----
   The row shows a small trigger with the ACTIVE colour; the full swatch set
   lives in a floating popover reparented to <body> while open
   (js/editor-shell.js). The .swatch buttons inside keep their classes and
   bound listeners — this is presentation only. */
.sw-compact { position: relative; }
.sw-trigger {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 6px 10px; border-radius: 9px;
  background: var(--chrome-2); border: 1px solid var(--border);
  color: var(--text); font-size: 12px; text-align: left;
  transition: border-color var(--dur-1), background var(--dur-1);
}
.sw-trigger:hover { border-color: var(--accent); background: var(--chrome-3); }
.sw-trigger[aria-expanded="true"] { border-color: var(--accent); }
.sw-cur {
  flex: none; width: 16px; height: 16px; border-radius: 5px;
  border: 1px solid rgba(128, 128, 160, .35);
}
.sw-cur-none {
  background:
    linear-gradient(to top left, transparent 44%, var(--danger) 46%, var(--danger) 54%, transparent 56%),
    var(--chrome-3);
}
.sw-cur-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--mono); font-size: 11px; color: var(--muted); }
.sw-pop {
  position: fixed; z-index: 214;
  padding: 10px; border-radius: 12px;
  background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border);
  box-shadow: var(--lw-shadow);
  animation: ck-pop var(--dur-1) var(--ease-out);
}
.sw-pop[hidden] { display: none; }
.sw-pop-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.sw-recent { margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--border-soft);
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.sw-recent[hidden] { display: none; }
.sw-recent-h { flex-basis: 100%; font-size: 10.5px; font-weight: 600; color: var(--muted); }
.sw-recent-chip {
  width: 22px; height: 22px; border-radius: 6px; border: 2px solid transparent; padding: 0;
  cursor: pointer; transition: transform var(--dur-1);
}
.sw-recent-chip:hover { transform: scale(1.12); }
/* Per-step narration popup, opened from a selected shape's quick bar. Small,
   dismissible, and deliberately NOT a modal — you keep looking at the diagram
   while writing what it should say. */
.step-notes-pop {
  position: fixed; z-index: 216; width: 300px; max-width: calc(100vw - 16px);
  padding: 11px; border-radius: 12px;
  background: var(--lw-surface, var(--panel));
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border, var(--border));
  box-shadow: var(--lw-shadow, 0 10px 30px rgba(0,0,0,.35));
}
.step-notes-pop .snp-h { font-size: 11px; font-weight: 650; color: var(--text);
  margin-bottom: 7px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.step-notes-pop .snp-text {
  width: 100%; box-sizing: border-box; min-height: 84px; resize: vertical;
  font: inherit; font-size: 12.5px; line-height: 1.4; padding: 7px 8px;
  border-radius: 8px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--text);
}
.step-notes-pop .snp-hint { font-size: 11.5px; color: var(--muted); line-height: 1.4; }
.step-notes-pop .snp-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.step-notes-pop .snp-link { background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 11.5px; color: var(--iris, #6a5cff); }
.step-notes-pop .snp-done { font-size: 11.5px; padding: 4px 12px; border-radius: 7px; cursor: pointer;
  border: 0; background: var(--iris, #6a5cff); color: #fff; }

/* Studio narration picker — attaches locally baked audio to the open
   document. Sits at the top of the Notes tab because it decides HOW every
   note below it is spoken. */

/* Notes pane — a tab beside Design, not a window over the canvas. Scrolls
   with the panel like every other pane. */
#notesPane { overflow-y: auto; }
.notes-pane-h { font-size: 11px; color: var(--muted); line-height: 1.4;
  padding: 2px 2px 10px; border-bottom: 1px solid var(--border-soft); margin-bottom: 10px; }

/* ---- target size guide (canvas-kit) ----
   A LIGHT DOTTED OUTLINE, nothing more. The previous on-canvas guide was
   removed for drawing a heavy cross through people's diagrams; this one has no
   fill and no centre lines, sits under every floating panel, and never takes a
   pointer event. It is chrome — a DOM element, never part of the diagram SVG,
   so it cannot reach an export. */
#ckFrame {
  position: fixed; z-index: 2; pointer-events: none;
  border: 1px dotted color-mix(in srgb, var(--iris, #6a5cff) 55%, transparent);
  border-radius: 3px;
}
/* INSIDE the frame: the clip-path that keeps the guide off the panels also
   removes anything drawn outside its own box, so a label hung above the top
   edge vanishes exactly when the frame meets the top of the canvas. */
/* Authoring chrome, never part of a show. The JS guard clears these on the
   next re-render, but entering Explain does not itself trigger one — so the
   rule that actually holds during a presentation is this one. */
body.presenting #ckFrame,
body.presenting #ckAdvice,
body.embed-mode #ckAdvice,
body.presenting #ckTargetMask { display: none !important; }

/* The focus mask: the device area reads as the working surface. Very faint —
   the earlier on-canvas guide was deleted for competing with the drawing. */
#ckTargetMask { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
#ckTargetMask i { position: fixed; display: block; background: var(--canvas-bg, #0b0d14); opacity: .16; }
@media (prefers-color-scheme: light) { #ckTargetMask i { opacity: .10; } }

/* The live verdict — whether the diagram fits the device and whether its
   smallest label survives being looked at there. Its OWN fixed pill now:
   the old in-frame placement was clipped by the frame's viewport clip-path
   and sat wherever the frame's corner happened to land — over the drawing,
   as often as not. Default seat: bottom-centre, above the dock; draggable
   anywhere (canvas-kit remembers the spot as window fractions), and the ×
   hides it until the target guide is cycled again. */
/* Positioned in PIXELS by canvas-kit's seatAdvice — no viewport-relative
   left/bottom here, because vw/percentage resolution against the initial
   containing block is exactly what headless panes report degenerately. */
#ckAdvice {
  position: fixed; z-index: 41; max-width: 560px;
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px 4px 10px; border-radius: 9px;
  background: var(--lw-surface, var(--panel)); border: 1px solid var(--border-soft);
  box-shadow: var(--shadow-sm, 0 2px 10px rgba(0,0,0,.18));
  font-size: 10.5px; line-height: 1.3; color: var(--muted);
  cursor: grab; touch-action: none; user-select: none;
}
#ckAdvice:active { cursor: grabbing; }
#ckAdvice[data-tone="warn"] { color: var(--text); border-color: #b4232a; }
#ckAdvice[data-tone="warn"] .ck-adv-msg::before { content: '⚠ '; color: #b4232a; }
#ckAdvice[data-tone="ok"] .ck-adv-msg::before { content: '✓ '; }
#ckAdvice .ck-adv-msg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#ckAdvice .ck-adv-fit {
  flex: 0 0 auto; cursor: pointer; font-size: 10.5px; padding: 2px 8px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
}
#ckAdvice .ck-adv-fit:hover { background: var(--panel); }
#ckAdvice .ck-adv-x {
  flex: 0 0 auto; cursor: pointer; width: 20px; height: 20px; padding: 0;
  border: 0; border-radius: 6px; background: transparent; color: var(--faint);
  font-size: 14px; line-height: 1;
}
#ckAdvice .ck-adv-x:hover { background: var(--panel-2); color: var(--text); }

#ckFrame .ck-frame-tag {
  position: absolute; top: 4px; left: 6px;
  font-size: 9.5px; letter-spacing: .04em; white-space: nowrap;
  color: var(--muted); opacity: .85;
}
@supports not (color: color-mix(in srgb, red 50%, transparent)) {
  #ckFrame { border-color: rgba(106, 92, 255, .55); }
}

/* The palette-swap opt-out. Sits under the palette grid, unchecked, with the
   consequence spelled out — a control that discards work must say so. */
.theme-wipe { display: flex; gap: 8px; align-items: flex-start; margin: 10px 2px 2px;
  padding: 8px 9px; border-radius: 9px; background: var(--panel-2);
  border: 1px solid var(--border-soft); cursor: pointer; }
.theme-wipe input { margin-top: 2px; flex: 0 0 auto; }
.theme-wipe span { font-size: 11.5px; color: var(--text); line-height: 1.35; }
.theme-wipe small { display: block; margin-top: 2px; font-size: 10.5px; color: var(--muted); }

/* ---- the universal colour picker (js/color-picker.js) ----
   Injected into the same .sw-pop the compact control already owns, so the
   trigger, the reparenting and the outside/Escape close are unchanged. The pop
   grows a lot taller, hence the cap + scroll: a colour control must never run
   off the bottom of a short window. Tokens are the real ones from the design
   system — --chrome/--panel/--text/--muted/--border-soft — never invented
   names, which fail silently to their fallback. */
.sw-pop { max-height: min(70vh, 560px); overflow-y: auto; overscroll-behavior: contain; }
.sw-more { margin-top: 2px; }
.sw-sec { margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--border-soft);
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.sw-sec[hidden] { display: none; }
.sw-sec-h { flex: 0 0 100%; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 3px; }
.sw-chip { width: 20px; height: 20px; border-radius: 6px; border: 1px solid var(--border);
  cursor: pointer; padding: 0; }
.sw-chip:hover, .sw-chip:focus-visible { outline: 2px solid var(--accent, #6d7cff); outline-offset: 1px; }
/* A derived colour is marked, not just coloured — the corner notch says the
   palette computed this one rather than an author choosing it. */
.sw-chip-derived { position: relative; }
.sw-chip-derived::after { content: ''; position: absolute; right: -1px; bottom: -1px;
  width: 7px; height: 7px; border-radius: 0 0 5px 0;
  background: linear-gradient(135deg, transparent 50%, var(--panel) 50%); }
.sw-custom { flex-direction: column; align-items: stretch; }
.sw-hex { width: 100%; box-sizing: border-box; font-family: var(--mono, ui-monospace, monospace);
  font-size: 12px; padding: 5px 7px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text); }
.sw-num-row { display: flex; gap: 5px; margin-top: 5px; }
.sw-num { flex: 1 1 0; display: flex; align-items: center; gap: 3px; font-size: 10.5px; color: var(--muted); }
.sw-num input { width: 100%; min-width: 0; box-sizing: border-box; font-size: 11.5px; padding: 3px 4px;
  border-radius: 6px; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); }
.sw-actions { display: flex; gap: 5px; margin-top: 7px; }
.sw-act { flex: 1 1 auto; font-size: 11.5px; padding: 5px 8px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text); }
.sw-act:hover { background: var(--panel); }
.sw-act-primary { background: var(--accent, #6d7cff); border-color: transparent; color: #fff; }
.sw-preview { display: flex; align-items: center; gap: 6px; margin-top: 9px; }
.sw-prev-chip { width: 34px; height: 24px; border-radius: 6px; border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; }
.sw-prev-ink { padding: 0 3px; border-radius: 3px; }
.sw-prev-note { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-contrast { margin-top: 6px; font-size: 11px; line-height: 1.35; }
.sw-contrast-ok { color: var(--muted); }
/* A warning, never a block — the spec is explicit that an intentional choice
   still applies. Carries a ⚠ glyph so the state is not colour alone. */
.sw-contrast-warn { color: #b4232a; }
.sw-state { margin-top: 6px; font-size: 10.5px; color: var(--muted); line-height: 1.35; }
.sw-state-custom { color: var(--text); }
@media (prefers-reduced-motion: reduce) { .sw-pop { animation: none; } .sw-recent-chip:hover { transform: none; } }

/* ============================================================
   INFINITE WORKSPACE (2026-08, pass 3)
   ------------------------------------------------------------
   The editor is a spatial world, not a document with a page in it.

   • The ARTBOARD is gone from the editor. Every renderer paints its page as
     one rect tagged [data-kind="bg"] (13 renderers, exactly one each), plus
     the page's tile ("bg-pattern") and washes ("bg-wash") — we hide all of
     them on screen, and the world takes the page's own colour and tile
     (app.js syncCanvasTheme), so the drawing sits on one seamless surface.
     Document CSS neither serializes into exported SVG nor applies to a
     rasterized copy, so SVG / PNG / GIF / video and Present keep painting
     the page exactly as before. Nothing about export geometry changes.
   • The GRID lives on #zoomLayer (the scrolling content box), so it travels
     with the world instead of sitting still behind it, and it tiles across
     the whole pan space with no seam or restart.
   • PAN SPACE is --pan on every side, so the world continues far past the
     drawing in all four directions. fitWorkspace subtracts it, so the
     usable-area maths from pass 2 is untouched.
   ============================================================ */

body {
  --pan: 1400px;                     /* world margin around the drawing */
  --grid-minor: 22px;                /* set from JS per zoom (setZoom) */
  --grid-dot: rgba(41, 48, 82, 0.30);
  --grid-major: rgba(41, 48, 82, 0.46);
  --canvas-world: #ffffff;           /* the page: white until a theme or a Paper colour says otherwise */
}
[data-ui-theme="light"] body {
  --grid-dot: rgba(44, 51, 88, 0.26);
  --grid-major: rgba(44, 51, 88, 0.40);
  --canvas-world: #ffffff;
}

/* ---- the world ---- */
body:not(.presenting) #canvasWrap {
  /* Flat, and exactly the page's colour. The soft radial lift that used to
     sit here made the world a different colour from the page it stands in
     for, which is the seam this surface exists to remove (Sep 14 2026). */
  background-color: var(--canvas-world);
  background-image: none;
}
/* The grid travels with the world. Two layers: minor dots and a major marker
   every 8 minor intervals, both one device pixel at any zoom. */
body:not(.presenting):not(.no-canvas-grid) #zoomLayer {
  background-image:
    radial-gradient(circle at center, var(--grid-major) var(--grid-major-r, 1.15px), transparent var(--grid-major-r, 1.15px)),
    radial-gradient(circle at center, var(--grid-dot) var(--grid-dot-r, 0.9px), transparent var(--grid-dot-r, 0.9px));
  background-size:
    calc(var(--grid-minor) * 8) calc(var(--grid-minor) * 8),
    var(--grid-minor) var(--grid-minor);
  background-position: var(--grid-origin-x, 0px) var(--grid-origin-y, 0px);
  background-attachment: local, local;
}
/* Zoomed far out the minor dots turn to mud — drop them and keep the majors. */
body.grid-coarse:not(.presenting):not(.no-canvas-grid) #zoomLayer {
  background-image: radial-gradient(circle at center, var(--grid-major) var(--grid-major-r, 1.15px), transparent var(--grid-major-r, 1.15px));
  background-size: calc(var(--grid-minor) * 8) calc(var(--grid-minor) * 8);
}
/* The two painting rules above now exclude .no-canvas-grid themselves — the
   old `body.no-canvas-grid #zoomLayer` override was (0,2,1) and lost to the
   coarse rule's (0,3,1), so the dock's grid toggle silently did nothing
   whenever the view was zoomed out far enough to be in coarse mode. */
body.no-canvas-grid #canvasWrap { background-image: none; }

/* A page with its own TILE — a Canvas background or a theme texture — carries
   that tile across the world instead of the dot grid, aligned to the
   drawing's origin (app.js syncWorldPattern). Specificity (1,3,1) ties the
   coarse grid rule above, and this one comes later. The grid toggle stays
   about the editing grid: it does not hide the document's own paper. */
body.world-patterned:not(.presenting):not(.watching) #zoomLayer {
  background-image: var(--world-pattern);
  background-size: var(--world-pattern-size, auto);
  background-position: var(--world-pattern-pos, 0 0);
  background-repeat: repeat;
  background-attachment: local;
}

/* Glassmorphism in the editor: the page's aurora glows (hidden with the rest
   of the page on screen) become the WORLD's light, fixed to the view like
   ambient light — same colours and placement as drawThemeTexture's
   'glassaurora' (common-settings.js). The grid toggle does not remove it:
   it is the document's backdrop, not the editing grid. */
body.world-aurora:not(.presenting) #canvasWrap,
body.world-aurora.no-canvas-grid:not(.presenting) #canvasWrap {
  background-color: var(--canvas-world);
  background-image:
    radial-gradient(circle at 16% 30%, rgba(124, 58, 237, .78) 0, rgba(124, 58, 237, .5) 16%, rgba(124, 58, 237, .16) 32%, transparent 48%),
    radial-gradient(circle at 82% 22%, rgba(37, 99, 235, .72) 0, rgba(37, 99, 235, .46) 15%, rgba(37, 99, 235, .14) 30%, transparent 44%),
    radial-gradient(circle at 52% 84%, rgba(219, 39, 119, .68) 0, rgba(219, 39, 119, .42) 15%, rgba(219, 39, 119, .13) 30%, transparent 46%);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* ---- the drawing sits directly on the world ---- */
/* The page — sheet, tile and washes — hidden on screen only. Exports and
   Present still paint it. */
body:not(.presenting):not(.watching):not(.recording) #svgHost svg :is([data-kind="bg"], [data-kind="bg-pattern"], [data-kind="bg-wash"]) { display: none; }
/* …and with no page there is no page furniture: no card shadow, no radius. */
body:not(.presenting) #svgHost svg {
  box-shadow: none;
  border-radius: 0;
  overflow: visible;
}

/* ---- pan space in every direction ---- */
body:not(.presenting) #zoomLayer {
  padding:
    calc(var(--pan) + var(--shell-top) + 26px)
    calc(var(--pan) + var(--shell-right) + 22px)
    calc(var(--pan) + 112px)
    calc(var(--pan) + var(--shell-left) + 22px);
}
@media (max-width: 760px) {
  body:not(.presenting) #zoomLayer {
    padding: calc(var(--pan) + var(--shell-top) + 10px) calc(var(--pan) + 16px)
             calc(var(--pan) + 96px) calc(var(--pan) + 16px);
  }
}

/* ---- rulers must not draw a page edge ---- */
/* They fade toward the floating panels rather than stopping at a hard line. */
body:not(.embed-mode):not(.presenting) #ckRulerH {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 46px, #000 calc(100% - 46px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 46px, #000 calc(100% - 46px), transparent 100%);
}
body:not(.embed-mode):not(.presenting) #ckRulerV {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 46px, #000 calc(100% - 46px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 46px, #000 calc(100% - 46px), transparent 100%);
}

/* ---- export frame (opt-in, never a white page) ---- */
#expFrame {
  position: absolute; z-index: 3; pointer-events: none;
  border: 1px dashed color-mix(in srgb, var(--accent) 58%, transparent);
  border-radius: 2px;
}
#expFrame[hidden] { display: none; }
body.frame-focus #expFrame { box-shadow: 0 0 0 100vmax color-mix(in srgb, #0a0d18 38%, transparent); }
/* Bottom-RIGHT: the aspect guide's own verdict badge owns the top-left, and
   two labels stacked there overlapped into noise. */
#expFrameTag {
  position: absolute; right: 0; top: 100%; margin-top: 6px;
  padding: 3px 8px; border-radius: 6px; white-space: nowrap;
  font: 600 10.5px/1.4 var(--mono);
  color: var(--muted); background: var(--lw-surface);
  -webkit-backdrop-filter: var(--lw-blur); backdrop-filter: var(--lw-blur);
  border: 1px solid var(--lw-surface-border);
}
body.presenting #expFrame, body.watching #expFrame, body.recording #expFrame,
body.embed-mode #expFrame { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  #zoomLayer, #canvasWrap { transition: none; }
}

/* ---- six-theme selector (pass 3) ----
   A theme is a whole visual system, so its preview shows the system: canvas,
   heading type, two node kinds at the theme's own radius, a primary and a
   secondary connector, and a note. Six large cards, not two dozen chips. */
.style-pop-themes { width: 340px; }
.style-pop-themes > .theme-grid { display: flex; flex-direction: column; gap: 8px; }
.theme-card6 {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 7px; border-radius: 11px; text-align: left;
  background: var(--chrome-2); border: 1px solid var(--border-soft);
  transition: border-color var(--dur-1), background var(--dur-1);
}
.theme-card6:hover { border-color: var(--accent); background: var(--chrome-3); }
.theme-card6.active { border-color: var(--accent); background: var(--accent-soft); }
.theme-card6:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tc6-prev { flex: none; width: 116px; height: 65px; border-radius: 7px; overflow: hidden;
  border: 1px solid var(--border); display: block; }
.tc6-prev svg { display: block; width: 100%; height: 100%; }
.tc6-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tc6-meta b { font-size: 13px; font-weight: 650; color: var(--text); }
.tc6-meta small { font-size: 11px; color: var(--muted); }
/* legacy: kept, clearly labelled, and never the default choice */
.theme-legacy {
  display: flex; flex-direction: column; gap: 5px; margin-top: 10px;
  padding: 9px 11px; border-radius: 10px;
  background: color-mix(in srgb, #f59e0b 10%, transparent);
  border: 1px solid color-mix(in srgb, #f59e0b 34%, var(--border));
}
.theme-legacy b { font-size: 11.5px; color: var(--text); }
.theme-legacy span { font-size: 11.5px; line-height: 1.45; color: var(--muted); }
.theme-legacy-try {
  align-self: flex-start; margin-top: 2px; padding: 5px 10px; border-radius: 7px;
  font-size: 11.5px; font-weight: 600; color: var(--accent-ink);
  background: var(--accent-soft); border: 1px solid var(--accent-ring);
}
.theme-legacy-all { margin-top: 10px; }
.theme-legacy-all > summary {
  list-style: none; cursor: pointer; font-size: 11.5px; font-weight: 600;
  color: var(--muted); padding: 7px 2px;
}
.theme-legacy-all > summary::-webkit-details-marker { display: none; }
.theme-legacy-all > summary:hover { color: var(--text); }
.theme-grid-legacy { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding-top: 4px; }


/* ============================================================
   THE HAND CHROME SKIN (body.pr-hand — doodle documents in Present).
   LAST IN THE FILE, NON-NEGOTIABLE: the Present polish sections above set
   type with `font:` SHORTHANDS (e.g. `font: 760 .../1.15 var(--sans)` on the
   panel title), which reset font-family and silently beat any earlier rule of
   equal specificity — that is exactly how the first version of this skin
   applied to the note body and not to the titles beside it. Position wins the
   ties; the !important on font-family alone wins against the shorthands that
   polish sections may yet grow. Everything else here is plain.
   ============================================================ */
body.presenting.pr-hand #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-hand #prNoteTitle,
body.presenting.pr-hand #prNoteStep,
body.presenting.pr-hand #prNarrationHead,
body.presenting.pr-hand #prNoteTakeaway,
body.presenting.pr-hand #prCaption,
body.presenting.pr-hand #prSubtitle,
body.presenting.pr-hand #prWhyDock,
body.presenting.pr-hand #prWhyDock .pr-why-label,
body.presenting.pr-hand #prTitleCardTitle,
body.presenting.pr-hand #prTitleCardHeader,
body.presenting.pr-hand #prTitleCardFooter,
body.presenting.pr-hand #prIntroTitle,
body.presenting.pr-hand #prIntroHeader,
body.presenting.pr-hand #prIntroMeta,
body.presenting.pr-hand #prTvTitle,
body.presenting.pr-hand #prZenTitleText,
body.presenting.pr-hand #prZenStep,
body.presenting.pr-hand #prTvStep,
body.presenting.pr-hand #prStepTime,
body.presenting.pr-hand .pr-tv-word,
body.presenting.pr-hand #prProgress,
body.presenting.pr-hand #prEnd h2 {
  font-family: 'Chalkboard SE', 'Segoe Print', 'Comic Neue', 'Bradley Hand',
    'Comic Sans MS', 'Marker Felt', cursive !important;
}
/* BRIGHT ink (operator): the handwriting reads best crisp and near-black on
   the white paper — the sheet-ink token is lifted for every panel consumer,
   and the two titles take full strength plus a touch more weight. */
body.presenting.pr-hand { --pr-sheet-ink: #1c212b; }
body.presenting.pr-hand #prNoteTitle { color: #1c212b; font-weight: 700; }
body.presenting.pr-hand #prTvTitle { color: var(--pr-sheet-ink); font-weight: 700; }
body.presenting.pr-hand #prZenTitleText { font-weight: 700 !important; }
body.presenting.pr-hand #prNarration[data-note-style] #prNarrationText { font-weight: 600; }
/* Doodle (`sketch`) and Handwritten Notes (`write`) opt into dense, clean
   hand type. Sticky Notes deliberately keeps its lighter workshop lettering. */
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prTvTitle {
  font-weight: 700 !important;
}
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prNarration[data-note-style] #prNarrationText {
  font-weight: 650 !important;
}
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prZenTitleText {
  font-weight: 750 !important;
}
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prCaption,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prSubtitle,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prWhyDockText,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prTitleCardHeader,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prTitleCardFooter,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prIntroHeader,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prIntroMeta {
  font-weight: 650 !important;
}
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prTitleCardTitle,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prIntroTitle,
body.presenting.pr-hand.pr-story:is([data-pr-story="sketch"], [data-pr-story="write"]) #prEnd h2 {
  font-weight: 750 !important;
}
/* The brand marks wobble through the page-level filter (index.html
   #prHandChromeFx) and sit a touch off-axis. */
body.presenting.pr-hand #prTvHome svg,
body.presenting.pr-hand #prZenMark svg,
body.presenting.pr-hand #prZenTitle .pr-stage-mark svg,
body.presenting.pr-hand #prTitleCardMark svg,
body.presenting.pr-hand .pr-intro-mark svg {
  filter: url(#prHandChromeFx);
  transform: rotate(-2deg);
}
body.presenting.pr-hand .pr-tv-word { transform: rotate(-0.8deg); }
/* The FULL name in the doodle header (operator, Aug 24): the zen title bar
   carries only the D mark, so the wordmark is drawn on as the mark button's
   ::after — handwritten, ink-dark, tilted with the mark. Content in CSS is
   presentation-only text (the button's aria-label still says everything), and
   it keeps the skin self-contained: no markup change, no other theme sees it. */
body.presenting.pr-hand #prZenMark {
  width: auto !important;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  overflow: visible;
}
body.presenting.pr-hand #prZenMark::after {
  content: 'Diagramium';
  font-family: 'Chalkboard SE', 'Segoe Print', 'Comic Neue', 'Bradley Hand',
    'Comic Sans MS', 'Marker Felt', cursive;
  font-size: 15px;
  font-weight: 700;
  color: #1c212b;
  letter-spacing: -.01em;
  transform: rotate(-1.2deg);
  white-space: nowrap;
}
/* The why card is a HANDWRITTEN PAPER NOTE under the hand skin (operator,
   Aug 23 night — "pure handwritten note section"): pale sticky-note paper, a
   pencil-grey hand-drawn outline (the uneven four-corner radius), a soft
   drop like a note lying on the page, and nothing of the product panel left —
   no rules, no chrome borders, no tinted plate. !important against the
   Present polish sections for the same reason as the font block above. */
body.presenting.pr-hand #prWhyDock,
/* The zen redesign styles the dock through a (1,5,1)-specificity chain with
   its own !important background and borders — and zen surfaces are the
   DEFAULT dress of the redesigned Present, which is why the paper note kept
   losing while looking correct in isolation. Among !important declarations
   specificity decides, so the skin carries a zen-strength selector of its
   own. */
body.pr-hand.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  background: #fffbe6 !important;
  border: 2.2px solid #444a55 !important;
  border-top: 2.2px solid #444a55 !important;
  /* Opposite corner-pair to the ::after pass below — two strokes that agree
     nowhere is what reads as drawn twice by hand. */
  border-radius: 18px 240px 20px 235px / 235px 18px 245px 20px !important;
  box-shadow: 3px 4px 0 rgba(49, 54, 63, 0.10) !important;
  transform: rotate(-1.2deg);
  padding: 12px 15px !important;
  color: #31363f !important;
  position: relative;
}
/* THE SECOND PEN PASS. One uneven-radius border still reads as a CSS trick;
   what sells "drawn by hand" is the doubled outline — the second stroke a
   hand lays when the first didn't feel closed. Slightly inset, its OWN corner
   radii, a touch rotated, half strength — on the dock's own ::after. */
body.presenting.pr-hand #prWhyDock::after,
body.pr-hand.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden])::after {
  content: '';
  position: absolute;
  inset: -5px -4px -4px -6px;
  border: 2px solid rgba(68, 74, 85, 0.45);
  border-radius: 245px 20px 230px 16px / 16px 230px 22px 250px;
  transform: rotate(0.9deg);
  pointer-events: none;
}
body.presenting.pr-hand #prWhyDock .pr-why-label,
body.pr-hand.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label {
  color: #8a6d1a !important;
  border: 0 !important;
  letter-spacing: .06em;
}
/* The lightbulb chip drops its product gradient for a hand-drawn box. */
body.presenting.pr-hand #prWhyDock .pr-whyd-chip,
body.pr-hand.pr-zen.presenting:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip {
  background: transparent !important;
  border: 1.8px solid #444a55 !important;
  border-radius: 9px 2px 8px 3px / 3px 8px 2px 9px !important;
  color: #8a6d1a !important;
}

/* ============================================================
   PER-THEME CHROME SKINS (operator, Aug 24 — every theme dresses its stage).
   Same position-and-!important contract as the hand skin above, for the same
   reason: the Present polish sections set type with `font:` shorthands, and a
   skin that loses those ties silently is a skin that only works on the panel
   it was tested on. Each block is deliberately SMALL — type identity on the
   reading surfaces plus one flavour note; colour identity comes free from
   --pr-focus, which enterPresent sets to every theme's own ui.emphasis.
   ============================================================ */
/* MONO — Obsidian. The numbers are the personality: step counters, clock and
   chips in the terminal face; titles stay clean sans. */
body.presenting.pr-chrome-mono #prNoteStep,
body.presenting.pr-chrome-mono #prTvStep,
body.presenting.pr-chrome-mono #prZenStep,
body.presenting.pr-chrome-mono #prStepTime,
body.presenting.pr-chrome-mono #prIntroMeta,
body.presenting.pr-chrome-mono #prProgress,
body.presenting.pr-chrome-mono #prCaption {
  font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace !important;
  letter-spacing: .02em;
}

/* SERIF — Editorial and Executive Navy. The whole reading register goes to
   the book face; counters stay sans so numbers read as apparatus, not prose. */
body.presenting.pr-chrome-serif #prNoteTitle,
body.presenting.pr-chrome-serif #prTvTitle,
body.presenting.pr-chrome-serif #prZenTitleText,
body.presenting.pr-chrome-serif #prTitleCardTitle,
body.presenting.pr-chrome-serif #prIntroTitle,
body.presenting.pr-chrome-serif #prEnd h2,
body.presenting.pr-chrome-serif #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-serif #prWhyDock,
body.presenting.pr-chrome-serif #prCaption,
body.presenting.pr-chrome-serif #prSubtitle,
body.presenting.pr-chrome-serif #prTitleCardHeader,
body.presenting.pr-chrome-serif #prTitleCardFooter,
body.presenting.pr-chrome-serif #prIntroHeader {
  font-family: Georgia, 'Iowan Old Style', 'Palatino Linotype', 'Times New Roman', serif !important;
}

/* SOFT — Canvas and Forest. Rounded, warm, nothing sharp. */
body.presenting.pr-chrome-soft #prNoteTitle,
body.presenting.pr-chrome-soft #prTvTitle,
body.presenting.pr-chrome-soft #prZenTitleText,
body.presenting.pr-chrome-soft #prTitleCardTitle,
body.presenting.pr-chrome-soft #prIntroTitle,
body.presenting.pr-chrome-soft #prEnd h2 {
  font-family: ui-rounded, 'SF Pro Rounded', 'Hiragino Maru Gothic ProN',
    'Arial Rounded MT Bold', system-ui, sans-serif !important;
}

/* GLOW — Aurora. No font change; the big titles carry the aurora halo. */
body.presenting.pr-chrome-glow #prZenTitleText,
body.presenting.pr-chrome-glow #prTvTitle,
body.presenting.pr-chrome-glow #prTitleCardTitle,
body.presenting.pr-chrome-glow #prIntroTitle {
  text-shadow: 0 0 18px rgba(155, 140, 245, 0.55), 0 0 42px rgba(79, 199, 212, 0.25);
}

/* WORKSHOP — Sticky Notes. Rides ON TOP of the hand skin (enterPresent sets
   both classes): the why card becomes a mint sticky rather than the doodle's
   yellow paper, and the step chip wears a sticky tab. */
body.presenting.pr-chrome-workshop #prWhyDock,
body.pr-hand.pr-zen.presenting.pr-chrome-workshop:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  background: #c9ecd7 !important;
  border-color: #5d9b77 !important;
  transform: rotate(0.8deg);
}
body.presenting.pr-chrome-workshop #prNoteStep {
  background: #ffe97a !important;
  color: #2b2620 !important;
  border-radius: 2px 2px 6px 6px !important;
  padding: 2px 8px !important;
  box-shadow: 1px 2px 0 rgba(43, 38, 32, 0.18);
}

/* TERM — the Retro Terminal. Everything the audience reads is monospace, the
   step chip is a shell prompt, and the two big titles carry the phosphor
   glow. The scanlines are NOT here — they are a sheet pattern
   (drawThemeTexture 'scanlines'), so exports carry the tube too. */
body.presenting.pr-chrome-term #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-term #prNoteTitle,
body.presenting.pr-chrome-term #prNoteStep,
body.presenting.pr-chrome-term #prCaption,
body.presenting.pr-chrome-term #prSubtitle,
body.presenting.pr-chrome-term #prWhyDock,
body.presenting.pr-chrome-term #prTvTitle,
body.presenting.pr-chrome-term #prZenTitleText,
body.presenting.pr-chrome-term #prZenStep,
body.presenting.pr-chrome-term #prTvStep,
body.presenting.pr-chrome-term #prStepTime,
body.presenting.pr-chrome-term #prIntroMeta,
body.presenting.pr-chrome-term #prIntroTitle,
body.presenting.pr-chrome-term #prIntroHeader,
body.presenting.pr-chrome-term #prTitleCardTitle,
body.presenting.pr-chrome-term #prTitleCardHeader,
body.presenting.pr-chrome-term #prTitleCardFooter,
body.presenting.pr-chrome-term #prProgress,
body.presenting.pr-chrome-term #prEnd h2 {
  font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace !important;
  letter-spacing: .01em;
}
body.presenting.pr-chrome-term #prNoteStep::before { content: '$ '; opacity: .8; }
body.presenting.pr-chrome-term #prNoteStep {
  background: #07100a !important;
  color: #5cff96 !important;
  border: 1px solid #2f9e58 !important;
  border-radius: 3px !important;
  padding: 2px 8px !important;
  text-transform: none !important;
}
body.presenting.pr-chrome-term #prZenTitleText,
body.presenting.pr-chrome-term #prTvTitle,
body.presenting.pr-chrome-term #prTitleCardTitle,
body.presenting.pr-chrome-term #prIntroTitle {
  text-shadow: 0 0 10px rgba(92, 255, 150, 0.45);
}
/* The blinking block cursor after the header title — the terminal is live. */
body.presenting.pr-chrome-term #prZenTitleText::after,
body.presenting.pr-chrome-term #prTvTitle:not(:empty)::after {
  content: '▌';
  margin-left: 3px;
  animation: prTermBlink 1.1s steps(1) infinite;
}
@keyframes prTermBlink { 50% { opacity: 0; } }
/* stepMarker 'pulse': the spoken shape's own group breathes in the theme's
   focus colour — no injected outline, no second geometry. drop-shadow wraps
   the group's real silhouette (box AND label), which on a glowing theme reads
   as the panel powering up rather than being pointed at. */
.pr-focus-pulse {
  animation: prOwnPulse 1.5s ease-in-out infinite;
}
@keyframes prOwnPulse {
  0%, 100% { filter: drop-shadow(0 0 2px var(--pr-focus, #4f46e5)); }
  50% { filter: drop-shadow(0 0 9px var(--pr-focus, #4f46e5))
               drop-shadow(0 0 20px color-mix(in srgb, var(--pr-focus, #4f46e5) 45%, transparent)); }
}
@media (prefers-reduced-motion: reduce) {
  .pr-focus-pulse { animation: none; filter: drop-shadow(0 0 6px var(--pr-focus, #4f46e5)); }
}

/* ---- the four new chrome skins (same end-of-file contract) ---- */
/* TRANSIT — Metro Map: the signage register — heavy, tight, unmistakably
   wayfinding — and the step chip becomes a line roundel. */
body.presenting.pr-chrome-transit #prNoteTitle,
body.presenting.pr-chrome-transit #prTvTitle,
body.presenting.pr-chrome-transit #prZenTitleText,
body.presenting.pr-chrome-transit #prTitleCardTitle,
body.presenting.pr-chrome-transit #prIntroTitle,
body.presenting.pr-chrome-transit #prEnd h2 {
  font-weight: 780 !important;
  letter-spacing: -.015em;
}
body.presenting.pr-chrome-transit #prNoteStep {
  background: #d1310f !important;
  color: #ffffff !important;
  border: 2.5px solid #20242e !important;
  border-radius: 999px !important;
  padding: 3px 11px !important;
}
/* MISSION — telemetry numbers in mono, ice glow on the titles, and the step
   chip reads as a mission clock. */
body.presenting.pr-chrome-mission #prNoteStep,
body.presenting.pr-chrome-mission #prTvStep,
body.presenting.pr-chrome-mission #prZenStep,
body.presenting.pr-chrome-mission #prStepTime,
body.presenting.pr-chrome-mission #prIntroMeta,
body.presenting.pr-chrome-mission #prProgress {
  font-family: ui-monospace, 'SF Mono', Menlo, monospace !important;
  letter-spacing: .03em;
}
body.presenting.pr-chrome-mission #prNoteStep::before { content: 'T+'; opacity: .75; }
body.presenting.pr-chrome-mission #prZenTitleText,
body.presenting.pr-chrome-mission #prTvTitle,
body.presenting.pr-chrome-mission #prTitleCardTitle,
body.presenting.pr-chrome-mission #prIntroTitle {
  text-shadow: 0 0 14px rgba(87, 184, 255, 0.45);
}
/* DRAFT — Blueprint Atelier: the title block — condensed capitals, wide
   tracking, ruled like a drawing's corner stamp. */
body.presenting.pr-chrome-draft #prNoteTitle,
body.presenting.pr-chrome-draft #prTvTitle,
body.presenting.pr-chrome-draft #prZenTitleText,
body.presenting.pr-chrome-draft #prTitleCardTitle,
body.presenting.pr-chrome-draft #prIntroTitle,
body.presenting.pr-chrome-draft #prEnd h2 {
  font-family: 'Avenir Next Condensed', 'Arial Narrow', 'Roboto Condensed',
    'Helvetica Neue', sans-serif !important;
  text-transform: uppercase;
  letter-spacing: .09em;
}
body.presenting.pr-chrome-draft #prNoteStep {
  border: 1px solid rgba(234, 243, 253, 0.7) !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #eaf3fd !important;
  padding: 2px 9px !important;
}
/* NEON — the diner: script titles burning pink, everything else legible sans. */
body.presenting.pr-chrome-neon #prNoteTitle,
body.presenting.pr-chrome-neon #prTvTitle,
body.presenting.pr-chrome-neon #prZenTitleText,
body.presenting.pr-chrome-neon #prTitleCardTitle,
body.presenting.pr-chrome-neon #prIntroTitle,
body.presenting.pr-chrome-neon #prEnd h2 {
  font-family: 'Snell Roundhand', 'Brush Script MT', 'Segoe Script', cursive !important;
  font-weight: 700 !important;
  text-shadow: 0 0 8px rgba(255, 79, 163, 0.75), 0 0 26px rgba(255, 79, 163, 0.35);
  letter-spacing: .01em;
}

/* NOTE — Handwritten Notes. Rides ON TOP of the hand skin (sketchReveal sets
   pr-hand too), so it must retake the fonts pr-hand forced: the professional
   hand writes with Bradley Hand / Segoe Print, never Comic Sans. Same
   position-and-!important contract as every skin above. */
body.presenting.pr-chrome-note #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-note #prNoteTitle,
body.presenting.pr-chrome-note #prNoteStep,
body.presenting.pr-chrome-note #prNarrationHead,
body.presenting.pr-chrome-note #prNoteTakeaway,
body.presenting.pr-chrome-note #prCaption,
body.presenting.pr-chrome-note #prSubtitle,
body.presenting.pr-chrome-note #prWhyDock,
body.presenting.pr-chrome-note #prWhyDock .pr-why-label,
body.presenting.pr-chrome-note #prTitleCardTitle,
body.presenting.pr-chrome-note #prTitleCardHeader,
body.presenting.pr-chrome-note #prTitleCardFooter,
body.presenting.pr-chrome-note #prIntroTitle,
body.presenting.pr-chrome-note #prIntroHeader,
body.presenting.pr-chrome-note #prIntroMeta,
body.presenting.pr-chrome-note #prTvTitle,
body.presenting.pr-chrome-note #prZenTitleText,
body.presenting.pr-chrome-note #prZenStep,
body.presenting.pr-chrome-note #prTvStep,
body.presenting.pr-chrome-note #prStepTime,
body.presenting.pr-chrome-note .pr-tv-word,
body.presenting.pr-chrome-note #prProgress,
body.presenting.pr-chrome-note #prEnd h2,
body.presenting.pr-chrome-note #prZenMark::after {
  font-family: 'Bradley Hand', 'Segoe Print', Noteworthy, 'Comic Neue',
    'Chalkboard SE', cursive !important;
}
/* Blue-black ink on the cream page; titles take pen weight. */
body.presenting.pr-chrome-note { --pr-sheet-ink: #1c2b52; }
body.presenting.pr-chrome-note #prNoteTitle { color: #1c2b52; font-weight: 700; }
body.presenting.pr-chrome-note #prZenMark::after { color: #1c2b52; }
/* The why card is the SAMPLE's yellow sticky: warm yellow paper, the red
   hand-lettered label with its underline, dark ink body, a light tilt.
   Zen-strength pair (+ the skin class beats pr-hand's own zen dock rule,
   the workshop precedent at its comment). */
body.presenting.pr-chrome-note:not(.pr-guide-collapsed) #prWhyDock:not([hidden]),
body.pr-hand.pr-zen.presenting.pr-chrome-note:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  background: #f4dd74 !important;
  border: 1.6px solid rgba(120, 96, 20, 0.45) !important;
  border-radius: 3px 6px 4px 7px / 6px 3px 7px 4px !important;
  box-shadow: 2px 4px 8px rgba(74, 60, 12, 0.22) !important;
  transform: rotate(0.9deg);
  color: #2b2620 !important;
}
body.presenting.pr-chrome-note:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label,
body.pr-hand.pr-zen.presenting.pr-chrome-note:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label {
  color: #b4232a !important;
  border: 0 !important;
  border-bottom: 2px solid #b4232a !important;
  padding-bottom: 2px;
  letter-spacing: .05em;
}
body.presenting.pr-chrome-note:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip,
body.pr-hand.pr-zen.presenting.pr-chrome-note:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip {
  background: transparent !important;
  border: 1.6px solid #b4232a !important;
  border-radius: 8px 3px 7px 4px / 4px 7px 3px 8px !important;
  color: #b4232a !important;
}
/* The step chip is a margin note: paper ground, ink box, red step number. */
body.presenting.pr-chrome-note #prNoteStep {
  background: #fffdf4 !important;
  color: #b4232a !important;
  border: 1.6px solid #2c3e66 !important;
  border-radius: 7px 3px 8px 3px / 3px 8px 3px 7px !important;
  padding: 2px 9px !important;
}
/* The step picture sits in a simple hand-drawn frame (this skin's deliberate
   exception to the frameless guide default — same chain + the skin class,
   later in the file, so it wins without touching other themes). */
body.presenting.pr-chrome-note:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]),
body.presenting.pr-chrome-note:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  background: #fffdf4;
  border: 2px solid #444a55;
  border-radius: 13px 8px 12px 9px / 9px 12px 8px 13px;
  padding: 4px;
  box-shadow: 2px 3px 0 rgba(49, 54, 63, 0.12);
}

/* SKETCH — Sketchnote (explainer doodles). Rides ON TOP of the hand skin
   (chrome 'sketch' is in the pr-hand family list in enterPresent), so it
   must retake the fonts pr-hand forced: the explainer hand prints with
   Bradley Hand / Segoe Print, never Comic Sans. Same position-and-!important
   contract as every skin above; the note skin is the template. */
body.presenting.pr-chrome-sketch #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-sketch #prNoteTitle,
body.presenting.pr-chrome-sketch #prNoteStep,
body.presenting.pr-chrome-sketch #prNarrationHead,
body.presenting.pr-chrome-sketch #prNoteTakeaway,
body.presenting.pr-chrome-sketch #prCaption,
body.presenting.pr-chrome-sketch #prSubtitle,
body.presenting.pr-chrome-sketch #prWhyDock,
body.presenting.pr-chrome-sketch #prWhyDock .pr-why-label,
body.presenting.pr-chrome-sketch #prTitleCardTitle,
body.presenting.pr-chrome-sketch #prTitleCardHeader,
body.presenting.pr-chrome-sketch #prTitleCardFooter,
body.presenting.pr-chrome-sketch #prIntroTitle,
body.presenting.pr-chrome-sketch #prIntroHeader,
body.presenting.pr-chrome-sketch #prIntroMeta,
body.presenting.pr-chrome-sketch #prTvTitle,
body.presenting.pr-chrome-sketch #prZenTitleText,
body.presenting.pr-chrome-sketch #prZenStep,
body.presenting.pr-chrome-sketch #prTvStep,
body.presenting.pr-chrome-sketch #prStepTime,
body.presenting.pr-chrome-sketch .pr-tv-word,
body.presenting.pr-chrome-sketch #prProgress,
body.presenting.pr-chrome-sketch #prEnd h2,
body.presenting.pr-chrome-sketch #prZenMark::after {
  font-family: 'Bradley Hand', 'Segoe Print', Noteworthy, 'Comic Neue',
    'Chalkboard SE', cursive !important;
}
/* Near-black fineliner ink on white paper; titles take marker weight. */
body.presenting.pr-chrome-sketch { --pr-sheet-ink: #20242c; }
body.presenting.pr-chrome-sketch #prNoteTitle { color: #20242c; font-weight: 700; }
body.presenting.pr-chrome-sketch #prZenMark::after { color: #20242c; }
/* The why card is an index card off the whiteboard: white paper, thin ink
   hand border, the presenter-red hand-lettered label. Zen-strength pair —
   the skin class beats pr-hand's own zen dock rule (the note precedent). */
body.presenting.pr-chrome-sketch:not(.pr-guide-collapsed) #prWhyDock:not([hidden]),
body.pr-hand.pr-zen.presenting.pr-chrome-sketch:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  background: #ffffff !important;
  border: 1.7px solid #2b2f38 !important;
  border-radius: 4px 8px 5px 9px / 8px 4px 9px 5px !important;
  box-shadow: 2px 4px 0 rgba(32, 36, 44, 0.14) !important;
  transform: rotate(-0.6deg);
  color: #20242c !important;
}
body.presenting.pr-chrome-sketch:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label,
body.pr-hand.pr-zen.presenting.pr-chrome-sketch:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label {
  color: #c9303e !important;
  border: 0 !important;
  border-bottom: 2px dashed #c9303e !important;
  padding-bottom: 2px;
  letter-spacing: .05em;
}
body.presenting.pr-chrome-sketch:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip,
body.pr-hand.pr-zen.presenting.pr-chrome-sketch:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip {
  background: transparent !important;
  border: 1.6px solid #c9303e !important;
  border-radius: 8px 3px 7px 4px / 4px 7px 3px 8px !important;
  color: #c9303e !important;
}
/* The step chip is circled in the presenter's red — the loop, miniature. */
body.presenting.pr-chrome-sketch #prNoteStep {
  background: #ffffff !important;
  color: #20242c !important;
  border: 1.8px solid #c9303e !important;
  border-radius: 12px 9px 13px 8px / 9px 13px 8px 12px !important;
  padding: 2px 9px !important;
}
/* The step picture wears the whiteboard's thin ink frame (same deliberate
   exception to the frameless guide default as the note skin). */
body.presenting.pr-chrome-sketch:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]),
body.presenting.pr-chrome-sketch:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  background: #ffffff;
  border: 2px solid #2b2f38;
  border-radius: 9px 13px 8px 12px / 13px 9px 12px 8px;
  padding: 4px;
  box-shadow: 2px 3px 0 rgba(32, 36, 44, 0.12);
}

/* PENCIL — Pencil Sketch (Sketchnote in pure graphite). Same contract as
   the sketch skin above, with every accent a grey: no colour anywhere is
   the theme's whole promise, so even the chrome writes in pencil. */
body.presenting.pr-chrome-pencil #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-pencil #prNoteTitle,
body.presenting.pr-chrome-pencil #prNoteStep,
body.presenting.pr-chrome-pencil #prNarrationHead,
body.presenting.pr-chrome-pencil #prNoteTakeaway,
body.presenting.pr-chrome-pencil #prCaption,
body.presenting.pr-chrome-pencil #prSubtitle,
body.presenting.pr-chrome-pencil #prWhyDock,
body.presenting.pr-chrome-pencil #prWhyDock .pr-why-label,
body.presenting.pr-chrome-pencil #prTitleCardTitle,
body.presenting.pr-chrome-pencil #prTitleCardHeader,
body.presenting.pr-chrome-pencil #prTitleCardFooter,
body.presenting.pr-chrome-pencil #prIntroTitle,
body.presenting.pr-chrome-pencil #prIntroHeader,
body.presenting.pr-chrome-pencil #prIntroMeta,
body.presenting.pr-chrome-pencil #prTvTitle,
body.presenting.pr-chrome-pencil #prZenTitleText,
body.presenting.pr-chrome-pencil #prZenStep,
body.presenting.pr-chrome-pencil #prTvStep,
body.presenting.pr-chrome-pencil #prStepTime,
body.presenting.pr-chrome-pencil .pr-tv-word,
body.presenting.pr-chrome-pencil #prProgress,
body.presenting.pr-chrome-pencil #prEnd h2,
body.presenting.pr-chrome-pencil #prZenMark::after {
  font-family: 'Bradley Hand', 'Segoe Print', Noteworthy, 'Comic Neue',
    'Chalkboard SE', cursive !important;
}
/* Graphite ink — a pencil never prints full black. */
body.presenting.pr-chrome-pencil { --pr-sheet-ink: #2e343d; }
body.presenting.pr-chrome-pencil #prNoteTitle { color: #2e343d; font-weight: 700; }
body.presenting.pr-chrome-pencil #prZenMark::after { color: #2e343d; }
/* The why card is a pencil-ruled index card: white paper, grey graphite
   border, the label underlined in pencil. Zen-strength pair as above. */
body.presenting.pr-chrome-pencil:not(.pr-guide-collapsed) #prWhyDock:not([hidden]),
body.pr-hand.pr-zen.presenting.pr-chrome-pencil:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  background: #ffffff !important;
  border: 1.7px solid #4a515c !important;
  border-radius: 4px 8px 5px 9px / 8px 4px 9px 5px !important;
  box-shadow: 2px 4px 0 rgba(46, 52, 61, 0.12) !important;
  transform: rotate(-0.6deg);
  color: #2e343d !important;
}
body.presenting.pr-chrome-pencil:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label,
body.pr-hand.pr-zen.presenting.pr-chrome-pencil:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-why-label {
  color: #343b45 !important;
  border: 0 !important;
  border-bottom: 2px solid #4a515c !important;
  padding-bottom: 2px;
  letter-spacing: .05em;
}
body.presenting.pr-chrome-pencil:not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip,
body.pr-hand.pr-zen.presenting.pr-chrome-pencil:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) .pr-whyd-chip {
  background: transparent !important;
  border: 1.6px solid #4a515c !important;
  border-radius: 8px 3px 7px 4px / 4px 7px 3px 8px !important;
  color: #343b45 !important;
}
/* The step chip is circled with the pencil, pressed harder. */
body.presenting.pr-chrome-pencil #prNoteStep {
  background: #ffffff !important;
  color: #2e343d !important;
  border: 1.8px solid #343b45 !important;
  border-radius: 12px 9px 13px 8px / 9px 13px 8px 12px !important;
  padding: 2px 9px !important;
}
/* The step picture in a plain graphite frame. */
body.presenting.pr-chrome-pencil:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarration[data-note-style] #prNarrationImg:not([hidden]),
body.presenting.pr-chrome-pencil:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prNarrationImg:not([hidden]) {
  background: #ffffff;
  border: 2px solid #4a515c;
  border-radius: 9px 13px 8px 12px / 13px 9px 12px 8px;
  padding: 4px;
  box-shadow: 2px 3px 0 rgba(46, 52, 61, 0.12);
}

/* ============================================================
   DRAWBOOK — a clean light landscape book.
   Notebook Novel's book chrome rebuilt for a SINGLE 16:9 sheet: no centre
   spine, facing leaf, visible binding, holes or rings. Every quick page turn
   still hinges on the left. Colour/type/duration arrive through the same
   --pr-book-* vars syncNotebookBookStyle publishes for any fx.book theme.
   ============================================================ */
body.presenting.pr-chrome-drawbook #stage {
  background:
    radial-gradient(115% 120% at 50% 18%, rgba(255, 255, 255, 0.9), transparent 58%),
    linear-gradient(135deg, #f4f1ea, #e7e4de);
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
    env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  --pr-plate: 0px;
}
body.presenting.pr-chrome-drawbook #canvasWrap {
  perspective: 1700px;
  perspective-origin: 22% 46%;
}
body.presenting.pr-chrome-drawbook #prTvHead,
body.presenting.pr-chrome-drawbook #prStepper,
body.presenting.pr-chrome-drawbook #prNarration { display: none !important; }
/* The sheet carries its own running title and folio (composed into the SVG,
   the notebook doctrine) — no generic header, no second title strip, no
   step chip. The zen title lane's padding reserve goes with it. */
body.presenting.pr-chrome-drawbook #prZenTitle { display: none !important; }
body.pr-zen-title.presenting.pr-chrome-drawbook #canvasWrap { padding-top: 0 !important; }
body.presenting.pr-chrome-drawbook #zoomLayer { display: grid; place-items: center; padding: 0; }

/* THE SHEET. The svg is only ink; the host paints one quiet premium paper
   surface with a restrained page edge and no visible binding. */
body.presenting.pr-chrome-drawbook #svgHost {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.52), transparent 42%),
    radial-gradient(120% 90% at 58% 42%, rgba(255, 255, 255, 0.42), transparent 62%),
    var(--pr-book-cream, #fbfaf5);
  border-radius: 10px;
  box-shadow:
    2px 3px 0 -1px var(--pr-book-edge, #efe9da),
    5px 6px 0 -2px rgba(40, 48, 60, 0.08),
    0 22px 44px rgba(43, 49, 58, 0.18);
  transform-style: preserve-3d;
}
body.presenting.pr-chrome-drawbook.pr-spot-fill #stage,
body.presenting.pr-chrome-drawbook.pr-spot-fill #canvasWrap {
  background: var(--pr-book-cream, #fbfaf5);
}
body.presenting.pr-chrome-drawbook.pr-spot-fill #canvasWrap {
  --pr-gutter: 0px;
  --pr-lane-top: 0px;
}
body.presenting.pr-chrome-drawbook.pr-spot-fill #svgHost {
  background: transparent;
  border-radius: 0;
  box-shadow: none;
}
/* The former coil pseudo-element stays explicitly empty so an older cached
   theme token cannot restore rings or punched holes. */
body.presenting.pr-chrome-drawbook #svgHost::before {
  content: none;
  display: none;
}
body.presenting.pr-chrome-drawbook :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay) rect[data-kind="bg"] {
  fill: transparent !important;
  fill-opacity: 0 !important;
}
body.presenting.pr-chrome-drawbook :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay) .spot-card-surface {
  fill: transparent !important;
  stroke: none !important;
}

/* THE FLIP. JS mounts a page-sized leaf on an invisible left hinge; the
   destination sheet is already complete underneath. */
body.presenting.pr-chrome-drawbook .pr-book-page-turn {
  position: absolute;
  z-index: 7;
  transform-style: preserve-3d;
  transform-origin: left center;
  pointer-events: none;
}
body.presenting.pr-chrome-drawbook .pr-book-page-stay {
  position: absolute;
  z-index: 6;
  overflow: hidden;
  background: var(--pr-book-cream, #fbfaf5);
  border-radius: 10px;
  pointer-events: none;
}
body.presenting.pr-chrome-drawbook .pr-book-leaf-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.44), transparent 45%),
    var(--pr-book-cream, #fbfaf5);
  border-radius: 10px;
}
body.presenting.pr-chrome-drawbook .pr-book-leaf-back { transform: rotateY(180deg); }
body.presenting.pr-chrome-drawbook .pr-book-turn-forward {
  animation: prBookTurnSheetFwd var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both,
    prDrawLeafLift var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-drawbook .pr-book-turn-back {
  transform-origin: left center;
  animation: prBookTurnSheetBack var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both,
    prDrawLeafLift var(--pr-book-turn-ms, 500ms) linear both;
}
/* Forward: the old sheet lifts from its left hinge and folds over —
   it BOWS as real paper does (asymmetric rotateZ/skew through the arc,
   more flex on the way up, settling flat), casts a travelling shadow
   (prDrawLeafLift's box-shadow) and shades its own face mid-flight
   (::after). Backward mirrors it home. The 50% face handoff dodges the
   Chromium backface leak, exactly like the bound book's. */
@keyframes prBookTurnSheetFwd {
  0% { transform: rotateY(0deg) rotateZ(0deg); }
  28% { transform: rotateY(-46deg) translateZ(24px) rotateZ(0.9deg) skewY(0.5deg); }
  52% { transform: rotateY(-94deg) translateZ(34px) rotateZ(0.5deg) skewY(0.2deg); }
  78% { transform: rotateY(-148deg) translateZ(16px) rotateZ(-0.3deg); }
  100% { transform: rotateY(-178deg) rotateZ(0deg); }
}
@keyframes prBookTurnSheetBack {
  0% { transform: rotateY(-178deg) rotateZ(0deg); }
  30% { transform: rotateY(-138deg) translateZ(18px) rotateZ(-0.5deg) skewY(-0.2deg); }
  56% { transform: rotateY(-86deg) translateZ(34px) rotateZ(0.6deg) skewY(0.4deg); }
  82% { transform: rotateY(-34deg) translateZ(16px) rotateZ(0.3deg); }
  100% { transform: rotateY(0deg) rotateZ(0deg); }
}
/* The airborne sheet's shadow grows with altitude, then lands. */
@keyframes prDrawLeafLift {
  0% { box-shadow: 0 0 0 rgba(0, 0, 0, 0); }
  45% { box-shadow: -34px 22px 44px rgba(0, 0, 0, 0.38); }
  100% { box-shadow: 0 0 0 rgba(0, 0, 0, 0); }
}
/* Self-shading across the flying face at the steep part of the arc. */
body.presenting.pr-chrome-drawbook .pr-book-page-turn::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 26%, rgba(0, 0, 0, 0.14) 72%, rgba(0, 0, 0, 0.3));
  opacity: 0;
  animation: prDrawLeafShade var(--pr-book-turn-ms, 500ms) linear both;
}
@keyframes prDrawLeafShade {
  0% { opacity: 0; }
  40% { opacity: 0.85; }
  70% { opacity: 0.5; }
  100% { opacity: 0; }
}
@keyframes prDrawLeafFrontFwd { 0%, 49.99% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes prDrawLeafBackFwd { 0%, 49.99% { opacity: 0; } 50%, 100% { opacity: 1; } }
body.presenting.pr-chrome-drawbook .pr-book-turn-forward .pr-book-leaf-front {
  animation: prDrawLeafFrontFwd var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-drawbook .pr-book-turn-forward .pr-book-leaf-back {
  animation: prDrawLeafBackFwd var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-drawbook .pr-book-turn-back .pr-book-leaf-front {
  animation: prDrawLeafBackFwd var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-drawbook .pr-book-turn-back .pr-book-leaf-back {
  animation: prDrawLeafFrontFwd var(--pr-book-turn-ms, 500ms) linear both;
}
/* Moving fore-edge highlight on the flying sheet. */
body.presenting.pr-chrome-drawbook .pr-book-page-turn::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; right: -2px;
  width: 3px;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 2px;
}
@media (prefers-reduced-motion: reduce) {
  body.presenting.pr-chrome-drawbook .pr-book-page-turn,
  body.presenting.pr-chrome-drawbook .pr-book-page-stay {
    display: none !important;
    animation: none !important;
  }
}

/* THE COVER — a light 16:9 editorial board with an invisible left hinge. */
body.presenting.pr-chrome-drawbook #prIntro,
body.presenting.pr-chrome-drawbook #prEnd {
  perspective: 1900px;
  padding: 0;
  background:
    radial-gradient(120% 130% at 50% 24%, rgba(255, 255, 255, 0.9), transparent 58%),
    linear-gradient(135deg, #f4f1ea, #e7e4de);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card,
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card {
  /* FULLSCREEN cover (operator, Sep 2): the board IS the screen — the
     largest 16:9 box the window offers, edge to edge on a 16:9 display,
     honest desk bars on any other shape. Corners square off because a
     fullscreen board has no surrounding desk. */
  aspect-ratio: 16 / 9;
  width: min(100vw, calc(100vh * 1.7778));
  height: auto;
  max-height: 100vh;
  max-width: none;
  padding: 4.5% 8% 4.5% 9%;
  background:
    radial-gradient(120% 160% at 14% 0%, rgba(255, 255, 255, 0.72), transparent 46%),
    linear-gradient(118deg, transparent 34%, rgba(255, 255, 255, 0.28) 48%, transparent 62%),
    repeating-linear-gradient(23deg, rgba(48, 55, 66, 0.011) 0 1px, transparent 1px 5px),
    linear-gradient(135deg, var(--pr-book-cover, #faf8f2), var(--pr-book-cover-deep, #e8e2d8));
  border-radius: 0;
  box-shadow: 0 18px 58px rgba(44, 51, 62, 0.18);
  transform-origin: left center;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card::before,
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card::before {
  content: none;
  display: none;
}
/* Embossed frame: debossed DOUBLE rule with a lit lower edge — pressed into
   the board rather than printed on it. The inner hairline is what makes the
   jacket read as tooled rather than outlined. */
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card::after {
  content: '';
  position: absolute;
  inset: 5% 12.6% 5% 8.6%;
  border: 1.5px solid color-mix(in srgb, var(--pr-book-gold, #c9b06a) 60%, transparent);
  border-radius: 4px 10px 10px 4px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 0 0 7px transparent,
    inset 0 0 0 8px color-mix(in srgb, var(--pr-book-gold, #c9b06a) 26%, transparent),
    inset 0 0 34px rgba(66, 73, 83, 0.035),
    0 1px 0 rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

/* ---- The generated cover is an editorial JACKET, not a presentation card.
   Its main hierarchy occupies the left reading column; a quiet embossed
   network medallion balances the fore-edge without competing with the title.
   Playback furniture is deliberately subordinate and uses the cover's own
   foil/ink instead of app-blue and white control pills. */
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) {
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  padding-bottom: 11%;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-brandin {
  position: absolute;
  top: 8.2%;
  left: 10.2%;
  flex-direction: row;
  gap: clamp(8px, 0.9vw, 13px);
  margin: 0;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-brandin .pr-intro-mark {
  width: clamp(32px, 3.1vw, 46px);
  height: clamp(32px, 3.1vw, 46px);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-brandin-word {
  font-size: clamp(18px, 2vw, 29px);
  letter-spacing: -0.02em;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-eyebrow,
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-title,
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta {
  width: 52%;
  max-width: 52%;
  text-align: left;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-eyebrow {
  margin: 0 0 clamp(14px, 2vh, 24px);
  color: var(--pr-book-gold, #c8996a);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-title {
  font-size: clamp(42px, 5.5vw, 84px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.72), 0 10px 24px rgba(47, 54, 64, 0.08);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-title::after {
  content: '';
  display: block;
  width: clamp(64px, 8vw, 120px);
  height: 2px;
  margin: clamp(12px, 1.8vh, 20px) 0 0;
  background: linear-gradient(90deg, var(--pr-book-gold, #c9b06a), transparent);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta {
  justify-content: flex-start;
  gap: 0;
  margin-top: clamp(16px, 2.2vh, 24px);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta span {
  padding: 0 clamp(10px, 1vw, 15px);
  border: 0;
  border-right: 1px solid color-mix(in srgb, var(--pr-book-gold, #c9b06a) 38%, transparent);
  border-radius: 0;
  background: transparent;
  color: color-mix(in srgb, var(--pr-book-cover-ink, #f2ead8) 72%, transparent);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta span:first-child { padding-left: 0; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta span:last-child { border-right: 0; }
/* A blind-embossed systems motif gives the wide jacket an authored right
   side while remaining generic enough for every Drawing Book course. */
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-intro-meta::after {
  content: '';
  position: absolute;
  right: 15.5%;
  top: 24%;
  width: min(28vw, 34%);
  aspect-ratio: 1;
  border: 1px solid color-mix(in srgb, var(--pr-book-gold, #c9b06a) 38%, transparent);
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 72%, transparent) 0 5%, transparent 5.5%),
    radial-gradient(circle at 22% 30%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 58%, transparent) 0 2%, transparent 2.4%),
    radial-gradient(circle at 77% 26%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 52%, transparent) 0 2.2%, transparent 2.6%),
    radial-gradient(circle at 82% 72%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 54%, transparent) 0 1.9%, transparent 2.3%),
    radial-gradient(circle at 24% 76%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 48%, transparent) 0 2.1%, transparent 2.5%),
    repeating-conic-gradient(from 9deg at 50% 50%, color-mix(in srgb, var(--pr-book-gold, #c9b06a) 18%, transparent) 0 1deg, transparent 1deg 44deg);
  box-shadow:
    inset 0 0 0 12px color-mix(in srgb, var(--pr-book-gold, #c9b06a) 5%, transparent),
    0 1px 0 rgba(255, 255, 255, 0.05),
    0 18px 40px rgba(0, 0, 0, 0.2);
  opacity: 0.72;
  pointer-events: none;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) #prIntroPlay {
  margin-top: clamp(22px, 3vh, 34px);
  padding: 10px 22px 10px 12px;
  border: 1px solid color-mix(in srgb, var(--pr-book-gold, #c9b06a) 72%, transparent);
  color: var(--pr-book-cream, #faf8f2);
  /* Fallback is the BRAND IRIS, never near-black: the book vars land a
     beat after the chrome class in a fresh load, and a #222a35 fallback
     painted a black capsule under/behind the branded Play for that window
     (screenshotted live). With vars set, the cover-ink inversion is
     unchanged. */
  background: var(--pr-book-cover-ink, var(--iris, #6a5cff));
  box-shadow: 0 12px 28px rgba(44, 51, 62, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) #prIntroPlay .pr-intro-play-ico {
  width: 30px;
  height: 30px;
  color: var(--pr-book-cover-deep, #151d2d);
  background: var(--pr-book-gold, #c9b06a);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-foot {
  position: absolute;
  left: 14%;
  right: 18%;
  bottom: 8.2%;
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.6vw, 22px);
  justify-content: center;
  font-size: clamp(10px, 1vw, 13px);
  letter-spacing: 0.26em;
  opacity: 0.92;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-foot:empty { display: none; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-foot::before,
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-foot::after {
  content: '';
  flex: 1 1 24px;
  height: 1px;
  background: color-mix(in srgb, var(--pr-book-gold, #c9b06a) 44%, transparent);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-row {
  position: absolute;
  left: 10.2%;
  right: 14.4%;
  bottom: 13.1%;
  gap: clamp(6px, 0.7vw, 10px);
  margin: 0;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-row .pr-mini {
  padding: 6px 10px;
  color: color-mix(in srgb, var(--pr-book-cover-ink, #f2ead8) 76%, transparent);
  background: rgba(255, 255, 255, 0.5);
  border-color: color-mix(in srgb, var(--pr-book-gold, #c9b06a) 34%, transparent);
  box-shadow: none;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-row::after {
  content: 'EDITION 01';
  position: absolute;
  right: 0;
  top: calc(100% + clamp(22px, 4.8vh, 48px));
  color: color-mix(in srgb, var(--pr-book-gold, #c9b06a) 66%, transparent);
  font: 700 clamp(8px, 0.8vw, 10px) ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: 0.2em;
  pointer-events: none;
}

/* THE ONE-PAGE CONTENTS SHEET. When the cover opens, the same fullscreen
   board becomes a clean paper page with no visible binding; intro chrome is
   hidden and #prDrawIndex lays out the list with its contextual picture. */
body.presenting.pr-chrome-drawbook #prIntro.pr-drawbook-indexing .pr-intro-card {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.46), transparent 44%),
    radial-gradient(120% 90% at 58% 42%, rgba(255, 255, 255, 0.5), transparent 60%),
    var(--pr-book-cream, #fbfaf5);
  animation: none;
  transform: none;
}
body.presenting.pr-chrome-drawbook #prIntro.pr-drawbook-indexing .pr-intro-card::after { display: none; }
body.presenting.pr-chrome-drawbook #prIntro.pr-drawbook-indexing .pr-intro-card > :not(#prDrawIndex) {
  display: none !important;
}
body.presenting.pr-chrome-drawbook #prDrawIndex:not([hidden]) {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  color: var(--pr-book-ink, #2c3038);
  text-align: left;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-body {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(20px, 4%, 48px);
  align-items: center;
  flex: 1 1 auto;
  min-height: 0;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-running {
  display: block;
  font-size: clamp(11px, 1.1vw, 14px);
  letter-spacing: 0.24em;
  color: var(--pr-book-muted, #6a6f77);
  margin-bottom: 10px;
}
body.presenting.pr-chrome-drawbook #prDrawIndexTitle {
  font-family: var(--pr-book-heading-font, Georgia, serif);
  font-size: clamp(22px, 2.8vw, 38px);
  color: var(--pr-book-ink, #2c3038);
  margin: 0 0 clamp(12px, 2vh, 22px);
  text-wrap: balance;
}
/* The heading is a programmatic focus target (the sheet announces itself);
   a keyboard-visible focus keeps its ring, a scripted focus stays quiet. */
body.presenting.pr-chrome-drawbook #prDrawIndexTitle:focus:not(:focus-visible) { outline: none; }
body.presenting.pr-chrome-drawbook #prDrawIndexTitle:focus-visible {
  outline: 2px solid var(--pr-book-accent, #4f46e5);
  outline-offset: 6px;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--pr-book-body-font, Georgia, serif);
  font-size: clamp(14px, 1.5vw, 20px);
  overflow: hidden;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-list li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: clamp(5px, 0.9vh, 10px) 0;
  border-bottom: 1px dashed color-mix(in srgb, var(--pr-book-rule, #6a6f77) 40%, transparent);
}
body.presenting.pr-chrome-drawbook .pr-draw-index-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-no {
  color: var(--pr-book-accent, #c96f2e);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-art {
  margin: 0;
  align-self: center;
  max-height: 100%;
  display: grid;
  place-items: center;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-art img {
  max-width: 100%;
  max-height: clamp(160px, 52vh, 460px);
  height: auto;
  border: 2px solid color-mix(in srgb, var(--pr-book-ink, #2c3038) 55%, transparent);
  border-radius: 9px 13px 8px 12px / 13px 9px 12px 8px;
  background: #fff;
  padding: 5px;
  box-shadow: 3px 4px 0 rgba(44, 48, 56, 0.12);
  transform: rotate(-0.8deg);
}
body.presenting.pr-chrome-drawbook .pr-draw-index-continue {
  align-self: flex-end;
  margin-top: clamp(8px, 1.6vh, 16px);
  font-family: var(--pr-book-body-font, Georgia, serif);
  font-size: clamp(13px, 1.3vw, 17px);
  color: var(--pr-book-accent, #c96f2e);
  background: transparent;
  border: 1.6px solid var(--pr-book-accent, #c96f2e);
  border-radius: 8px 3px 7px 4px / 4px 7px 3px 8px;
  padding: 7px 16px;
  cursor: pointer;
}
body.presenting.pr-chrome-drawbook .pr-draw-index-continue:hover {
  background: color-mix(in srgb, var(--pr-book-accent, #c96f2e) 12%, transparent);
}
body.presenting.pr-chrome-drawbook #prIntroTitle,
body.presenting.pr-chrome-drawbook #prEnd h2 {
  font-family: var(--pr-book-heading-font, Georgia, serif) !important;
  color: var(--pr-book-cover-ink, #f2ead8) !important;
}
body.presenting.pr-chrome-drawbook #prIntroHeader,
body.presenting.pr-chrome-drawbook #prIntroMeta,
body.presenting.pr-chrome-drawbook #prIntroFooter {
  color: color-mix(in srgb, var(--pr-book-cover-ink, #f2ead8) 78%, transparent);
}
/* CUSTOM JACKET on the drawing book: authored 16:9 pixels ARE the board.
   No binding hardware or app frame is painted over the finished artwork. */
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-book-custom-cover {
  aspect-ratio: 16 / 9;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-book-custom-cover::after { display: none; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-book-custom-cover > :not(.pr-book-custom-cover-art):not(#prIntroPlay):not(#prDrawIndex):not(.pr-book-index) {
  display: none !important;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-book-custom-cover-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  border-radius: 0;
  box-shadow: none;
  z-index: 1;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-book-custom-cover-art[hidden] { display: none; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-book-custom-cover #prIntroPlay {
  position: absolute;
  left: 50%;
  bottom: 4.5%;
  transform: translateX(-50%);
  z-index: 3;
  margin: 0;
  padding: 8px 17px 8px 9px;
  font-size: 13px;
  gap: 8px;
  color: #f7f2e7;
  border: 1px solid rgba(200, 153, 106, 0.62);
  background: rgba(5, 12, 31, 0.76);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.09);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-book-custom-cover #prIntroPlay .pr-intro-play-ico {
  width: 27px;
  height: 27px;
  background: #c8996a;
  color: #07112c;
}
/* PREMIUM FRONT COVER polish: letterpress title, tracked eyebrow with a
   foil rule, and — when the document has an illustration-layout title
   picture — the art blended in as a white-matted plate beside the title
   block (the export composes the same picture through the shared cover
   layout). */
body.presenting.pr-chrome-drawbook #prIntroTitle {
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.72), 0 8px 22px rgba(47, 54, 64, 0.08);
}
/* The brand lockup prints in the cover's own foil, not app chrome colours. */
body.presenting.pr-chrome-drawbook #prIntro .pr-brandin .pr-intro-mark {
  color: var(--pr-book-gold, #c8996a);
  opacity: 1;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-brandin-word {
  color: var(--pr-book-cover-ink, #efe7d8);
}
body.presenting.pr-chrome-drawbook #prIntro .pr-brandin-glow { display: none; }
body.presenting.pr-chrome-drawbook #prIntroHeader { letter-spacing: 0.26em; }
body.presenting.pr-chrome-drawbook #prIntroHeader::after {
  content: '';
  display: block;
  width: 58px;
  height: 2px;
  margin: 9px auto 0;
  background: linear-gradient(90deg, transparent, var(--pr-book-gold, #c8996a), transparent);
}
body.presenting.pr-chrome-drawbook #prIntroArtImg { display: none; }
/* !important on purpose: fitNotebookDomCover writes the safe-rect padding
   INLINE on every fit pass, and the art column must survive it — inline
   loses only to an important declaration. */
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-drawbook-art { padding-right: 40% !important; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card.pr-drawbook-art #prIntroArtImg:not([hidden]) {
  display: block;
  position: absolute;
  right: 6.5%;
  top: 50%;
  transform: translateY(-50%) rotate(1.4deg);
  max-width: 29%;
  max-height: 64%;
  width: auto;
  height: auto;
  object-fit: contain;
  background: #fff;
  padding: clamp(4px, 0.7vw, 9px);
  border-radius: 3px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
  z-index: 2;
}

/* PREMIUM BACK COVER: the Thank-you board writes in the cover's own serif
   and foil — gold heading, quiet ink, outlined foil action pills. */
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card {
  color: var(--pr-book-cover-ink, #efe7d8);
  /* The colophon sits in the CENTRE of the board (operator, Sep 2) — the
     generic end card stacks from the top, which read as a header. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: clamp(34px, 5.2vh, 62px) clamp(54px, 7.5vw, 118px);
  overflow: hidden;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-mark {
  flex: 0 0 auto;
  width: clamp(38px, 3.5vw, 54px);
  height: clamp(38px, 3.5vw, 54px);
  margin: 0 0 clamp(10px, 1.8vh, 18px);
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card h2 {
  font-family: var(--pr-book-heading-font, Georgia, serif) !important;
  color: var(--pr-book-gold, #c8996a) !important;
  font-size: clamp(30px, 4.4vw, 56px);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.72);
  letter-spacing: 0.02em;
  line-height: 1.05;
  margin: 0;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-sub {
  max-width: min(880px, 92%);
  margin-top: clamp(10px, 1.8vh, 18px);
  color: color-mix(in srgb, var(--pr-book-cover-ink, #222a35) 72%, transparent);
  font: 600 clamp(14px, 1.35vw, 20px)/1.35 var(--pr-book-body-font, Georgia, serif);
  text-wrap: balance;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card button {
  background: transparent !important;
  border: 1.5px solid color-mix(in srgb, var(--pr-book-gold, #c8996a) 72%, transparent) !important;
  color: var(--pr-book-cover-ink, #efe7d8) !important;
  border-radius: 999px !important;
  box-shadow: none !important;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card button:hover {
  background: color-mix(in srgb, var(--pr-book-gold, #c8996a) 16%, transparent) !important;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-card a {
  color: var(--pr-book-gold, #c8996a) !important;
  margin: 0;
}
/* Drawing Book is a wide 16:9 back cover, so its three invitations are
   editorial panels rather than the bound-book's narrow stacked controls.
   Explicit flex on both anchors and the button prevents the label/detail
   text from collapsing into strings such as "SubscribeMore". */
body.presenting.pr-chrome-drawbook #prBookCloseActions:not([hidden]) {
  display: flex;
  flex: 0 0 auto;
  width: min(1080px, 96%);
  min-height: 0;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(12px, 1.8vh, 20px);
  margin: clamp(20px, 3.2vh, 34px) 0 clamp(16px, 2.4vh, 26px);
  text-align: center;
}
body.presenting.pr-chrome-drawbook #prBookCloseActions > p {
  margin: 0;
  color: color-mix(in srgb, var(--pr-book-cover-ink, #222a35) 86%, transparent);
  font: 500 clamp(16px, 1.55vw, 22px)/1.35 var(--pr-book-body-font, Georgia, serif);
}
body.presenting.pr-chrome-drawbook .pr-book-close-action-row {
  width: 100%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.5vw, 24px);
}
body.presenting.pr-chrome-drawbook #prEnd .pr-book-close-action-row :is(a, button) {
  display: flex !important;
  min-width: 0;
  min-height: clamp(82px, 10vh, 112px);
  box-sizing: border-box;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 !important;
  padding: clamp(13px, 1.6vh, 18px) clamp(14px, 1.5vw, 22px) !important;
  color: var(--pr-book-cover-ink, #222a35) !important;
  border: 1.5px solid color-mix(in srgb, var(--pr-book-gold, #c8996a) 62%, transparent) !important;
  border-radius: 14px !important;
  background: color-mix(in srgb, var(--pr-book-cover, #faf8f2) 76%, white) !important;
  box-shadow: 0 12px 28px -24px color-mix(in srgb, var(--pr-book-cover-ink, #222a35) 48%, transparent) !important;
  text-align: center;
  text-decoration: none;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-book-close-action-row :is(a, button):is(:hover, :focus-visible) {
  border-color: var(--pr-book-gold, #c8996a) !important;
  background: color-mix(in srgb, var(--pr-book-gold, #c8996a) 10%, var(--pr-book-cover, #faf8f2)) !important;
  transform: translateY(-2px);
}
body.presenting.pr-chrome-drawbook #prEnd .pr-book-close-action-row :is(a, button):focus-visible {
  outline: 2px solid var(--pr-book-gold, #c8996a);
  outline-offset: 3px;
}
body.presenting.pr-chrome-drawbook .pr-book-close-action-row b,
body.presenting.pr-chrome-drawbook .pr-book-close-action-row span {
  display: block;
  min-width: 0;
  max-width: 100%;
}
body.presenting.pr-chrome-drawbook .pr-book-close-action-row b {
  color: var(--pr-book-gold, #c8996a);
  font: 760 clamp(13px, 1.2vw, 17px)/1.15 ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body.presenting.pr-chrome-drawbook .pr-book-close-action-row span {
  color: color-mix(in srgb, var(--pr-book-cover-ink, #222a35) 72%, transparent);
  font: 500 clamp(12px, 1.05vw, 15px)/1.35 var(--pr-book-body-font, Georgia, serif);
  text-wrap: balance;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-ctas {
  flex: 0 0 auto;
  flex-wrap: nowrap;
  gap: clamp(8px, 1vw, 14px);
  margin-top: 0;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-btn {
  min-width: 0;
  padding: 9px clamp(14px, 1.5vw, 22px) !important;
  font-size: clamp(12px, 1vw, 15px);
  white-space: nowrap;
}
body.presenting.pr-chrome-drawbook #prEnd .pr-end-brand {
  flex: 0 0 auto;
  margin-top: clamp(18px, 2.6vh, 28px);
  color: color-mix(in srgb, var(--pr-book-cover-ink, #222a35) 62%, transparent);
  font-size: clamp(11px, .95vw, 14px);
}
/* These controls are self-labelled. The globally generated focus tooltip
   otherwise sits over the invitation row as soon as Replay receives the
   dialog's initial keyboard focus. */
body.presenting.pr-chrome-drawbook #prEnd [data-tip]::after { content: none; }
@media (max-width: 760px), (max-height: 560px) {
  body.presenting.pr-chrome-drawbook #prEnd .pr-end-card {
    justify-content: flex-start;
    padding: 24px 28px;
    overflow-y: auto;
  }
  body.presenting.pr-chrome-drawbook #prEnd .pr-end-mark { display: none; }
  body.presenting.pr-chrome-drawbook #prBookCloseActions:not([hidden]) { margin-block: 14px; }
  body.presenting.pr-chrome-drawbook .pr-book-close-action-row { gap: 8px; }
  body.presenting.pr-chrome-drawbook .pr-book-close-action-row :is(a, button) {
    min-height: 64px;
    padding: 9px 8px !important;
  }
  body.presenting.pr-chrome-drawbook #prEnd .pr-end-ctas { flex-wrap: wrap; }
}
body.presenting.pr-chrome-drawbook #prIntro.pr-book-opening .pr-intro-card {
  animation: prDrawBookCoverOpen calc(var(--pr-book-turn-ms, 500ms) * 1.4) cubic-bezier(.4, .03, .16, 1) both;
}
@keyframes prDrawBookCoverOpen {
  0% { transform: rotateY(0deg); }
  100% { transform: rotateY(-114deg) translateX(-2%); opacity: .96; }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting.pr-chrome-drawbook #prIntro.pr-book-opening .pr-intro-card { animation: none; opacity: 0; }
}

/* NATIVE DRAWING-BOOK OPENING. With no optional cover artwork selected, use
   Diagramium's familiar centred start screen instead of manufacturing a book
   jacket. It keeps the light paper requested for this theme, while the brand
   lockup, title, metadata and controls follow the product's default hierarchy.
   The class is removed for a custom jacket and the selector yields while the
   contents sheet is visible. */
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 0;
  height: auto;
  max-width: min(620px, 92%);
  max-height: 100%;
  aspect-ratio: auto;
  padding: 10px;
  overflow-y: auto;
  color: var(--pr-book-ink, #222a35);
  text-align: center;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transform-origin: center;
  animation: prCardIn .5s var(--ease-out) both;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front::before,
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front::after {
  content: none;
  display: none;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-brandin {
  position: relative;
  inset: auto;
  flex-direction: column;
  gap: 10px;
  margin: 0 0 10px;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-brandin .pr-intro-mark {
  width: 74px;
  height: 74px;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-brandin-word {
  color: var(--pr-book-ink, #222a35);
  font-size: 31px;
  letter-spacing: -0.035em;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-eyebrow,
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-title,
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-meta {
  width: auto;
  max-width: 92%;
  text-align: center;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-eyebrow {
  margin: 0 0 16px;
  color: var(--iris, #6a5cff);
  font: 700 11.5px/1.3 var(--mono) !important;
  letter-spacing: .16em;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front #prIntroTitle {
  margin: 0;
  color: var(--pr-book-ink, #222a35) !important;
  font-family: var(--sans) !important;
  font-size: clamp(28px, 4.6vw, 52px);
  font-weight: 680;
  line-height: 1.08;
  letter-spacing: -.03em;
  text-shadow: none;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front #prIntroTitle::after {
  content: none;
  display: none;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-meta {
  justify-content: center;
  gap: 8px;
  margin-top: 18px;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-meta::after { content: none; }
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-meta span {
  padding: 5px 12px;
  color: var(--pr-book-muted, #5f6875);
  border: 1px solid color-mix(in srgb, var(--pr-book-ink, #222a35) 16%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--pr-book-surface, #ffffff) 42%, transparent);
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front #prIntroPlay {
  margin-top: 34px;
  padding: 14px 34px 14px 24px;
  color: #fff;
  border: 0;
  background: var(--iris, #6a5cff);
  box-shadow: 0 1px 0 rgba(255,255,255,.24) inset,
    0 16px 44px -12px color-mix(in srgb, var(--iris, #6a5cff) 60%, transparent);
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front #prIntroPlay .pr-intro-play-ico {
  width: 34px;
  height: 34px;
  color: #fff;
  background: rgba(255,255,255,.2);
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-row {
  position: relative;
  inset: auto;
  justify-content: center;
  gap: 10px;
  margin-top: 16px;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-row::after { content: none; }
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-row .pr-mini {
  padding: 7px 13px;
  color: #3f4855;
  background: rgba(255,255,255,.46);
  border-color: rgba(34,42,53,.16);
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-foot {
  position: relative;
  inset: auto;
  display: block;
  margin-top: 26px;
  color: #727b87;
  font: 11px/1.4 var(--mono);
  letter-spacing: 0;
  opacity: 1;
}
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-foot::before,
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-diagramium-front .pr-intro-foot::after {
  content: none;
  display: none;
}
body.presenting.pr-chrome-drawbook #prIntro.pr-book-opening:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front {
  transform-origin: center;
  animation: prDiagramiumFrontOut 360ms var(--ease-out) both;
}
@keyframes prDiagramiumFrontOut {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(.985); }
}
@media (prefers-reduced-motion: reduce) {
  body.presenting.pr-chrome-drawbook #prIntro.pr-book-opening:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front {
    animation: none;
    opacity: 0;
  }
}

/* The PLACED step picture — a floating card over a corner of the sheet
   (narration __imgpos<N>; the Step Guide slot stays the default home).
   Geometry rides the published tap lanes so the card sits in the DIAGRAM
   column whatever the notes reserve is, and the bottom pair clears the
   subtitle band. pointer-events none: it never steals a tap from the show. */
#prStepImgCard { display: none; }
body.presenting #prStepImgCard:not([hidden]) {
  display: block;
  position: absolute;
  z-index: 6;
  max-width: min(26%, 300px);
  pointer-events: none;
}
body.presenting #prStepImgCard img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: min(32vh, 300px);
  object-fit: contain;
  border-radius: 12px;
  box-shadow: 0 14px 34px -18px rgba(0, 0, 0, 0.55);
}
body.presenting #prStepImgCard[data-pos="tl"] { left: calc(20px + var(--pr-tap-left, 0px)); top: 58px; }
body.presenting #prStepImgCard[data-pos="tr"] { right: calc(20px + var(--pr-tap-right, 0px)); top: 58px; }
body.presenting #prStepImgCard[data-pos="bl"] { left: calc(20px + var(--pr-tap-left, 0px)); bottom: calc(24px + var(--pr-band, 0px)); }
body.presenting #prStepImgCard[data-pos="br"] { right: calc(20px + var(--pr-tap-right, 0px)); bottom: calc(24px + var(--pr-band, 0px)); }
/* The placement select in the notes media row. */
.pnl-img-pos {
  max-width: 220px;
  min-width: 0;
  font-size: 12px;
  color: var(--text);
  background-color: var(--chrome-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 27px 5px 8px;
  appearance: none;
  -webkit-appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 14px) 52%, calc(100% - 9px) 52%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}
.pnl-img-pos:focus { border-color: var(--accent); outline: none; }
.snp-why-h { margin-top: 8px; }

/* The step-image preview lightbox (thumbnail click in the Notes tab or the
   step popup) — a viewer, not a modal stack. */
#imgPreviewOverlay {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 10, 18, 0.82);
  cursor: zoom-out;
}
#imgPreviewOverlay[hidden] { display: none; }
#imgPreviewOverlay img {
  max-width: min(86vw, 1100px);
  max-height: 86vh;
  border-radius: 12px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
/* Dragging the placed card: the author's hand, not the viewer's. The card
   accepts the pointer only outside locked shows/embeds (the drag wiring
   checks), and while a free position is active the inline left/top wins. */
body.presenting #prStepImgCard:not([hidden]) { pointer-events: auto; cursor: grab; }
body.presenting #prStepImgCard:not([hidden]),
body.presenting #prNarrationImg:not([hidden]) {
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
}
body.presenting.sample-locked #prStepImgCard:not([hidden]),
body.embed-mode #prStepImgCard:not([hidden]) { pointer-events: none; cursor: default; }
body.presenting #prStepImgCard.dragging { cursor: grabbing; }
body.presenting #prStepImgCard.dragging img { box-shadow: 0 20px 44px -14px rgba(0, 0, 0, 0.7); }
@keyframes prPlaceTarget {
  0%, 100% { filter: none; }
  45% { filter: drop-shadow(0 0 13px color-mix(in srgb, var(--accent) 78%, white)); }
}
body.presenting .pr-place-target:not([hidden]) {
  animation: prPlaceTarget .9s ease-in-out 4;
  outline: 3px solid color-mix(in srgb, var(--accent) 74%, white);
  outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
  body.presenting .pr-place-target:not([hidden]) { animation: none; }
}

/* ================================================================
   Hand-story cue choreography

   The diagram, guide, media and Why card now enter on one theme-owned cue
   sheet (fx.story).  Prior cumulative ink never moves; only the newest idea
   is performed.  These are chrome-only effects — document/export geometry
   remains untouched, and reduced-motion resolves immediately. */
body.presenting.pr-story-drawing #svgHost [data-pr-connector-motion] {
  opacity: 0 !important;
}
body.presenting.pr-story #svgHost [data-pr-connector-motion] {
  transition: opacity .36s ease;
}
body.presenting.pr-story-cue-pending #prWhyDock:not([hidden]),
body.presenting.pr-story-cue-pending .pr-story-visual-in:not([hidden]) {
  opacity: 0 !important;
}
.pr-sticky-payload {
  filter: drop-shadow(0 12px 12px rgba(61, 49, 24, .22));
}

@keyframes prStoryWhyLand {
  from { opacity: 0; clip-path: inset(16% 8% 34% 8% round 12px); filter: blur(3px) saturate(.85); }
  58% { opacity: 1; clip-path: inset(0 round 8px); filter: blur(0) saturate(1.04); }
  to { opacity: 1; clip-path: inset(0 round 8px); filter: none; }
}
body.presenting.pr-story #prWhyDock.pr-whyd-in:not([hidden]) {
  animation: prStoryWhyLand .62s cubic-bezier(.22, 1, .36, 1)
    var(--pr-story-why-delay, 1500ms) both !important;
}

@keyframes prStoryVisualLand {
  from { opacity: 0; transform: translateY(18px) rotate(-1.5deg) scale(.94); filter: blur(5px); }
  72% { opacity: 1; transform: translateY(-2px) rotate(.35deg) scale(1.012); filter: blur(0); }
  to { opacity: 1; transform: none; filter: none; }
}
body.presenting.pr-story .pr-story-visual-in:not([hidden]) {
  animation: prStoryVisualLand .72s cubic-bezier(.22, 1, .36, 1)
    var(--pr-story-media-delay, 560ms) both !important;
  transform-origin: 50% 50%;
}
body.presenting.pr-story #prStepImgCard.pr-story-visual-in::before {
  content: '';
  position: absolute;
  z-index: 2;
  left: 50%; top: -7px;
  width: min(38%, 86px); height: 18px;
  transform: translateX(-50%) rotate(-2deg);
  background: rgba(244, 224, 156, .72);
  border: 1px solid rgba(132, 107, 56, .14);
  box-shadow: 0 1px 2px rgba(65, 49, 19, .10);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  body.presenting.pr-story #prWhyDock.pr-whyd-in:not([hidden]),
  body.presenting.pr-story .pr-story-visual-in:not([hidden]) {
    animation: none !important;
    opacity: 1 !important;
    clip-path: none !important;
    filter: none !important;
    transform: none !important;
  }
  .pr-sticky-payload { display: none !important; }
}

/* ================================================================
   VISUAL STORY — scene board, playback order and scene timeline

   Visual Story deliberately reuses the ordinary Diagramium shell. These
   rules style its two-level scene/step model without turning it into a
   second editor or player. Every surface and text colour comes from the
   established UI tokens, so the same controls remain legible in both themes.
   ================================================================ */

/* The editor SVG is a board containing several bounded scene sheets, not one
   giant white page. Let each scene own its shadow and clipping boundary. */
body.visual-story-mode:not(.presenting) #svgHost svg.vs-board-svg {
  overflow: visible;
  border-radius: 0;
  box-shadow: none;
}
body.visual-story-mode:not(.presenting) #zoomLayer {
  padding-bottom: 190px;
}
body.visual-story-mode #canvasWrap { overscroll-behavior: contain; }
body.visual-story-mode:not(.presenting) #side:not(.collapsed) {
  height: calc(100% - var(--shell-top) - 14px);
}

/* ---- Scene navigator (the Scenes group in the component library) ---- */
.visual-story-mode .vs-pal-scene-grid {
  display: block;
  min-width: 0;
}
.visual-story-mode #palGroups .vs-library-import {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px;
  margin: 6px 4px 2px;
  padding-top: 9px;
  border-top: 1px solid var(--border-soft);
}
.visual-story-mode #palGroups .vs-library-import input {
  min-width: 0;
  height: 34px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  font: inherit;
  font-size: 11px;
}
.visual-story-mode #palGroups .vs-library-import button {
  min-height: 34px;
  padding-inline: 9px;
  font-size: 10.5px;
}
.visual-story-mode .vs-scene-nav {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 8px;
}
.visual-story-mode .vs-nav-add {
  width: 100%;
  min-height: 38px;
  padding: 8px 10px;
  border: 1px dashed var(--border);
  border-radius: 9px;
  background: var(--panel);
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.visual-story-mode .vs-nav-add:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.visual-story-mode .vs-nav-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.visual-story-mode .vs-nav-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 26px 26px 26px;
  align-items: center;
  gap: 2px;
  min-width: 0;
  padding: 4px;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--panel);
  color: var(--text);
  transition: background var(--dur-1), border-color var(--dur-1), opacity var(--dur-1);
}
.visual-story-mode .vs-nav-row:hover { border-color: var(--border); }
.visual-story-mode .vs-nav-row.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.visual-story-mode .vs-nav-row.excluded { opacity: .58; }
.visual-story-mode .vs-nav-row.active.excluded { opacity: .76; }
.visual-story-mode .vs-nav-main {
  display: grid;
  grid-template-columns: 27px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 38px;
  padding: 4px;
  border-radius: 7px;
  color: var(--text);
  text-align: left;
}
.visual-story-mode .vs-nav-main:hover { background: var(--panel-2); }
.visual-story-mode .vs-nav-main > span:last-child {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
}
.visual-story-mode .vs-nav-main b,
.visual-story-mode .vs-nav-main small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.visual-story-mode .vs-nav-main b { font-size: 12px; font-weight: 720; }
.visual-story-mode .vs-nav-main small { color: var(--muted); font-size: 10px; }
.visual-story-mode .vs-nav-num {
  display: inline-flex;
  width: 25px;
  height: 25px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
}
.visual-story-mode .vs-nav-row.active .vs-nav-num {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}
.visual-story-mode .vs-nav-row > input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: auto;
  accent-color: var(--accent);
}
.visual-story-mode .vs-nav-move {
  display: inline-flex;
  width: 26px;
  height: 30px;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  color: var(--muted);
  font-size: 13px;
}
.visual-story-mode .vs-nav-move:hover:not(:disabled) {
  background: var(--panel-2);
  color: var(--text);
}
.visual-story-mode .vs-nav-move:disabled { color: var(--faint); opacity: .45; }

/* ---- Step timeline: a compact strip above the ordinary canvas dock ---- */
/* The element is created once and lives in the shared stage. Keep it inert in
   every other editor and throughout Explain; the scoped rule below is the
   only state in which it should participate in layout. */
#vsAutosaveWarning { display: none; }
body.visual-story-mode:not(.presenting):not(.recording) #vsAutosaveWarning:not([hidden]) {
  position: fixed;
  z-index: 120;
  top: 68px;
  left: 50%;
  display: block;
  box-sizing: border-box;
  width: min(620px, calc(100vw - 28px));
  padding: 11px 14px;
  transform: translateX(-50%);
  color: var(--text);
  background: color-mix(in srgb, var(--danger) 8%, var(--chrome));
  border: 1px solid color-mix(in srgb, var(--danger) 52%, var(--border));
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  font-size: 12px;
  font-weight: 650;
  line-height: 1.4;
}
#vsTimeline { display: none; }
body.visual-story-mode:not(.presenting):not(:has(#homePage:not([hidden]))):not(:has(#explorePage:not([hidden]))):not(:has(#searchPage:not([hidden]))):not(:has(#rolesPage:not([hidden]))) #vsTimeline:not([hidden]) {
  position: absolute;
  z-index: 39;
  right: calc(var(--shell-right) + 12px);
  bottom: 70px;
  left: calc(var(--shell-left) + 12px);
  display: grid;
  grid-template-columns: minmax(120px, 170px) minmax(0, 1fr) auto auto auto;
  align-items: stretch;
  gap: 7px;
  min-width: 0;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--chrome);
  box-shadow: var(--shadow-sm);
  color: var(--text);
}
.visual-story-mode .vs-tl-heading {
  display: flex;
  min-width: 0;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 0 7px;
}
.visual-story-mode .vs-tl-heading b,
.visual-story-mode .vs-tl-heading small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.visual-story-mode .vs-tl-heading b { font-size: 12px; font-weight: 750; }
.visual-story-mode .vs-tl-heading small {
  color: var(--muted);
  font-size: 9px;
  font-weight: 750;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.visual-story-mode .vs-tl-list {
  display: flex;
  min-width: 0;
  align-items: stretch;
  gap: 5px;
  margin: 0;
  padding: 0 2px 3px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-color: var(--border) transparent;
  scrollbar-width: thin;
  list-style: none;
}
.visual-story-mode .vs-tl-list > li { flex: 0 0 126px; min-width: 0; }
.visual-story-mode .vs-tl-step {
  display: grid;
  width: 100%;
  height: 100%;
  min-height: 50px;
  grid-template-columns: 23px minmax(0, 1fr);
  grid-template-rows: 1fr 1fr;
  column-gap: 7px;
  align-items: center;
  padding: 6px 8px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--panel);
  color: var(--text);
  text-align: left;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.visual-story-mode .vs-tl-step:hover { border-color: var(--border); background: var(--panel-2); }
.visual-story-mode .vs-tl-step.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.visual-story-mode .vs-tl-step > span {
  display: inline-flex;
  width: 23px;
  height: 23px;
  grid-row: 1 / 3;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
}
.visual-story-mode .vs-tl-step.active > span { background: var(--accent); color: var(--on-accent); }
.visual-story-mode .vs-tl-step b,
.visual-story-mode .vs-tl-step small {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.visual-story-mode .vs-tl-step b { align-self: end; font-size: 11px; }
.visual-story-mode .vs-tl-step small { align-self: start; color: var(--muted); font-size: 9.5px; }
.visual-story-mode :is(.vs-tl-add, .vs-tl-preview) {
  min-width: 66px;
  min-height: 50px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--panel);
  color: var(--text);
  font-size: 11px;
  font-weight: 750;
  white-space: nowrap;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.visual-story-mode .vs-tl-add:hover { border-color: var(--accent); background: var(--accent-soft); }
.visual-story-mode .vs-tl-preview {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}
.visual-story-mode .vs-tl-preview:hover { filter: brightness(1.08); }

/* ---- Visual Story inspector ---- */
.visual-story-mode .vs-inspector {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 10px;
  color: var(--text);
}
.visual-story-mode .vs-inspector .ins-section {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  border: 1px solid var(--border-soft);
  border-radius: 11px;
  background: var(--panel);
}
.visual-story-mode .vs-inspector .ins-section > h3 {
  margin: 0 0 2px;
  color: var(--text);
  font-size: 12px;
  font-weight: 780;
  letter-spacing: .01em;
}
.visual-story-mode .vs-ins-kicker {
  margin-top: -6px;
  color: var(--muted);
  font-size: 10px;
}
.visual-story-mode .vs-inspector .ins-row {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 5px;
  color: var(--text);
}
.visual-story-mode .vs-inspector .ins-row > span {
  color: var(--muted);
  font-size: 9.5px;
  font-weight: 750;
  letter-spacing: .065em;
  text-transform: uppercase;
}
.visual-story-mode .vs-inspector :is(input[type="text"], input[type="number"], select, textarea) {
  width: 100%;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
}
.visual-story-mode .vs-inspector :is(input[type="text"], input[type="number"], select) {
  min-height: 34px;
  padding: 6px 8px;
}
.visual-story-mode .vs-inspector textarea {
  min-height: 62px;
  padding: 7px 8px;
  resize: vertical;
}
.visual-story-mode .vs-inspector .vs-source textarea {
  min-height: 170px;
  font-family: var(--mono);
  font-size: 10.5px;
  tab-size: 2;
}
.visual-story-mode .vs-inspector input[type="color"] {
  width: 100%;
  min-width: 0;
  height: 34px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
}
.visual-story-mode .vs-ins-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.visual-story-mode .vs-ins-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
}
.visual-story-mode .vs-ins-actions > button,
.visual-story-mode .vs-wide { min-width: 0; min-height: 34px; padding-inline: 7px; }
.visual-story-mode .vs-check {
  display: flex;
  min-height: 32px;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}
.visual-story-mode .vs-check input { width: 16px; height: 16px; accent-color: var(--accent); }
.visual-story-mode .vs-action-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.visual-story-mode .vs-action-list li {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 7px;
  padding: 6px 7px 6px 9px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10.5px;
}
.visual-story-mode .vs-action-list li span {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.visual-story-mode .vs-action-list li button {
  display: inline-flex;
  width: 25px;
  height: 25px;
  flex: none;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  color: var(--danger);
  font-size: 16px;
}
.visual-story-mode .vs-action-list li button:hover { background: var(--panel); }
.visual-story-mode .vs-onboard {
  margin: 0;
  padding: 10px 11px;
  border-left: 3px solid var(--accent);
  border-radius: 4px 9px 9px 4px;
  background: var(--accent-soft);
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.55;
}
.visual-story-mode .vs-field-note {
  margin: -2px 0 2px;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.45;
}
.visual-story-mode .vs-readiness {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.visual-story-mode .vs-readiness li {
  border-left: 3px solid var(--border);
  border-radius: 5px 8px 8px 5px;
  background: var(--panel-2);
}
.visual-story-mode .vs-readiness li.warning { border-left-color: var(--danger); }
.visual-story-mode .vs-readiness li.info { border-left-color: var(--accent); }
.visual-story-mode .vs-readiness :is(button, span) {
  display: block;
  width: 100%;
  padding: 7px 8px;
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.45;
  text-align: left;
}
.visual-story-mode .vs-readiness button:hover {
  background: var(--accent-soft);
  color: var(--text);
}
.visual-story-mode .vs-ready-ok {
  margin: 0;
  padding: 9px 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 9%, var(--panel));
  color: var(--text);
  font-size: 11px;
  font-weight: 680;
}
.visual-story-mode .vs-ready-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
}
.visual-story-mode .vs-ready-actions > button { min-height: 34px; padding-inline: 7px; }
.visual-story-mode .vs-media-summary {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px 10px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--accent);
  border-radius: 7px 9px 9px 7px;
  background: var(--panel-2);
  color: var(--text);
}
.visual-story-mode .vs-media-summary.warning { border-left-color: var(--danger); }
.visual-story-mode .vs-media-summary strong { font-size: 11px; }
.visual-story-mode .vs-media-summary small {
  overflow: hidden;
  color: var(--muted);
  font-size: 9.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.visual-story-mode .vs-media-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.visual-story-mode .vs-media-chips span {
  padding: 3px 6px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  background: var(--panel);
  color: var(--muted);
  font-size: 9px;
  font-weight: 650;
}

/* ---- Bounded scene frames, editable objects and animation badges ---- */
.visual-story-mode #svgHost .vs-scene {
  outline: none;
  transition: opacity var(--dur-2), filter var(--dur-2);
}
.visual-story-mode #svgHost .vs-scene-boundary {
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 8px 10px color-mix(in srgb, var(--text) 17%, transparent));
}
.visual-story-mode #svgHost .vs-scene.selected .vs-scene-boundary {
  filter: drop-shadow(0 10px 14px color-mix(in srgb, var(--accent) 26%, transparent));
}
.visual-story-mode #svgHost .vs-scene.excluded { opacity: .58; }
.visual-story-mode #svgHost .vs-scene.excluded .vs-scene-boundary { stroke-dasharray: 10 7; }
.visual-story-mode #svgHost .vs-scene-header { cursor: grab; outline: none; }
.visual-story-mode #svgHost .vs-scene-header:active { cursor: grabbing; }
.visual-story-mode #svgHost .vs-safe-guides { opacity: .88; }
.visual-story-mode #svgHost .vs-scene-header:focus-visible > rect,
.visual-story-mode #svgHost .vs-scene:focus-visible > .vs-scene-boundary {
  stroke: var(--accent);
  stroke-width: 5;
}
.visual-story-mode #svgHost .vs-object {
  cursor: grab;
  outline: none;
  transform-box: fill-box;
  transform-origin: center;
  transition: filter var(--dur-1), opacity var(--dur-1);
}
.visual-story-mode #svgHost .vs-object:active { cursor: grabbing; }
.visual-story-mode #svgHost .vs-object:hover,
.visual-story-mode #svgHost .vs-object:focus-visible {
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--accent) 42%, transparent));
}
.visual-story-mode #svgHost .vs-object.selected {
  filter: drop-shadow(0 0 9px color-mix(in srgb, var(--accent) 52%, transparent));
}
.visual-story-mode #svgHost .vs-resize-handle {
  cursor: nwse-resize;
  touch-action: none;
}
.visual-story-mode #svgHost .vs-resize-ne,
.visual-story-mode #svgHost .vs-resize-sw { cursor: nesw-resize; }
.visual-story-mode #svgHost :is(.vs-resize-n, .vs-resize-s) { cursor: ns-resize; }
.visual-story-mode #svgHost :is(.vs-resize-e, .vs-resize-w) { cursor: ew-resize; }
.visual-story-mode #svgHost .vs-nested-diagram {
  image-rendering: auto;
  text-rendering: geometricPrecision;
}
body.visual-story-mode.presenting #svgHost .vs-nested-prior {
  opacity: 1;
}
body.visual-story-mode.presenting #svgHost .vs-nested-arrival {
  animation: vsNestedArrival .38s var(--ease-out) both;
}
@keyframes vsNestedArrival {
  from { opacity: 0; }
  to { opacity: 1; }
}
.visual-story-mode #svgHost .vs-object.outside {
  opacity: .62;
  filter: saturate(.55);
}
.visual-story-mode #svgHost .vs-object.vs-highlight,
.visual-story-mode #svgHost .vs-object.vs-focus {
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--accent) 64%, transparent));
}
/* Animation badges are the direct circle/text pair appended to an object.
   The direct-child selector leaves icon artwork and embedded diagrams alone. */
.visual-story-mode #svgHost .vs-object > circle:last-of-type,
.visual-story-mode #svgHost .vs-object > circle:last-of-type + text:last-child {
  filter: drop-shadow(0 2px 3px color-mix(in srgb, var(--text) 24%, transparent));
  paint-order: stroke;
}

/* ---- Explain transport: scene jumps appear only for Visual Story ---- */
.vs-pr-scene { display: none; }
body.visual-story-mode.presenting .vs-pr-scene {
  display: inline-flex;
  min-width: 70px;
  min-height: 36px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 9px;
  white-space: nowrap;
}
body.visual-story-mode.presenting .vs-pr-scene:disabled {
  color: var(--faint);
  opacity: .42;
  cursor: not-allowed;
}

/* A Visual Story already owns a full 16:9 slide. Keep the stage iris static,
   remove the generic travelling object outline, and let only story content
   animate. The authored scene edge/background remains a steady video frame. */
body.visual-story-mode.presenting #prFrame { animation: none; opacity: 1; }
body.visual-story-mode.presenting #svgHost .pr-focus-ring { display: none !important; }
body.visual-story-mode.presenting #svgHost .vs-scene-boundary {
  stroke: none !important;
  filter: none !important;
}

/* ---- Scene-to-scene transitions ---- */
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition] {
  transform-box: border-box;
  transform-origin: center;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition="fade"] {
  animation: vsSceneFade var(--vs-transition-ms, 500ms) var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition="slide-left"] {
  animation: vsSceneFromRight var(--vs-transition-ms, 500ms) var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition="slide-right"] {
  animation: vsSceneFromLeft var(--vs-transition-ms, 500ms) var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition="zoom"] {
  animation: vsSceneZoom var(--vs-transition-ms, 500ms) var(--ease-out) both;
}
@keyframes vsSceneFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes vsSceneFromRight { from { opacity: .25; translate: 5vw 0; } to { opacity: 1; translate: 0 0; } }
@keyframes vsSceneFromLeft { from { opacity: .25; translate: -5vw 0; } to { opacity: 1; translate: 0 0; } }
@keyframes vsSceneZoom { from { opacity: .2; scale: .94; } to { opacity: 1; scale: 1; } }

/* A native diagram is itself a cumulative player. Scene entry must therefore
   stay visibly anchored instead of hiding the entire nested player at the
   transition's first frame. The movement remains, with a high opacity floor. */
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-has-diagram="1"][data-vs-transition="fade"] {
  animation-name: vsDiagramSceneFade;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-has-diagram="1"][data-vs-transition="slide-left"] {
  animation-name: vsDiagramSceneFromRight;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-has-diagram="1"][data-vs-transition="slide-right"] {
  animation-name: vsDiagramSceneFromLeft;
}
body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-has-diagram="1"][data-vs-transition="zoom"] {
  animation-name: vsDiagramSceneZoom;
}
@keyframes vsDiagramSceneFade { from { opacity: .62; } to { opacity: 1; } }
@keyframes vsDiagramSceneFromRight { from { opacity: .62; translate: 2.4vw 0; } to { opacity: 1; translate: 0 0; } }
@keyframes vsDiagramSceneFromLeft { from { opacity: .62; translate: -2.4vw 0; } to { opacity: 1; translate: 0 0; } }
@keyframes vsDiagramSceneZoom { from { opacity: .62; scale: .975; } to { opacity: 1; scale: 1; } }

/* Current-step object actions. The model supplies the final SVG state; these
   cues only perform the newest change and settle back onto that authored
   state, so cumulative objects do not keep moving on later steps. */
body.visual-story-mode.presenting #svgHost .vs-action-appear {
  animation: vsActionAppear .42s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-disappear {
  animation: vsActionDisappear .42s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-draw-connector > path {
  animation: vsActionDraw .58s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-reveal-text:not(.vs-object-bullets) > text,
body.visual-story-mode.presenting #svgHost text.vs-action-reveal-text,
body.visual-story-mode.presenting #svgHost .vs-action-reveal-text .vs-bullet-new {
  animation: vsActionReveal .44s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-highlight {
  animation: vsActionHighlight .72s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-dim {
  animation: vsActionDim .42s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-move {
  animation: vsActionMove .5s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-zoom {
  animation: vsActionZoom .5s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-focus {
  animation: vsActionFocus .7s var(--ease-out) both;
}
body.visual-story-mode.presenting #svgHost .vs-action-pulse {
  animation: vsActionPulse .66s var(--ease-out) both;
}
@keyframes vsActionAppear {
  from { opacity: 0; translate: 0 10px; scale: .98; filter: blur(2px); }
  to { translate: 0 0; scale: 1; filter: none; }
}
@keyframes vsDiagramAppear {
  from { opacity: .45; translate: 0 4px; scale: .995; }
  to { opacity: 1; translate: 0 0; scale: 1; }
}
@keyframes vsActionDisappear {
  from { opacity: var(--vs-opacity-from, 1); scale: 1; filter: none; }
  to { opacity: 0; scale: .98; filter: blur(2px); }
}
@keyframes vsActionDraw {
  from { clip-path: inset(0 100% 0 0); opacity: .35; }
  to { clip-path: inset(0); opacity: 1; }
}
@keyframes vsActionReveal {
  from { opacity: 0; translate: 0 5px; }
  to { opacity: 1; translate: 0 0; }
}
@keyframes vsActionHighlight {
  0% { filter: none; }
  45% { filter: brightness(1.1) drop-shadow(0 0 12px color-mix(in srgb, var(--accent) 72%, transparent)); }
  100% { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--accent) 50%, transparent)); }
}
@keyframes vsActionDim {
  from { opacity: var(--vs-opacity-from, 1); filter: saturate(1); }
  to { opacity: var(--vs-opacity-to, .3); filter: saturate(.5); }
}
@keyframes vsActionMove {
  from { translate: var(--vs-move-x, 0) var(--vs-move-y, 0); }
  to { translate: 0 0; }
}
@keyframes vsActionZoom {
  from { scale: var(--vs-scale-from, .94); opacity: .55; }
  to { scale: 1; }
}
@keyframes vsActionFocus {
  0% { scale: var(--vs-scale-from, 1); filter: none; }
  52% { filter: brightness(1.08) drop-shadow(0 0 14px color-mix(in srgb, var(--accent) 76%, transparent)); }
  100% { scale: 1; filter: drop-shadow(0 0 9px color-mix(in srgb, var(--accent) 54%, transparent)); }
}
@keyframes vsActionPulse {
  0%, 100% { scale: 1; }
  48% { scale: 1.035; filter: brightness(1.08); }
}

/* ---- Responsive scene controls ---- */
@media (max-width: 760px) {
  body.visual-story-mode:not(.presenting) #zoomLayer { padding-bottom: 184px; }
  body.visual-story-mode:not(.presenting) #side:not(.collapsed) { height: auto; }
  body.visual-story-mode:not(.presenting) #vsTimeline:not([hidden]) {
    right: 8px;
    bottom: calc(64px + env(safe-area-inset-bottom));
    left: 8px;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    padding: 7px;
    border-radius: 13px;
  }
  .visual-story-mode .vs-tl-heading { display: none; }
  .visual-story-mode .vs-tl-list > li { flex-basis: 118px; }
  .visual-story-mode :is(.vs-tl-step, .vs-tl-add, .vs-tl-preview) { min-height: 44px; }
  .visual-story-mode :is(.vs-tl-add, .vs-tl-preview) { min-width: 52px; padding-inline: 8px; }
  .visual-story-mode .vs-nav-add,
  .visual-story-mode .vs-nav-main,
  .visual-story-mode .vs-nav-move { min-height: 44px; }
  .visual-story-mode .vs-nav-move { width: 36px; }
  .visual-story-mode .vs-nav-row { grid-template-columns: minmax(0, 1fr) 32px 36px 36px; }
  .visual-story-mode .vs-inspector :is(input[type="text"], input[type="number"], select),
  .visual-story-mode .vs-inspector input[type="color"],
  .visual-story-mode .vs-ins-actions > button,
  .visual-story-mode .vs-wide { min-height: 44px; }
  body.visual-story-mode.presenting .vs-pr-scene {
    width: 44px;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    font-size: 0;
  }
  body.visual-story-mode.presenting #vsPrPrevScene::before { content: "⇤"; font-size: 18px; }
  body.visual-story-mode.presenting #vsPrNextScene::before { content: "⇥"; font-size: 18px; }
}

@media (max-width: 430px) {
  .visual-story-mode .vs-ins-grid,
  .visual-story-mode .vs-ins-actions { grid-template-columns: 1fr; }
  .visual-story-mode .vs-tl-list > li { flex-basis: 108px; }
  .visual-story-mode .vs-tl-step { grid-template-columns: 20px minmax(0, 1fr); padding-inline: 6px; }
  .visual-story-mode .vs-tl-step > span { width: 20px; height: 22px; }
  .visual-story-mode .vs-tl-add { min-width: 44px; font-size: 0; }
  .visual-story-mode .vs-tl-add::before { content: "+"; font-size: 18px; }
  .visual-story-mode .vs-tl-preview { min-width: 44px; font-size: 0; }
  .visual-story-mode .vs-tl-preview::before { content: "▶"; font-size: 14px; }
}

/* Keyboard focus is intentionally stronger than hover across both the list
   controls and the inspector; SVG focus uses stroke/filter rules above. */
.visual-story-mode :is(
  .vs-nav-add, .vs-nav-main, .vs-nav-move,
  .vs-tl-step, .vs-tl-add, .vs-tl-preview,
  .vs-action-list button, .vs-inspector button,
  .vs-inspector input, .vs-inspector select, .vs-inspector textarea
):focus-visible,
body.visual-story-mode.presenting .vs-pr-scene:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .visual-story-mode :is(
    .vs-nav-add, .vs-nav-row, .vs-nav-main, .vs-tl-step,
    .vs-tl-add, .vs-tl-preview, .vs-scene, .vs-object
  ) { transition: none !important; }
  body.visual-story-mode.presenting #svgHost .vs-scene-content[data-vs-transition],
  body.visual-story-mode.presenting #svgHost .vs-nested-arrival,
  body.visual-story-mode.presenting #svgHost :is(
    .vs-action-appear, .vs-action-highlight, .vs-action-dim,
    .vs-action-move, .vs-action-zoom, .vs-action-focus, .vs-action-pulse
  ),
  body.visual-story-mode.presenting #svgHost .vs-action-draw-connector > path,
  body.visual-story-mode.presenting #svgHost .vs-action-reveal-text:not(.vs-object-bullets) > text,
  body.visual-story-mode.presenting #svgHost .vs-action-reveal-text .vs-bullet-new,
  body.visual-story-mode.presenting #svgHost text.vs-action-reveal-text {
    animation: none !important;
    translate: none !important;
    scale: 1 !important;
  }
  body.visual-story-mode.presenting #svgHost .vs-action-draw-connector > path {
    clip-path: none !important;
  }
  body.visual-story-mode.presenting #svgHost .vs-action-disappear {
    animation: none !important;
    opacity: 0 !important;
  }
}

/* ==================================================================
   Landing v4 — "THE DRAFTING DESK" (Aug 2026).
   The home page leaves the app's dark chrome entirely: an engineering
   graph-paper desk, ink typography, ONE marigold marker (the favicon
   amber), kraft tape, sticky notes, and hard-offset "drawn" shadows.
   Direction validated against the design DB's Anti-Polish / Raw
   aesthetic + "warm ink + amber on paper" palette for writing tools.
   Scoped by token PINS on #homePage: descendant declarations beat the
   inherited theme in BOTH UI themes, so every existing component
   re-skins itself to paper without new rules.
   ================================================================== */
#homePage, #explorePage, #searchPage, #rolesPage {
  /* -- primitives: ink on paper (v4.6 palette, Sep 2026). Every grey here
     is a READING colour: --slate is body copy (7:1 on the paper), --slate-2
     captions and labels (6:1), --faint the quietest metadata allowed
     (5:1). Nothing below AA-for-small-text exists on the desk. -- */
  --ink: #171821; --ink-2: #34353E;
  --paper: #FAF7EF;
  --panel: #ffffff; --panel-2: #F3EFE4;
  --slate: #55545A; --slate-2: #5F5E66;
  --edge: #D9D3C6; --dot: #d7ddf0; --faint: #6B6A72;
  --shadow: 0 1px 2px rgba(23,24,33,.05), 0 14px 32px -20px rgba(23,24,33,.22);
  --shadow-sm: 0 1px 2px rgba(23,24,33,.05), 0 6px 16px -10px rgba(23,24,33,.16);
  --shadow-lg: 0 2px 4px rgba(23,24,33,.06), 0 26px 52px -24px rgba(23,24,33,.26);
  --wordmark: #171821; --muted: #55545A; --border-soft: #E4DFD3;
  --danger: #c9364d; --canvas-bg: #ffffff;
  /* -- the one marker: marigold. --iris is the CTA orange, --iris-deep its
     hover, --iris-soft the pale highlighter, --iris-ink the only orange
     allowed AS TEXT (5.2:1 on the paper — the marker itself is 1.9:1 and
     never colours a word). --navy is the dark preview ground. -- */
  --iris: #F4A51C; --iris-bright: #F4A51C; --iris-deep: #DB8910;
  --iris-ink: #8F5E08; --iris-soft: #FBE6A6; --on-signal: #171821;
  --navy: #11152A;
  /* -- aliases re-derived so they read the pins above -- */
  --chrome: var(--paper); --chrome-2: var(--panel); --chrome-3: var(--panel-2);
  --border: var(--edge); --text: var(--ink);
  --accent: var(--iris); --accent-ink: var(--iris-ink); --on-accent: var(--on-signal);
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
  --accent-ring: color-mix(in srgb, var(--accent) 30%, transparent);
  --glass-bg: rgba(250, 247, 239, .96);
  /* Inherited COLOR computes on body — outside this pin scope — so it must
     be re-anchored here or heading/default text keeps the dark theme's ink. */
  color: var(--text);
  /* -- the desk: warm paper under a fine blue drafting grid. The grid does
     NOT scroll (background of the scroll container) — sheets slide over it. */
  background:
    linear-gradient(90deg, rgba(76, 98, 160, .1) 1px, transparent 1px) 0 0 / 120px 120px,
    linear-gradient(180deg, rgba(76, 98, 160, .1) 1px, transparent 1px) 0 0 / 120px 120px,
    linear-gradient(90deg, rgba(76, 98, 160, .055) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(180deg, rgba(76, 98, 160, .055) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--paper);
}

/* ---- Reveal language: papers being laid on the desk (settle, not slide). */
#homePage .lp3 .sr { transform: translateY(16px) rotate(.5deg); }
#homePage .lp3 .sr.sr-in { transform: none; }

/* ---- Type voice: heavy ink display; the promise in a serif hand. ---- */
#homePage .lp3 .lp-section h2, #homePage .lp3 .lp-finale-title { font-weight: 720; letter-spacing: -0.03em; }
.lp3-serif, #homePage .lp3 .lp-warm {
  font-family: 'Iowan Old Style', Palatino, 'Palatino Linotype', 'Book Antiqua', Georgia, serif;
  font-style: italic; font-weight: 560; letter-spacing: -0.012em;
}
#homePage .lp3 .lp-warm {
  background: none; -webkit-background-clip: initial; background-clip: initial;
  -webkit-text-fill-color: currentColor; color: var(--ink);
  position: relative; display: inline-block; padding: 0 .06em;
  animation: none;
}
/* The highlighter: a thick marigold swipe UNDER the words, drawn on load. */
#homePage .lp3 .lp-warm-line {
  position: absolute; left: 0; right: 0; bottom: .02em; width: 100%; height: .46em;
  overflow: visible; pointer-events: none; z-index: -1;
}
#homePage .lp3 .lp-warm-line path {
  stroke: var(--iris-soft); stroke-width: 10; fill: none; stroke-linecap: round; opacity: 1;
  stroke-dasharray: 100; stroke-dashoffset: 100;
  animation: lp4-marker 0.9s cubic-bezier(.6,.05,.3,1) .65s forwards;
}
@keyframes lp4-marker { to { stroke-dashoffset: 0; } }
#homePage .lp3 .lp-eyebrow { color: var(--slate); font-family: var(--font); font-weight: 650; letter-spacing: .1em; }
#homePage .lp3 .lp-eyebrow-dot { background: var(--iris-bright); border: 1.5px solid var(--ink); }
.lp-kicker::before {
  content: ""; display: inline-block; width: 22px; height: 3px;
  background: var(--iris-bright); vertical-align: middle; margin-right: 10px; border-radius: 2px;
}

/* ---- Buttons: marker + ink, the hard-offset "drawn" shadow. ---- */
#homePage .lp3 .lp-btn-primary {
  background: var(--iris-bright); color: var(--on-signal);
  border: 2px solid var(--ink); border-radius: 11px;
  box-shadow: 3px 3px 0 var(--ink);
  transition: transform .16s var(--ease-out), box-shadow .16s var(--ease-out), background .16s;
}
#homePage .lp3 .lp-btn-primary:hover {
  background: var(--iris-deep); filter: none;
  transform: translate(-2px, -2px); box-shadow: 5px 5px 0 var(--ink);
}
#homePage .lp3 .lp-btn-primary:active { transform: translate(1px, 1px); box-shadow: 2px 2px 0 var(--ink); }
#homePage .lp3 .lp-btn-ghost {
  background: var(--panel); color: var(--ink); border: 1.5px solid var(--ink);
}
#homePage .lp3 .lp-btn-ghost:hover {
  background: var(--panel); border-color: var(--ink);
  transform: translate(-2px, -2px); box-shadow: 3px 3px 0 var(--ink);
}

/* ---- Hero stage: a white sheet taped to the desk. ---- */
#homePage .lp3 .lp-hero::before { content: none; }
#homePage .lp3 .lp-stage {
  background: #fff; border: 1px solid var(--edge); border-radius: 8px;
  transform: rotate(-.5deg);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 2px 4px rgba(26,28,38,.06), 0 26px 50px -22px rgba(26,28,38,.32);
  overflow: visible;
  transition: transform .4s var(--ease-out);
}
#homePage .lp3 .lp-stage:hover { transform: rotate(0deg); }
#homePage .lp3 .lp-stage::before {  /* kraft tape */
  content: ""; position: absolute; top: -13px; left: 50%; width: 110px; height: 26px;
  transform: translateX(-50%) rotate(-2.2deg);
  background: rgba(216, 194, 152, .8);
  border-left: 1px dashed rgba(26,28,38,.18); border-right: 1px dashed rgba(26,28,38,.18);
  box-shadow: 0 1px 2px rgba(26,28,38,.1); z-index: 2;
}
#homePage .lp3 .lp-stage > * { border-radius: 0; }
#homePage .lp3 .lp-stage-bar { border-bottom: 1.5px solid rgba(76,98,160,.22); }
#homePage .lp3 .lp-stage-dot { background: var(--iris-bright); border: 1.5px solid var(--ink); opacity: 1; }
#homePage .lp3 .lp-stage-file { color: var(--slate-2); }
#homePage .lp3 .lp-stage-present {
  background: var(--iris-bright); color: var(--on-signal);
  border: 1.5px solid var(--ink); border-radius: 999px;
  font-family: var(--font); font-size: 12.5px; letter-spacing: .01em; font-weight: 700;
  box-shadow: 2px 2px 0 var(--ink);
  transition: transform .16s var(--ease-out), box-shadow .16s var(--ease-out);
}
#homePage .lp3 .lp-stage-present:hover { filter: none; background: var(--iris-deep); transform: translate(-1px,-1px) scale(1); box-shadow: 3px 3px 0 var(--ink); }
#homePage .lp3 .lp-stage-present .bp-glyph { color: var(--on-signal); }
/* Script pane: ruled paper you write on. */
#homePage .lp3 .lp-stage-script {
  border-right: 1.5px solid rgba(76,98,160,.22); border-bottom: none;
  background: repeating-linear-gradient(180deg, transparent 0 27px, rgba(76,98,160,.12) 27px 28px);
}
@media (max-width: 639.98px) { #homePage .lp3 .lp-stage-script { border-right: none; border-bottom: 1.5px solid rgba(76,98,160,.22); } }
#homePage .lp3 .lp-stage-script textarea { color: var(--ink-2); caret-color: var(--iris-deep); }
#homePage .lp3 .lp-stage-script textarea:focus { color: var(--ink); }
#homePage .lp3 .lp-stage-ghost { color: var(--faint); }
/* Drawing pane: the fine blue grid. */
#homePage .lp3 .lp-stage-canvas {
  background:
    linear-gradient(90deg, rgba(76,98,160,.07) 1px, transparent 1px) 0 0 / 22px 22px,
    linear-gradient(180deg, rgba(76,98,160,.07) 1px, transparent 1px) 0 0 / 22px 22px,
    #fff;
}
#homePage .lp3 .hero-actor-name { fill: #1d2130; }
#homePage .lp3 .hero-msg-text { fill: #2c3147; }
#homePage .lp3 .hero-lifeline { stroke: #767e98; opacity: .6; }
#homePage .lp3 .hero-note rect { fill: #ffe9a2; stroke: #d9ab29; }
#homePage .lp3 .hero-note-text { fill: #57430a; }
#homePage .lp3 .hero-empty-hint { fill: #82869b; }
#homePage .lp3 .lp-stage-progress { background: repeating-linear-gradient(90deg, transparent 0 calc(12.5% - 3px), #fff calc(12.5% - 3px) 12.5%), #ece8da; }
#homePage .lp3 .lp-stage-progress span { background: var(--iris-bright); }
#homePage .lp3 .lp-stage-caption { border-top: 1px dashed rgba(76,98,160,.28); color: var(--slate-2); }

/* ---- Proof: a pencil ledger line. ---- */
#homePage .lp3 .lp-proof {
  border: 0; border-top: 1.5px solid var(--ink); border-bottom: 1.5px solid var(--ink);
  border-radius: 0; background: none;
  display: flex; flex-wrap: wrap; gap: 8px 40px; justify-content: center;
  padding: 15px 0;
}
#homePage .lp3 .lp-proof-cell { flex-direction: row; align-items: baseline; gap: 8px; padding: 4px 0; border: 0; }
#homePage .lp3 .lp-proof-num { font-family: var(--font); font-size: 15.5px; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
#homePage .lp3 .lp-proof-formats { font-family: var(--mono); font-size: 13px; padding-top: 0; }
#homePage .lp3 .lp-proof-label { font-family: var(--font); text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--slate); font-weight: 500; }

/* ---- Tech band: the EDITABLE DIAGRAM card (v4.6). One card, not three
   hand skins: a cream notebook leaf — faint ruling on the body — with a
   SMALLER dark preview inset at the top, so it sits beside the lesson card
   (white, full-bleed dark poster) as the same family at two weights.
   explore.js still stamps .lp-look-* on each tile; those classes now do
   nothing on purpose (the skins were deleted, not hidden). ---- */
#homePage .lp3 .lp-tech-grid { grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: 1.1rem 1rem; }
#homePage .lp3 .lp-sample {
  background: #FDFAF3; border: 1px solid var(--edge); border-radius: 10px;
  padding: 10px 10px 0;
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s;
}
#homePage .lp3 .lp-sample:hover, #homePage .lp3 .lp-sample:focus-visible {
  border-color: var(--ink); transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
#homePage .lp3 .lp-sample-art {
  aspect-ratio: 16 / 9; border-radius: 6px; overflow: hidden;
  background: var(--navy);
}
#homePage .lp3 .lp-sample-art img { padding: 14px; }
/* the notebook: the body is ruled, the rule spacing matches the line-height */
#homePage .lp3 .lp-sample-body {
  margin: 0 -10px; padding: 12px 14px 14px; border-top: 0;
  background: repeating-linear-gradient(180deg, transparent 0 21px, rgba(76,98,160,.11) 21px 22px);
  background-origin: content-box;
}
#homePage .lp3 .lp-sample-name { color: var(--ink); font-size: 15px; font-weight: 650; line-height: 1.35; }
#homePage .lp3 .lp-sample-blurb { color: var(--slate); font-size: 13.5px; line-height: 1.5; }
/* the Edit chip: a small drawn button riding the artwork */
#homePage .lp3 .lp-sample-edit {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  display: inline-flex; align-items: center; gap: 6px;
  font: 700 12px var(--font); letter-spacing: .01em;
  color: var(--ink); cursor: pointer;
  background: #fff; border: 1.5px solid var(--ink); border-radius: 999px; padding: 5px 12px;
  box-shadow: 2px 2px 0 var(--ink);
  transition: transform .15s var(--ease-out), box-shadow .15s var(--ease-out), background .15s;
}
#homePage .lp3 .lp-sample-edit svg { width: 13px; height: 13px; }
#homePage .lp3 .lp-sample-edit:hover, #homePage .lp3 .lp-sample-edit:focus-visible {
  background: var(--iris-bright); transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink);
}
/* the state badges read as pencil notes on paper */
#homePage .lp3 .lp-sample-free, #homePage .lp3 .lp-sample-soon, #homePage .lp3 .lp-sample-lock {
  background: #fff; color: var(--slate); border: 1px solid var(--edge);
  font-family: var(--font); font-weight: 600; letter-spacing: .01em;
}

/* ---- Video band: polaroids from the channel, one small strip.
   Structure (js/home-videos.js): .lp-video-card = the polaroid; inside it a
   .lp-video <button> (image + play; becomes the iframe holder on click) and
   a .lp-video-cap row with the title and the watch-on-YouTube link. ---- */
#homePage .lp3 .lp-video-grid {
  display: flex; gap: 18px; overflow-x: auto; padding: 10px 4px 18px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin; scrollbar-color: #cfccbc transparent;
}
#homePage .lp3 .lp-video-card {
  flex: 0 0 234px; scroll-snap-align: start;
  padding: 8px; background: #fff; border: 1px solid var(--edge); border-radius: 10px;
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s;
}
#homePage .lp3 .lp-video-card:hover, #homePage .lp3 .lp-video-card:focus-within {
  border-color: var(--ink); transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
#homePage .lp3 .lp-video {
  display: block; position: relative; width: 100%;
  padding: 0; margin: 0; border: 0; background: none; cursor: pointer;
  border-radius: 6px; overflow: hidden; background: var(--navy);
}
#homePage .lp3 .lp-video img {
  position: static; display: block; width: 100%; height: auto; aspect-ratio: 16 / 9;
  object-fit: cover; border-radius: 6px; opacity: 1; transform: none;
}
#homePage .lp3 .lp-video-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(26,28,38,.75); color: #fff; border: none;
  display: grid; place-items: center; pointer-events: none;
  transition: transform .2s var(--ease-out), background .2s;
}
#homePage .lp3 .lp-video-play svg { width: 15px; height: 15px; margin-left: 2px; }
#homePage .lp3 .lp-video:hover .lp-video-play, #homePage .lp3 .lp-video:focus-visible .lp-video-play { transform: translate(-50%,-50%) scale(1.1); background: var(--ink); }
#homePage .lp3 .lp-video-cap { display: flex; align-items: flex-start; gap: 7px; padding: 8px 2px 0; }
#homePage .lp3 .lp-video-title {
  position: static; display: -webkit-box; flex: 1 1 auto; padding: 0;
  font: 600 12.5px var(--font); line-height: 1.4; letter-spacing: 0;
  color: var(--ink-2); background: none; text-align: left;
  overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
#homePage .lp3 .lp-video-ext { flex: none; color: var(--slate-2); padding: 1px; border-radius: 4px; }
#homePage .lp3 .lp-video-ext svg { width: 14px; height: 14px; display: block; }
#homePage .lp3 .lp-video-ext:hover { color: var(--ink); }
#homePage .lp3 .lp-video-playing { aspect-ratio: 16 / 9; cursor: default; }
#homePage .lp3 .lp-video-playing iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 6px; }
#homePage .lp3 .lp-video-blocked {
  display: grid; place-items: center; aspect-ratio: 16 / 9; padding: 12px;
  font: 600 12px var(--font); color: var(--ink); text-align: center;
  text-decoration: underline; text-underline-offset: 3px;
  background: var(--panel-2); border-radius: 6px;
}
#homePage .lp3 .lp-video-note { font-size: 13px; line-height: 1.5; color: var(--slate-2); margin-top: 8px; }
#homePage .lp3 .lp-sub-link { color: var(--iris-ink); text-decoration: underline; text-underline-offset: 3px; }
#homePage .lp3 .lp-sub-link:hover { color: var(--ink); }

/* ---- The 26 types: index-card tabs. ---- */
#homePage .lp3 .home-cards { display: flex; flex-wrap: wrap; gap: 11px; }
#homePage .lp3 .home-card {
  display: inline-flex; flex-direction: row; align-items: center; gap: 10px;
  width: auto; padding: 12px 18px 12px 14px; margin: 0;
  border: 1px solid var(--edge); border-radius: 10px;
  background: #fff; box-shadow: none;
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s;
}
#homePage .lp3 .home-card:hover, #homePage .lp3 .home-card:focus-visible {
  border-color: var(--ink); background: #fff;
  transform: translateY(-2px); box-shadow: var(--shadow-sm);
}
#homePage .lp3 .hc-preview { display: none; }
#homePage .lp3 .hc-glyph { display: inline-flex; flex: none; }
#homePage .lp3 .hc-glyph svg { width: 23px; height: 23px; color: var(--slate-2); transition: color .2s; }
#homePage .lp3 .home-card:hover .hc-glyph svg { color: var(--iris-deep); }
#homePage .lp3 .hc-name { font-size: 14.5px; font-weight: 600; color: var(--ink-2); margin: 0; }
#homePage .lp3 .home-card:hover .hc-name { color: var(--ink); }
#homePage .lp3 .hc-continue { font: 600 11.5px var(--font); color: var(--iris-ink); margin: 0; }
#homePage .lp3 .hc-continue:empty { display: none; }

/* ---- Philosophy: pillars + the sheet with the product's own diagram. ---- */
.lp3-phil { display: grid; grid-template-columns: 1fr; gap: clamp(40px, 5vw, 76px); align-items: center; }
@media (min-width: 1000px) { .lp3-phil { grid-template-columns: minmax(0, 46fr) minmax(0, 54fr); } }
#homePage .lp3 .lp-quiet { text-align: left; }
#homePage .lp3 .lp-quiet h2 { margin-left: 0; max-width: 20ch; }
.lp3-pillars { display: grid; gap: 4px; margin-top: 38px; }
.lp3-pillar { padding: 20px 0 20px 16px; border-top: 1.5px solid var(--border-soft); border-left: 3px solid var(--iris-bright); margin-top: 6px; }
.lp3-pk { font-family: var(--font); font-size: 11.5px; letter-spacing: .12em; color: var(--iris-ink); text-transform: uppercase; margin: 0; font-weight: 700; }
.lp3-pillar h3 { font-size: 19px; font-weight: 700; letter-spacing: -.015em; margin: 8px 0 0; color: var(--ink); }
.lp3-pillar p { color: var(--slate); font-size: 15px; line-height: 1.6; margin: 8px 0 0; max-width: 46ch; }
#homePage .lp3 .lp-quiet-note { margin-top: 26px; color: var(--slate-2); }
.lp3-phil-right { position: relative; }
.lp3-sheet {
  position: relative; border-radius: 5px; padding: 12px;
  background: #fff; border: 1px solid var(--edge);
  box-shadow: var(--shadow-lg);
  transform: rotate(.5deg);
}
.lp3-sheet::before {
  content: ""; position: absolute; top: -12px; right: 38px; width: 96px; height: 24px;
  transform: rotate(2.4deg);
  background: rgba(216,194,152,.8);
  border-left: 1px dashed rgba(26,28,38,.16); border-right: 1px dashed rgba(26,28,38,.16);
  box-shadow: 0 1px 2px rgba(26,28,38,.08);
}
.lp3-sheet svg { display: block; width: 100%; height: auto; }
.lp3-phil-cap { font-family: var(--font); font-size: 12.5px; letter-spacing: 0; color: var(--slate-2); margin-top: 14px; text-align: right; }
/* the privacy diagram inks itself on scroll (landing.js adds .on) */
.pv3 { opacity: 0; transition: opacity .45s ease; }
.pv3.on { opacity: 1; }
.pv3 .wire { stroke-dasharray: 100; stroke-dashoffset: 100; }
.pv3.on .wire { stroke-dashoffset: 0; transition: stroke-dashoffset .55s cubic-bezier(.4,0,.3,1); }
.pv3 .head, .pv3 .lbl { opacity: 0; transition: opacity .3s ease .38s; }
.pv3.on .head, .pv3.on .lbl { opacity: 1; }
.pv3 .box { transform: translateY(7px); transition: transform .5s cubic-bezier(.22,1,.36,1); }
.pv3.on .box { transform: none; }

/* ---- The ink spine: a pencil rail down the margin that fills with marker
   as you read; each scene tag's port lights when you pass it (landing.js). */
.lp4-spine {
  position: absolute; top: 0; bottom: 0; left: clamp(4px, 1vw, 18px); width: 2px;
  background: rgba(25,27,38,.1); pointer-events: none;
}
.lp4-spine i { display: block; width: 100%; height: 0; background: var(--iris-bright); }
@media (max-width: 900px) { .lp4-spine { display: none; } }
#homePage .lp3 .lp-scene-tag { color: var(--slate-2); }
#homePage .lp3 .lp-scene-tag::before {
  border: 1.5px solid var(--ink); background: #fff; border-radius: 2px;
  transition: background .3s, border-color .3s;
}
#homePage .lp3 .lp-scene-tag.passed::before { background: var(--iris-bright); }
#homePage .lp3 .lp-scene-tag::after { background: linear-gradient(90deg, rgba(25,27,38,.18), transparent); }

/* ---- FAQ + finale on paper. ---- */
#homePage .lp3 .lp-faq-item summary { color: var(--ink); }
#homePage .lp3 .lp-finale-title { color: var(--ink); }
#homePage .lp3 .lp-finale-title .lp3-serif { padding: 0 .08em; background: linear-gradient(180deg, transparent 52%, var(--iris-soft) 52% 92%, transparent 92%); }

/* ---- Reduced motion: everything lands settled. ---- */
@media (prefers-reduced-motion: reduce) {
  #homePage .lp3 .lp-warm-line path { animation: none; stroke-dashoffset: 0; }
  #homePage .lp3 .lp-stage, #homePage .lp3 .lp-sample, #homePage .lp3 .lp-video,
  #homePage .lp3 .home-card, #homePage .lp3 .lp-btn-primary, #homePage .lp3 .lp-btn-ghost,
  #homePage .lp3 .lp-sample-edit { transition: none; }
  .pv3, .pv3 .wire, .pv3 .head, .pv3 .lbl, .pv3 .box { transition: none; }
}

/* ---- v4.1: the export pipeline — diagram → Explain → files, drawn in the
   desk's hand. The section's .sr-in (scroll-fx.js) inks the arrows and pops
   the stamps in sequence. ---- */
#homePage .lp3 .lp-pipe {
  display: flex; align-items: center; flex-wrap: wrap; gap: 14px 16px;
  margin: 6px 0 10px;
}
#homePage .lp3 .lp-pipe-doc {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 14px 8px; background: #fff;
  border: 1.5px solid var(--ink); border-radius: 8px;
  box-shadow: 3px 3px 0 rgba(25,27,38,.85);
}
#homePage .lp3 .lp-pipe-doc svg { width: 92px; height: 64px; display: block; }
#homePage .lp3 .lp-pipe-doc i, #homePage .lp3 .lp-pipe-play i, #homePage .lp3 .lp-stamp i {
  font: 600 11px var(--font); font-style: normal; letter-spacing: 0;
  color: var(--slate-2); text-transform: none;
}
#homePage .lp3 .lp-pipe-arrow { width: 62px; height: 26px; flex: none; }
#homePage .lp3 .lp-pipe-arrow .lp-pipe-wire { stroke-dasharray: 100; stroke-dashoffset: 100; }
#homePage .lp3 .lp-pipe-arrow .lp-pipe-head { opacity: 0; }
#homePage .lp3 .sr.sr-in .lp-pipe-arrow:nth-of-type(1) .lp-pipe-wire { stroke-dashoffset: 0; transition: stroke-dashoffset .5s cubic-bezier(.4,0,.3,1) .25s; }
#homePage .lp3 .sr.sr-in .lp-pipe-arrow:nth-of-type(1) .lp-pipe-head { opacity: 1; transition: opacity .2s ease .7s; }
#homePage .lp3 .sr.sr-in .lp-pipe-arrow:nth-of-type(2) .lp-pipe-wire { stroke-dashoffset: 0; transition: stroke-dashoffset .5s cubic-bezier(.4,0,.3,1) .95s; }
#homePage .lp3 .sr.sr-in .lp-pipe-arrow:nth-of-type(2) .lp-pipe-head { opacity: 1; transition: opacity .2s ease 1.4s; }
#homePage .lp3 .lp-pipe-play {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 10px 18px 8px;
  background: var(--iris-bright); color: var(--on-signal);
  border: 1.5px solid var(--ink); border-radius: 999px;
  font: 700 14px var(--font); letter-spacing: .01em;
  box-shadow: 2px 2px 0 var(--ink);
}
#homePage .lp3 .lp-pipe-play svg { width: 12px; height: 12px; display: inline; vertical-align: -1px; margin-right: 6px; }
#homePage .lp3 .lp-pipe-play i { color: var(--ink-2); }
#homePage .lp3 .lp-pipe-stamps { display: flex; gap: 10px; flex-wrap: wrap; }
#homePage .lp3 .lp-stamp {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 58px; padding: 9px 12px 7px;
  background: #fff; color: var(--ink);
  border: 1.5px solid var(--ink); border-radius: 7px;
  font: 800 14px var(--mono); letter-spacing: .03em;
  box-shadow: 2px 2px 0 var(--ink);
}
#homePage .lp3 .lp-stamp-hero { background: var(--iris-bright); }
#homePage .lp3 .lp-stamp-hero i { color: var(--ink-2); }
#homePage .lp3 .sr .lp-stamp { opacity: 0; transform: translateY(8px) scale(.85) rotate(-2deg); }
#homePage .lp3 .sr.sr-in .lp-stamp {
  opacity: 1; transform: none;
  transition: opacity .3s var(--ease-out), transform .35s var(--ease-spring);
}
#homePage .lp3 .sr.sr-in .lp-stamp:nth-child(1) { transition-delay: 1.5s; }
#homePage .lp3 .sr.sr-in .lp-stamp:nth-child(2) { transition-delay: 1.65s; }
#homePage .lp3 .sr.sr-in .lp-stamp:nth-child(3) { transition-delay: 1.8s; }
#homePage .lp3 .sr.sr-in .lp-stamp:nth-child(4) { transition-delay: 1.95s; }
#homePage .lp3 .lp-pipe-note { font-size: 14px; color: var(--slate); margin: 4px 0 16px; }
@media (max-width: 640px) { #homePage .lp3 .lp-pipe-arrow { display: none; } }

/* Real-exports band (js/svg-reel.js), after the hero's proof strip: three
   equal tiles on one line, each a live animated-SVG export playing its
   reveal. One tile swaps at a time — the module's contract — so the row is
   never all mid-reveal at once. Tiles stack on phones. */
/* Enlarged view — an in-page lightbox (js/svg-reel.js), never a raw SVG
   document: the export stays an <img>, so its embedded script stays inert. */
.lp-svg-lightbox { position: fixed; inset: 0; z-index: 1300; display: flex;
  align-items: center; justify-content: center; padding: 4vh 4vw;
  background: rgba(5, 8, 16, .82); backdrop-filter: blur(6px); }
.lp-svg-lightbox[hidden] { display: none; }
.lp-svg-lightbox-fig { margin: 0; max-width: 100%; max-height: 100%;
  display: flex; flex-direction: column; gap: 10px; align-items: center; }
.lp-svg-lightbox-fig img { max-width: 92vw; max-height: 82vh; width: auto; height: auto;
  border-radius: 14px; border: 1px solid rgba(255, 255, 255, .14);
  background: #0b0f1c; box-shadow: 0 30px 80px -20px rgba(0, 0, 0, .8); }
.lp-svg-lightbox-cap { display: flex; align-items: center; gap: 14px;
  font-size: 14px; font-weight: 650; color: #e9ecf8; }
.lp-svg-lightbox-close { font: inherit; font-size: 22px; line-height: 1; cursor: pointer;
  width: 36px; height: 36px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, .3);
  background: rgba(255, 255, 255, .08); color: #e9ecf8; }
.lp-svg-lightbox-close:hover { background: rgba(255, 255, 255, .18); }
body.lp-svg-lightbox-open { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  #homePage .lp3 .lp-pipe-arrow .lp-pipe-wire, #homePage .lp3 .lp-pipe-arrow .lp-pipe-head,
  #homePage .lp3 .sr .lp-stamp { transition: none; opacity: 1; transform: none; stroke-dashoffset: 0; }
}

/* ---- v4.5: dialogs over the desk are paper sheets too. Modals live outside
   the pinned page containers, so the desk tokens are repeated for them,
   gated by which marketing overlay is visible. Tokens only — the backdrop
   keeps its own dim; .modal papers itself through var(--chrome-2)/tokens.
   (The reported case: the sign-in / free-account popup rendering dark over
   the paper home page.) ---- */
body:has(#homePage:not([hidden])) .modal-backdrop,
body:has(#explorePage:not([hidden])) .modal-backdrop,
body:has(#searchPage:not([hidden])) .modal-backdrop,
body:has(#rolesPage:not([hidden])) .modal-backdrop {
  --ink: #171821; --ink-2: #34353E;
  --paper: #FAF7EF; --panel: #ffffff; --panel-2: #F3EFE4;
  --slate: #55545A; --slate-2: #5F5E66;
  --edge: #D9D3C6; --dot: #d7ddf0; --faint: #6B6A72;
  --shadow: 0 1px 2px rgba(23,24,33,.05), 0 14px 32px -20px rgba(23,24,33,.22);
  --shadow-sm: 0 1px 2px rgba(23,24,33,.05), 0 6px 16px -10px rgba(23,24,33,.16);
  --shadow-lg: 0 2px 4px rgba(23,24,33,.06), 0 26px 52px -24px rgba(23,24,33,.26);
  --wordmark: #171821; --muted: #55545A; --border-soft: #E4DFD3;
  --danger: #c9364d; --canvas-bg: #ffffff;
  --iris: #F4A51C; --iris-bright: #F4A51C; --iris-deep: #DB8910;
  --iris-ink: #8F5E08; --iris-soft: #FBE6A6; --on-signal: #171821;
  --navy: #11152A;
  --chrome: var(--paper); --chrome-2: var(--panel); --chrome-3: var(--panel-2);
  --border: var(--edge); --text: var(--ink);
  --accent: var(--iris); --accent-ink: var(--iris-ink); --on-accent: var(--on-signal);
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
  --accent-ring: color-mix(in srgb, var(--accent) 30%, transparent);
  --glass-bg: rgba(250, 247, 239, .96);
  color: var(--text);
}

/* ---- inspector accordion (the collapsible Sequence-style section) ---- */
.insp-acc { margin: 4px 0 8px; border: 1px solid var(--border-soft); border-radius: 8px; }
.insp-acc > summary {
  cursor: pointer; list-style: none;
  padding: 9px 12px; font-size: 12.5px; font-weight: 650; color: var(--text);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border-radius: 8px;
}
.insp-acc > summary::-webkit-details-marker { display: none; }
.insp-acc > summary::after { content: "▾"; color: var(--slate-2); font-size: 11px; transition: transform .18s ease; }
.insp-acc:not([open]) > summary::after { transform: rotate(-90deg); }
.insp-acc > summary:hover { background: rgba(255, 255, 255, 0.07); }
.insp-acc[open] > summary { border-bottom: 1px solid var(--border-soft); border-radius: 8px 8px 0 0; }
.insp-acc > .field, .insp-acc > .check, .insp-acc > .muted { margin-left: 12px; margin-right: 12px; }
.insp-acc > .field:first-of-type { margin-top: 10px; }
.insp-acc > .field:last-of-type, .insp-acc > .check:last-of-type { margin-bottom: 12px; }

/* accordion summaries echo the panel's section-header language */
.insp-acc > summary {
  justify-content: flex-start;
  text-transform: uppercase; font-size: 11.5px; letter-spacing: .08em;
}
.insp-acc > summary::before {
  content: ""; flex: none; width: 3px; height: 11px; border-radius: 2px;
  background: var(--accent); margin-right: 2px;
}
.insp-acc > summary::after { margin-left: auto; }

/* ========================================================================
   NOTEBOOK NOVEL — a bound, narrated coursebook
   ------------------------------------------------------------------------
   The semantic renderer still owns every diagram and every measurement. This
   skin contributes the physical object around it: a restrained desk, linen
   covers, a warm page with a sewn gutter, and one finite page turn between
   Spotlight Cards.  Nothing here changes editor geometry or exported SVG.
   ======================================================================== */
body.presenting.pr-chrome-book {
  --pr-book-cover: #25324a;
  --pr-book-cover-deep: #151d2d;
  --pr-book-cover-ink: #fff7e8;
  --pr-book-gold: #c7a763;
  --pr-book-cream: #f7f1e3;
  --pr-book-ink: #241e1a;
  --pr-book-muted: #625a50;
  --pr-book-accent: #9a3c3a;
  --pr-book-rule: #a18d6c;
  --pr-book-desk: #151d2d;
  --pr-book-ribbon: #842f4b;
  --pr-book-board: #a87c49;
  --pr-book-edge: #d8c7a3;
  --pr-book-heading-font: Georgia, 'Iowan Old Style', 'Palatino Linotype', 'Times New Roman', serif;
  --pr-book-body-font: 'Iowan Old Style', 'Palatino Linotype', 'Book Antiqua', Georgia, serif;
  --pr-book-turn-ms: 500ms;
  /* One stock recipe for the resting spread and every retained/turning
     clone. Keeping these surfaces identical prevents the old card-shaped
     flash when a physical leaf lifts away from the destination. */
  --pr-book-spread-paper:
    radial-gradient(75% 115% at 23% 45%, color-mix(in srgb, white 17%, transparent), transparent 72%),
    radial-gradient(75% 115% at 77% 45%, color-mix(in srgb, white 19%, transparent), transparent 72%),
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--pr-book-ink) 1.8%, transparent) 0 1px, transparent 1px 5px),
    linear-gradient(90deg,
      color-mix(in srgb, var(--pr-book-cream) 80%, var(--pr-book-rule)) 0,
      color-mix(in srgb, var(--pr-book-cream) 96%, white) 2.2%,
      var(--pr-book-cream) 11%,
      color-mix(in srgb, var(--pr-book-cream) 94%, white) 43.5%,
      color-mix(in srgb, var(--pr-book-cream) 79%, var(--pr-book-rule)) 49.15%,
      color-mix(in srgb, var(--pr-book-ink) 15%, var(--pr-book-cream)) 49.92%,
      color-mix(in srgb, var(--pr-book-cream) 75%, var(--pr-book-rule)) 50.3%,
      color-mix(in srgb, var(--pr-book-cream) 95%, white) 56.5%,
      var(--pr-book-cream) 89%,
      color-mix(in srgb, var(--pr-book-cream) 79%, var(--pr-book-rule)) 100%);
  --pr-sheet-ink: var(--pr-book-ink);
}

/* The room stays quiet and dark; the page is the brightest thing in it. */
body.presenting.pr-chrome-book #stage,
body.pr-zen.presenting.pr-chrome-book #stage {
  --pr-plate: 0px;
  padding:
    max(8px, env(safe-area-inset-top, 0px))
    max(8px, env(safe-area-inset-right, 0px))
    max(8px, env(safe-area-inset-bottom, 0px))
    max(8px, env(safe-area-inset-left, 0px));
  background:
    radial-gradient(900px 540px at 47% 35%, color-mix(in srgb, var(--pr-book-cover) 54%, transparent), transparent 66%),
    repeating-linear-gradient(1deg, color-mix(in srgb, var(--pr-book-gold) 3%, transparent) 0 1px, transparent 1px 23px),
    linear-gradient(145deg, color-mix(in srgb, var(--pr-book-desk) 78%, black) 0%, var(--pr-book-desk) 58%, color-mix(in srgb, var(--pr-book-cover-deep) 72%, black) 100%);
  animation: none;
}
body.presenting.pr-chrome-book #canvasWrap {
  --pr-lane-top: 0px;
  --pr-lane-bottom: 0px;
  --pr-gutter: 0px;
  padding: 0 !important;
  perspective: 1800px;
  perspective-origin: 50% 42%;
}
/* The publication is already its own title, progress and notes surface. Its
   fixed 54:35 spread is centred in the entire safe stage instead of paying
   again for generic slide chrome or inheriting inline-block top-left bias. */
body.presenting.pr-chrome-book #prTvHead,
body.presenting.pr-chrome-book #prStepper,
body.presenting.pr-chrome-book #prNarration { display: none !important; }
body.presenting.pr-chrome-book #zoomLayer {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  padding: 0;
}
body.presenting.pr-chrome-book #svgHost { vertical-align: top; }
/* The Index's folio label and Continue control sit just below the bound page
   edge. Present normally clips the canvas because chapter sheets are fully
   fitted; while this front-matter spread is open, let those two intentional
   overhangs paint into the quiet lower bezel instead of being cut in half. */
body.presenting.pr-chrome-book #canvasWrap:has(#prIntro.pr-book-indexing) {
  --pr-lane-top: 0px;
  --pr-lane-bottom: 0px;
  --pr-gutter: 0px;
  padding: 0 !important;
  overflow: visible;
}
/* Opening front matter owns the whole Explain stage. The TV header, guide
   lane and generic Zen padding are hidden during this hold, so retaining
   their layout reserves only makes the physical book look undersized. Keep
   the device safe areas, then give the remaining rectangle to the spread. */
body.presenting.pr-chrome-book #stage:has(#prIntro.pr-book-indexing) {
  --pr-plate: 0px;
  padding:
    max(8px, env(safe-area-inset-top, 0px))
    max(8px, env(safe-area-inset-right, 0px))
    max(8px, env(safe-area-inset-bottom, 0px))
    max(8px, env(safe-area-inset-left, 0px));
}
body.presenting.pr-chrome-book #prIntro.pr-book-indexing {
  padding: 0 !important;
}

/* Book pages carry their own running head. Keep the generic Zen title from
   becoming a second white title strip above the physical cover/page. */
body.presenting.pr-chrome-book #prZenTitle { display: none !important; }
body.pr-zen-title.presenting.pr-chrome-book #canvasWrap { padding-top: 0 !important; }

/* The mounted SVG becomes the same continuous two-leaf spread as the Index.
   The semantic SVG is transparent paper ink; the host owns stock, binding
   and stacked page edges while the detached spread owns its portable running
   furniture, so authored card geometry stays portable and unmodified. */
body.presenting.pr-chrome-book #svgHost {
  position: relative;
  isolation: isolate;
  overflow: visible;
  border-radius: 5% 5% 4.2% 4.2% / 2.2% 2.2% 5.4% 5.4%;
  background: var(--pr-book-spread-paper);
  box-shadow:
    -5px 5px 0 -2px color-mix(in srgb, var(--pr-book-edge) 82%, var(--pr-book-cream)),
    5px 5px 0 -2px color-mix(in srgb, var(--pr-book-edge) 82%, var(--pr-book-cream)),
    -8px 9px 0 -3px color-mix(in srgb, var(--pr-book-edge) 72%, var(--pr-book-rule)),
    8px 9px 0 -3px color-mix(in srgb, var(--pr-book-edge) 72%, var(--pr-book-rule)),
    -11px 13px 0 -5px color-mix(in srgb, var(--pr-book-edge) 62%, var(--pr-book-rule)),
    11px 13px 0 -5px color-mix(in srgb, var(--pr-book-edge) 62%, var(--pr-book-rule)),
    0 15px 0 5px color-mix(in srgb, var(--pr-book-board) 88%, var(--pr-book-cover-deep)),
    0 32px 68px -25px rgba(0, 0, 0, .86),
    0 0 0 1px color-mix(in srgb, var(--pr-book-rule) 34%, transparent) inset;
  transform-style: preserve-3d;
}
body.presenting.pr-chrome-book #svgHost > svg {
  position: relative;
  z-index: 1;
  display: block;
  overflow: hidden;
  border-radius: 5% 5% 4.2% 4.2% / 2.2% 2.2% 5.4% 5.4%;
}
/* Every renderer emits an opaque document background rect. In book mode the
   host/leaf is that background; revealing it here is what makes separate
   Spotlight Cards read as ink on one uninterrupted spread. Detached page
   clones are included so a turn never flashes the old flat SVG sheet. */
body.presenting.pr-chrome-book :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay) svg rect[data-kind="bg"] {
  fill: transparent !important;
  fill-opacity: 0 !important;
}
body.presenting.pr-chrome-book #svgHost::before {
  content: "";
  position: absolute;
  z-index: 3;
  inset: 0 auto 0 50%;
  width: clamp(26px, 4.8%, 54px);
  transform: translateX(-50%);
  pointer-events: none;
  background:
    radial-gradient(ellipse at center,
      transparent 36%, color-mix(in srgb, var(--pr-book-gold) 54%, #777) 39% 46%,
      color-mix(in srgb, white 50%, transparent) 48%, transparent 53%)
      center 7px / clamp(18px, 2.2vw, 26px) 30px repeat-y,
    linear-gradient(90deg,
      transparent 0,
      color-mix(in srgb, var(--pr-book-ink) 8%, transparent) 19%,
      color-mix(in srgb, var(--pr-book-ink) 27%, transparent) 43%,
      color-mix(in srgb, var(--pr-book-ink) 48%, transparent) 49%,
      color-mix(in srgb, white 31%, transparent) 51.5%,
      color-mix(in srgb, var(--pr-book-ink) 12%, transparent) 72%,
      transparent 100%),
    repeating-linear-gradient(0deg, transparent 0 20px, color-mix(in srgb, var(--pr-book-rule) 6%, transparent) 21px 22px);
  filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--pr-book-ink) 58%, transparent));
  box-shadow: 0 0 21px -9px color-mix(in srgb, var(--pr-book-ink) 96%, transparent) inset;
  -webkit-mask-image: linear-gradient(transparent 1%, black 6% 94%, transparent 99%);
  mask-image: linear-gradient(transparent 1%, black 6% 94%, transparent 99%);
}
body.presenting.pr-chrome-book #svgHost::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -1px -7px -9px;
  border-right: 7px solid color-mix(in srgb, var(--pr-book-edge) 76%, var(--pr-book-rule));
  border-bottom: 9px double color-mix(in srgb, var(--pr-book-edge) 80%, var(--pr-book-rule));
  border-left: 7px solid color-mix(in srgb, var(--pr-book-edge) 82%, var(--pr-book-rule));
  border-radius: 7% 7% 5% 5% / 2.5% 2.5% 7% 7%;
  background:
    radial-gradient(24px 17px at 100% 100%, color-mix(in srgb, white 52%, transparent), transparent 72%),
    radial-gradient(24px 17px at 0 100%, color-mix(in srgb, var(--pr-book-rule) 34%, transparent), transparent 72%);
  box-shadow:
    0 8px 0 4px color-mix(in srgb, var(--pr-book-board) 84%, var(--pr-book-cover-deep)),
    0 17px 20px -15px rgba(0,0,0,.92);
  pointer-events: none;
}
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-running,
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-folios {
  position: absolute;
  z-index: 4;
  left: clamp(24px, 4.2%, 46px);
  right: clamp(24px, 4.2%, 46px);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(38px, 8%, 86px);
  color: color-mix(in srgb, var(--pr-book-muted) 72%, transparent);
  font: 650 9.5px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .09em;
  text-transform: uppercase;
  pointer-events: none;
}
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-running { top: 11px; }
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-running span {
  min-width: 0;
  padding-bottom: 7px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid color-mix(in srgb, var(--pr-book-rule) 34%, transparent);
}
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-running span:last-child,
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-folios span:last-child { text-align: right; }
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-running span.pr-book-empty-leaf,
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-folios span.pr-book-empty-leaf {
  visibility: hidden;
  border-bottom: 0;
}
body.presenting.pr-chrome-book #svgHost > .pr-book-spread-folios {
  bottom: 9px;
  color: color-mix(in srgb, var(--pr-book-muted) 62%, transparent);
  font-size: 8.5px;
}

/* Spotlight Cards are page content in this theme, not cards laid on paper.
   Their first rect remains in the DOM as the renderer's silhouette/hit and
   clipping contract, but contributes no fill, border, glow or shadow. Images
   likewise lose the UI-card keyline while authored block backgrounds remain
   intact as genuine editorial choices. Stable renderer classes keep live and
   serialized/raster paths on the same contract. */
body.presenting.pr-chrome-book :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay)
  svg .spot-card-surface {
  fill: transparent !important;
  fill-opacity: 0 !important;
  stroke: none !important;
  stroke-opacity: 0 !important;
  filter: none !important;
}
body.presenting.pr-chrome-book :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay)
  svg .spot-card-media-frame {
  stroke: none !important;
}
body.presenting.pr-chrome-book :is(#svgHost, .pr-book-page-turn, .pr-book-page-stay)
  svg .pr-anim-bookpage {
  animation: none !important;
  opacity: 1 !important;
}
body.presenting.pr-chrome-book svg .spot-book-writer {
  filter: drop-shadow(0 2px 2px color-mix(in srgb, var(--pr-book-ink) 22%, transparent));
  will-change: transform, opacity;
}

/* Live page-turn leaf. The destination is already mounted underneath, so a
   failed/hidden-tab animation still leaves a complete readable page. */
body.presenting.pr-chrome-book .pr-book-page-turn,
body.presenting.pr-chrome-book .pr-book-page-stay {
  position: absolute;
  z-index: 7;
  transform-style: preserve-3d;
  border-radius: 16px;
  pointer-events: none;
}
body.presenting.pr-chrome-book .pr-book-page-stay {
  z-index: 6;
  overflow: hidden;
  background: var(--pr-book-spread-paper);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-book-rule) 28%, transparent) inset;
  filter: brightness(.985) saturate(.98);
}
body.presenting.pr-chrome-book .pr-book-stay-left { clip-path: inset(0 50% 0 0); }
body.presenting.pr-chrome-book .pr-book-stay-right { clip-path: inset(0 0 0 50%); }
/* The airborne leaf casts a brief spine-side shadow onto the stationary mate.
   Without this contact shadow an otherwise correct 3-D turn reads like a
   rigid panel; the soft peak around the edge-on midpoint gives it paper depth. */
body.presenting.pr-chrome-book .pr-book-page-stay::after {
  content: "";
  position: absolute;
  z-index: 3;
  inset: 0 50% 0 0;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 63%, color-mix(in srgb, var(--pr-book-ink) 45%, transparent) 100%);
  opacity: 0;
  animation: prBookStayShadow var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both;
}
body.presenting.pr-chrome-book .pr-book-stay-right::after {
  inset: 0 0 0 50%;
  background: linear-gradient(270deg, transparent 63%, color-mix(in srgb, var(--pr-book-ink) 45%, transparent) 100%);
}
body.presenting.pr-chrome-book .pr-book-page-turn {
  overflow: visible;
  /* Keep the wide SVG leaf on the compositor. Animating CSS filter forced a
     fresh raster of every word/image on each turn frame; the dedicated shade,
     moving edge and stationary-page shadow already supply the same depth. */
  will-change: transform, opacity;
}
body.presenting.pr-chrome-book .pr-book-leaf-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  background: var(--pr-book-spread-paper);
  background-size: 200% 100%;
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--pr-book-rule) 30%, transparent) inset,
    0 30px 58px -23px rgba(0, 0, 0, .92);
}
body.presenting.pr-chrome-book .pr-book-leaf-back { transform: rotateY(180deg); }
/* Chromium can briefly raster the front face through its back despite
   backface-visibility while a wide embedded SVG is being transformed. The
   explicit half-turn handoff makes the physical rule deterministic: old
   right front before the spine, blank/new-left back after it. */
body.presenting.pr-chrome-book .pr-book-page-turn .pr-book-leaf-front {
  animation: prBookLeafFrontFace var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-book .pr-book-page-turn .pr-book-leaf-back {
  animation: prBookLeafBackFace var(--pr-book-turn-ms, 500ms) linear both;
}
body.presenting.pr-chrome-book .pr-book-turn-forward .pr-book-leaf-front {
  border-radius: 2px 16px 16px 2px;
  background-position: right top;
}
body.presenting.pr-chrome-book .pr-book-turn-forward .pr-book-leaf-back {
  border-radius: 16px 2px 2px 16px;
  background-position: left top;
}
body.presenting.pr-chrome-book .pr-book-turn-back .pr-book-leaf-front {
  border-radius: 16px 2px 2px 16px;
  background-position: left top;
}
body.presenting.pr-chrome-book .pr-book-turn-back .pr-book-leaf-back {
  border-radius: 2px 16px 16px 2px;
  background-position: right top;
}
body.presenting.pr-chrome-book .pr-book-page-turn::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 43%, color-mix(in srgb, white 16%, transparent) 54%, color-mix(in srgb, var(--pr-book-ink) 8%, transparent) 70%, color-mix(in srgb, var(--pr-book-ink) 44%, transparent) 100%);
  opacity: 0;
  animation: prBookLeafShade var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both;
}
body.presenting.pr-chrome-book .pr-book-turn-back::after {
  background: linear-gradient(270deg, transparent 43%, color-mix(in srgb, white 16%, transparent) 54%, color-mix(in srgb, var(--pr-book-ink) 8%, transparent) 70%, color-mix(in srgb, var(--pr-book-ink) 44%, transparent) 100%);
}
body.presenting.pr-chrome-book .pr-book-page-turn::before {
  content: "";
  position: absolute;
  z-index: 3;
  top: 0;
  right: -2px;
  bottom: 0;
  width: clamp(3px, .65%, 7px);
  border-radius: 50%;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--pr-book-rule) 58%, transparent),
    color-mix(in srgb, white 78%, var(--pr-book-cream)) 48%,
    color-mix(in srgb, var(--pr-book-ink) 28%, transparent));
  box-shadow: 1px 0 7px color-mix(in srgb, var(--pr-book-ink) 32%, transparent);
  opacity: 0;
  animation: prBookLeafEdge var(--pr-book-turn-ms, 500ms) ease-in-out both;
}
body.presenting.pr-chrome-book .pr-book-turn-back::before { right: auto; left: -2px; }
body.presenting.pr-chrome-book .pr-book-turn-forward {
  transform-origin: left center;
  animation: prBookTurnForward var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both;
}
body.presenting.pr-chrome-book .pr-book-turn-back {
  transform-origin: right center;
  animation: prBookTurnBack var(--pr-book-turn-ms, 500ms) cubic-bezier(.36, .02, .18, 1) both;
}
@keyframes prBookTurnForward {
  0%   { transform: rotateY(0deg) translateZ(0) rotateZ(0) skewY(0); opacity: 1; }
  22%  { transform: rotateY(-35deg) translateZ(10px) rotateZ(-.22deg) skewY(-.28deg); }
  49%  { transform: rotateY(-91deg) translateZ(27px) rotateZ(-.45deg) skewY(-.7deg) scaleY(.992); opacity: 1; }
  77%  { transform: rotateY(-145deg) translateZ(11px) rotateZ(.18deg) skewY(.28deg); }
  100% { transform: rotateY(-180deg) translateZ(1px) rotateZ(0) skewY(0); opacity: 1; }
}
@keyframes prBookLeafFrontFace {
  0%, 49.99% { opacity: 1; }
  50%, 100% { opacity: 0; }
}
@keyframes prBookLeafBackFace {
  0%, 49.99% { opacity: 0; }
  50%, 100% { opacity: 1; }
}
@keyframes prBookTurnBack {
  0%   { transform: rotateY(0deg) translateZ(0) rotateZ(0) skewY(0); opacity: 1; }
  22%  { transform: rotateY(35deg) translateZ(10px) rotateZ(.22deg) skewY(.28deg); }
  49%  { transform: rotateY(91deg) translateZ(27px) rotateZ(.45deg) skewY(.7deg) scaleY(.992); opacity: 1; }
  77%  { transform: rotateY(145deg) translateZ(11px) rotateZ(-.18deg) skewY(-.28deg); }
  100% { transform: rotateY(180deg) translateZ(1px) rotateZ(0) skewY(0); opacity: 1; }
}
@keyframes prBookLeafShade {
  0%, 100% { opacity: 0; }
  48% { opacity: .9; }
}
@keyframes prBookLeafEdge {
  0%, 100% { opacity: 0; transform: scaleX(.4); }
  42%, 58% { opacity: .95; transform: scaleX(1.2); }
}
@keyframes prBookStayShadow {
  0%, 100% { opacity: 0; }
  44%, 60% { opacity: .72; }
}

/* Linen front cover — title first, like a real book jacket. */
body.presenting.pr-chrome-book #prIntro,
body.presenting.pr-chrome-book #prEnd {
  perspective: 1900px;
  background:
    radial-gradient(760px 470px at 50% 38%, color-mix(in srgb, var(--pr-book-cover) 58%, transparent), transparent 68%),
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-gold) 3%, transparent) 0 1px, transparent 1px 25px),
    color-mix(in srgb, var(--pr-book-cover-deep) 94%, transparent);
  -webkit-backdrop-filter: blur(7px) saturate(.88);
  backdrop-filter: blur(7px) saturate(.88);
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card,
body.presenting.pr-chrome-book #prEnd .pr-end-card {
  position: relative;
  box-sizing: border-box;
  width: min(500px, calc(100vw - 54px), calc((100vh - 42px) * .72));
  min-width: min(350px, calc(100vw - 34px));
  height: min(86vh, 720px);
  max-width: none;
  max-height: calc(100vh - 34px);
  padding: clamp(42px, 6vh, 62px) clamp(34px, 5vw, 58px) 32px;
  overflow: hidden;
  color: var(--pr-book-cover-ink);
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 66%, transparent);
  border-radius: 7px 18px 18px 7px;
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-deep) 48%, transparent), color-mix(in srgb, var(--pr-book-cover-ink) 6%, transparent) 7%, transparent 15%),
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--pr-book-cover-ink) 4%, transparent) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-ink) 3%, transparent) 0 1px, transparent 1px 10px),
    linear-gradient(145deg, color-mix(in srgb, var(--pr-book-cover) 82%, white), var(--pr-book-cover) 46%, var(--pr-book-cover-deep));
  box-shadow:
    9px 9px 0 -3px color-mix(in srgb, var(--pr-book-cream) 76%, var(--pr-book-rule)),
    14px 14px 0 -7px color-mix(in srgb, var(--pr-book-cream) 54%, var(--pr-book-rule)),
    0 36px 80px -24px rgba(0, 0, 0, .9);
  transform-origin: left center;
  animation: prBookCoverArrive 720ms cubic-bezier(.2, .78, .2, 1) both;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card::before,
body.presenting.pr-chrome-book #prEnd .pr-end-card::before,
body.presenting.pr-chrome-book #prTitleCard::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 5.2%;
  border: 1.5px solid var(--pr-book-gold);
  border-radius: 4px 12px 12px 4px;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--pr-book-cover-ink) 16%, transparent) inset;
  pointer-events: none;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card > *,
body.presenting.pr-chrome-book #prEnd .pr-end-card > *,
body.presenting.pr-chrome-book #prTitleCard > * { position: relative; z-index: 1; }
@keyframes prBookCoverArrive {
  from { opacity: 0; transform: translateY(24px) rotateY(-7deg) rotateZ(-1deg) scale(.965); }
  to   { opacity: 1; transform: none; }
}
body.presenting.pr-chrome-book #prIntro.pr-book-opening { pointer-events: none; }
body.presenting.pr-chrome-book #prIntro.pr-book-opening .pr-intro-card {
  animation: prBookCoverOpen var(--pr-book-turn-ms, 500ms) cubic-bezier(.64, .02, .22, 1) forwards;
}
@keyframes prBookCoverOpen {
  0%   { opacity: 1; transform: rotateY(0deg); filter: brightness(1); }
  54%  { opacity: 1; filter: brightness(.82); }
  100% { opacity: 0; transform: rotateY(-112deg) translateX(-3%); filter: brightness(.66); }
}

body.presenting.pr-chrome-book #prIntro .pr-intro-eyebrow {
  order: 0;
  margin: 14px 0 15px;
  color: var(--pr-book-gold);
  font: 700 10.5px ui-monospace, 'SF Mono', Menlo, monospace !important;
  letter-spacing: .2em;
  overflow-wrap: anywhere;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-title {
  order: 1;
  margin: 0;
  max-width: 94%;
  color: var(--pr-book-cover-ink);
  font-family: var(--pr-book-heading-font) !important;
  font-size: clamp(28px, 5vh, 48px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.022em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-title::after {
  content: "";
  display: block;
  width: 68px;
  height: 2px;
  margin: 20px auto 0;
  background: var(--pr-book-gold);
  box-shadow: 0 0 15px color-mix(in srgb, var(--pr-book-gold) 28%, transparent);
}
body.presenting.pr-chrome-book #prIntro .pr-intro-meta { order: 2; margin-top: 20px; }
body.presenting.pr-chrome-book #prIntro .pr-intro-meta span {
  color: color-mix(in srgb, var(--pr-book-cover-ink) 82%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-gold) 36%, transparent);
  background: color-mix(in srgb, var(--pr-book-cover-deep) 18%, transparent);
}
body.presenting.pr-chrome-book #prIntro .pr-intro-play {
  order: 3;
  margin-top: clamp(22px, 4vh, 36px);
  color: var(--pr-book-cover-deep);
  background: linear-gradient(180deg, color-mix(in srgb, var(--pr-book-gold) 68%, white), var(--pr-book-gold));
  box-shadow: 0 1px 0 rgba(255,255,255,.42) inset, 0 17px 34px -17px color-mix(in srgb, var(--pr-book-cover-deep) 76%, black);
}
/* The global tooltip ring also uses ::after; the cover button supplies its
   own focus ring, so suppress that overlapping pseudo-element here. */
body.presenting.pr-chrome-book #prIntro .pr-intro-play::after { content: none; }
body.presenting.pr-chrome-book #prIntro .pr-intro-play:focus-visible {
  outline-color: color-mix(in srgb, var(--pr-book-gold) 68%, white);
  outline-offset: 3px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-row { order: 4; justify-content: center; flex-wrap: wrap; }
body.presenting.pr-chrome-book #prIntro .pr-mini {
  color: color-mix(in srgb, var(--pr-book-cover-ink) 90%, transparent);
  background: color-mix(in srgb, var(--pr-book-cover-deep) 22%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-gold) 28%, transparent);
}
body.presenting.pr-chrome-book #prIntro .pr-intro-foot {
  order: 5;
  margin-top: 18px;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 64%, transparent);
  font-family: var(--pr-book-body-font) !important;
  font-style: italic;
  overflow-wrap: anywhere;
}
body.presenting.pr-chrome-book #prIntro .pr-brandin {
  order: 6;
  margin: auto 0 0;
  gap: 5px;
}
body.presenting.pr-chrome-book #prIntro .pr-brandin .pr-intro-mark { width: 35px; height: 35px; color: var(--pr-book-gold); opacity: 1; }
body.presenting.pr-chrome-book #prIntro .pr-brandin-word { color: var(--pr-book-cover-ink); font-size: 17px; }
body.presenting.pr-chrome-book #prIntro .pr-bi-spark,
body.presenting.pr-chrome-book #prIntro .pr-brandin-glow { display: none; }
body.presenting.pr-chrome-book #prIntro.pr-book-auto .pr-intro-play,
body.presenting.pr-chrome-book #prIntro.pr-book-auto .pr-intro-row { visibility: hidden; }

/* A precomposed jacket replaces generated cover furniture only when the
   portable title-image layout explicitly says `cover`. The course title
   remains in the accessibility tree and the whole jacket remains the Play
   target, while the authored pixels themselves are never cropped. */
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover {
  width: auto;
  min-width: 0;
  height: min(86vh, 720px);
  max-width: calc(100vw - 54px);
  max-height: calc(100vh - 34px);
  aspect-ratio: var(--pr-book-custom-cover-ratio, 2 / 3);
  padding: 0 !important;
  background: #050816 !important;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover::before { content: none; }
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover > :not(#prIntroCoverImg):not(#prIntroTitle):not(#prIntroPlay):not(.pr-book-index) {
  display: none !important;
}
body.presenting.pr-chrome-book #prIntro .pr-book-custom-cover-art {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
  background: #050816;
  pointer-events: none;
}
body.presenting.pr-chrome-book #prIntro .pr-book-custom-cover-art[hidden] { display: none; }
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover #prIntroTitle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover #prIntroPlay {
  position: absolute;
  z-index: 4;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border-radius: inherit;
  opacity: 0;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover:has(#prIntroPlay:focus-visible) {
  outline: 3px solid color-mix(in srgb, var(--pr-book-gold) 78%, white);
  outline-offset: 5px;
}

/* Front matter: the cover opens into a genuine two-page contents spread.
   The list is derived at show time, so it always reflects the final authored
   course rather than a stale copy saved earlier. */
body.pr-rec.pr-rec-book-index #prIntro { display: grid !important; }
/* Recording briefly reuses the interactive cover shell to render the Index.
   Keep that captured surface Index-only even while its paging classes settle:
   Play, setup controls, metadata and the authored footer belong to the live
   Explain menu, never to the exported take. */
/* In a take's index hold only the Index itself may show — the bound book's
   two-leaf section OR the drawing book's one-page contents sheet
   (#prDrawIndex; it was caught by this rule and a recorded drawing book
   skipped its contents — operator, Sep 5). */
body.pr-rec.pr-rec-book-index #prIntro .pr-intro-card > :not(.pr-book-index):not(#prDrawIndex) { display: none !important; }
body.presenting.pr-chrome-book #prBookIndex[hidden] { display: none !important; }
body.presenting.pr-chrome-book #prIntro.pr-book-indexing .pr-intro-card {
  /* The Index is the first real spread, so it should occupy the same visual
     stage as the chapter pages. JS inscribes the exact rectangle from this
     overlay's measured box. The percentage fallback is ratio-preserving and
     uncapped, so the first paint is already a large spread if JS is delayed. */
  --pr-book-index-material-edge: 18px;
  width: var(--pr-book-index-fit-width, calc(100% - var(--pr-book-index-material-edge) - var(--pr-book-index-material-edge)));
  height: var(--pr-book-index-fit-height, auto);
  aspect-ratio: 54 / 35;
  flex: 0 0 auto;
  min-width: 0;
  max-width: calc(100% - var(--pr-book-index-material-edge) - var(--pr-book-index-material-edge));
  max-height: calc(100% - var(--pr-book-index-material-edge) - var(--pr-book-index-material-edge));
  /* fitNotebookDomCover writes a cover-specific safe-area inset and hidden
     overflow inline. Once the cover opens those values must not shrink or
     crop the two-page spread (including the button below its fore edge). */
  padding: 0 !important;
  overflow: visible !important;
  color: var(--pr-book-ink);
  border: 0;
  border-radius: 16px;
  background: transparent;
  box-shadow: none;
  animation: prBookIndexOpen 760ms cubic-bezier(.2, .78, .2, 1) both;
}
body.presenting.pr-chrome-book #prIntro.pr-book-indexing .pr-intro-card::before { content: none; }
body.presenting.pr-chrome-book #prIntro.pr-book-indexing .pr-intro-card > :not(.pr-book-index) { display: none !important; }
body.presenting.pr-chrome-book #prBookIndex {
  position: relative;
  z-index: 2;
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  counter-reset: book-index;
  filter: drop-shadow(0 32px 28px rgba(0, 0, 0, .48));
  transform-style: preserve-3d;
  perspective: 1800px;
  isolation: isolate;
}
body.presenting.pr-chrome-book #prBookIndex::before {
  content: "";
  position: absolute;
  z-index: 5;
  top: 1.5%;
  bottom: 1.5%;
  left: 50%;
  width: clamp(26px, 4.8%, 54px);
  transform: translateX(-50%);
  pointer-events: none;
  background:
    radial-gradient(ellipse at center,
      transparent 36%, color-mix(in srgb, var(--pr-book-gold) 54%, #777) 39% 46%,
      color-mix(in srgb, white 50%, transparent) 48%, transparent 53%)
      center 7px / clamp(18px, 2.2vw, 26px) 30px repeat-y,
    linear-gradient(90deg,
      transparent, color-mix(in srgb, var(--pr-book-ink) 26%, transparent) 43%,
      color-mix(in srgb, var(--pr-book-ink) 48%, transparent) 49%,
      color-mix(in srgb, white 30%, transparent) 51.5%,
      color-mix(in srgb, var(--pr-book-ink) 11%, transparent) 72%, transparent);
  filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--pr-book-ink) 58%, transparent));
  -webkit-mask-image: linear-gradient(transparent, black 5% 95%, transparent);
  mask-image: linear-gradient(transparent, black 5% 95%, transparent);
}
body.presenting.pr-chrome-book #prBookIndex::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -1px -7px -9px;
  border-right: 7px solid color-mix(in srgb, var(--pr-book-edge) 76%, var(--pr-book-rule));
  border-bottom: 9px double color-mix(in srgb, var(--pr-book-edge) 80%, var(--pr-book-rule));
  border-left: 7px solid color-mix(in srgb, var(--pr-book-edge) 82%, var(--pr-book-rule));
  border-radius: 7% 7% 5% 5% / 2.5% 2.5% 7% 7%;
  box-shadow: 0 13px 18px -14px rgba(0,0,0,.9);
  pointer-events: none;
}
.pr-book-bindery {
  position: absolute;
  display: block;
  pointer-events: none;
}
.pr-book-cover-board {
  z-index: 0;
  inset: 7px -14px -16px;
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 24%, transparent);
  border-radius: 6% 6% 5% 5% / 2.5% 2.5% 8% 8%;
  background:
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-cover-ink) 3%, transparent) 0 1px, transparent 1px 11px),
    linear-gradient(150deg, color-mix(in srgb, var(--pr-book-board) 84%, white), var(--pr-book-board) 55%, var(--pr-book-cover-deep));
  box-shadow: 0 18px 30px -18px rgba(0,0,0,.92);
}
.pr-book-page-fan {
  z-index: 0;
  bottom: -11px;
  width: calc(50% - 5px);
  height: 18px;
  border-bottom: 1px solid color-mix(in srgb, var(--pr-book-rule) 54%, transparent);
  border-radius: 0 0 50% 50% / 0 0 100% 100%;
  background: repeating-linear-gradient(0deg,
    color-mix(in srgb, var(--pr-book-edge) 82%, white) 0 1px,
    color-mix(in srgb, var(--pr-book-edge) 48%, var(--pr-book-cream)) 1px 3px);
}
.pr-book-page-fan-left { left: 2px; transform: rotate(.35deg); }
.pr-book-page-fan-right { right: 2px; transform: rotate(-.35deg); }
.pr-book-ribbon {
  z-index: 6;
  top: -9px;
  left: calc(50% - 10px);
  width: 20px;
  height: 47%;
  clip-path: polygon(12% 0, 88% 0, 82% 86%, 54% 100%, 48% 91%, 12% 98%, 24% 63%);
  background:
    linear-gradient(90deg, rgba(0,0,0,.22), transparent 26%, rgba(255,255,255,.23) 48%, transparent 69%, rgba(0,0,0,.26)),
    var(--pr-book-ribbon);
  filter: drop-shadow(2px 4px 3px color-mix(in srgb, var(--pr-book-ink) 42%, transparent));
  transform: rotate(-1.2deg);
  transform-origin: top center;
}
.pr-book-index-page {
  --pr-book-page-inset: clamp(34px, 4.5vw, 66px);
  --pr-book-page-start: var(--pr-book-page-inset);
  position: relative;
  z-index: 2;
  min-width: 0;
  overflow: hidden;
  box-sizing: border-box;
  padding: clamp(48px, 6vh, 72px) var(--pr-book-page-inset) 48px var(--pr-book-page-start);
  color: var(--pr-book-ink);
  border: 1px solid color-mix(in srgb, var(--pr-book-rule) 60%, transparent);
  background:
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--pr-book-ink) 2%, transparent) 0 1px, transparent 1px 5px),
    var(--pr-book-cream);
  font-family: var(--pr-book-body-font);
}
.pr-book-index-foreword {
  border-radius: 8% 1% 1.5% 7% / 2.5% 1% 7% 6%;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--pr-book-cream) 84%, var(--pr-book-rule)),
      var(--pr-book-cream) 9%,
      color-mix(in srgb, var(--pr-book-cream) 92%, white) 82%,
      color-mix(in srgb, var(--pr-book-cream) 88%, var(--pr-book-rule))),
    var(--pr-book-cream);
  box-shadow: -8px 8px 0 -5px color-mix(in srgb, var(--pr-book-cream) 62%, var(--pr-book-rule));
}
.pr-book-index-contents {
  border-radius: 1% 8% 7% 1.5% / 1% 2.5% 6% 7%;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--pr-book-cream) 78%, var(--pr-book-rule)),
      var(--pr-book-cream) 8%,
      color-mix(in srgb, var(--pr-book-cream) 93%, white) 86%,
      color-mix(in srgb, var(--pr-book-cream) 87%, var(--pr-book-rule))),
    var(--pr-book-cream);
  box-shadow: 8px 8px 0 -5px color-mix(in srgb, var(--pr-book-cream) 62%, var(--pr-book-rule));
}
.pr-book-index-foreword::after,
.pr-book-index-contents::before {
  content: "";
  position: absolute;
  z-index: 3;
  inset: 0 0 0 auto;
  width: 28px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--pr-book-ink) 17%, transparent));
}
.pr-book-index-contents::before { inset: 0 auto 0 0; background: linear-gradient(90deg, color-mix(in srgb, var(--pr-book-ink) 20%, transparent), transparent); }
.pr-book-running {
  position: absolute;
  top: 20px;
  left: var(--pr-book-page-start);
  right: var(--pr-book-page-inset);
  padding-bottom: 8px;
  color: var(--pr-book-muted);
  border-bottom: 1px solid color-mix(in srgb, var(--pr-book-rule) 45%, transparent);
  font: 650 9px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.pr-book-index-kicker {
  margin-bottom: 10px;
  color: var(--pr-book-accent);
  font: 750 10px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .18em;
  text-transform: uppercase;
}
.pr-book-index-page h3 {
  margin: 0 0 22px;
  color: var(--pr-book-ink);
  font-family: var(--pr-book-heading-font);
  font-size: clamp(25px, 3vw, 42px);
  line-height: 1.04;
  letter-spacing: -.025em;
}
.pr-book-index-list {
  max-height: calc(100% - 92px);
  margin: 0;
  padding: 0;
  overflow: hidden;
  list-style: none;
}
.pr-book-index-list li {
  counter-increment: book-index;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 8px;
  padding: 7px 0;
  color: var(--pr-book-ink);
  font-size: clamp(12px, 1.25vw, 16px);
  line-height: 1.32;
  opacity: 0;
  animation: prBookIndexIn 360ms cubic-bezier(.2, .75, .25, 1) calc(260ms + var(--book-i, 0) * 52ms) forwards;
}
.pr-book-index-list li::before {
  content: counter(book-index, decimal-leading-zero);
  min-width: 2.5ch;
  color: var(--pr-book-accent);
  font: 700 9px ui-monospace, 'SF Mono', Menlo, monospace;
  font-variant-numeric: tabular-nums;
  line-height: 1.32;
  text-align: right;
}
.pr-book-index-list li[data-book-cont="true"]::before {
  content: "↳";
  font-size: 12px;
}
.pr-book-index-list li span {
  min-width: 0;
  text-align: left;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.28;
  padding-bottom: 3px;
  border-bottom: 1px dotted color-mix(in srgb, var(--pr-book-rule) 55%, transparent);
}
.pr-book-index-list li b {
  min-width: 2.5ch;
  color: var(--pr-book-muted);
  font: 650 9px ui-monospace, 'SF Mono', Menlo, monospace;
  font-variant-numeric: tabular-nums;
  line-height: 1.32;
  text-align: right;
}
/* Both leaves are dedicated contents pages. Their rows use the complete
   printable depth instead of forming a small stack beneath foreword copy.
   Each row grows in proportion to its measured line cost, so a wrapped title
   receives more room while the numbering, title and folio lanes stay aligned. */
.pr-book-index-leaf {
  display: grid;
  grid-template-rows: max-content max-content minmax(0, 1fr);
  align-content: stretch;
}
.pr-book-index-leaf .pr-book-index-list {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  max-height: none;
}
.pr-book-index-leaf .pr-book-index-list li {
  flex: var(--book-index-lines, 1) 1 0;
  align-content: center;
  box-sizing: border-box;
  min-height: 0;
  width: 100%;
  padding-block: clamp(2px, .45vh, 6px);
  font-size: clamp(14px, 1.45vw, 20px);
}
.pr-book-index-leaf .pr-book-index-list li::before,
.pr-book-index-leaf .pr-book-index-list li b {
  font-size: clamp(9px, .9vw, 13px);
}
/* A single surviving topic is a short contents page, not a display poster.
   Keep it on the normal top reading measure; two or more rows earn the
   full-depth distribution above. */
.pr-book-index-leaf .pr-book-index-list:not(:has(li:nth-child(2))) li {
  flex: 0 0 auto;
  align-content: start;
}
.pr-book-index-continue {
  position: absolute;
  z-index: 8;
  left: 50%;
  bottom: clamp(10px, 1.8%, 16px);
  transform: translateX(-50%);
  min-width: min(168px, 56%);
  max-width: min(310px, 56%);
  padding: 8px 16px;
  color: var(--pr-book-cover-deep);
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 70%, transparent);
  border-radius: 999px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--pr-book-gold) 68%, white), var(--pr-book-gold));
  box-shadow: 0 15px 30px -18px #000;
  font-size: clamp(10px, 1.05vw, 13px);
  font-weight: 750;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.pr-book-index-continue:focus-visible { outline: 3px solid var(--pr-book-cover-ink); outline-offset: 3px; }
.pr-book-index-position {
  position: absolute;
  z-index: 8;
  left: clamp(16px, 2.5%, 28px);
  bottom: clamp(16px, 2.4%, 24px);
  color: color-mix(in srgb, var(--pr-book-muted) 78%, transparent);
  font: 650 9px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .11em;
  text-transform: uppercase;
}
body.presenting.pr-chrome-book #prIntro.pr-book-auto.pr-book-indexing :is(.pr-book-index-continue, .pr-book-index-position),
body.pr-rec.pr-rec-book-index #prIntro :is(.pr-book-index-continue, .pr-book-index-position) {
  display: none !important;
}
@keyframes prBookIndexOpen {
  from { opacity: 0; transform: translateY(16px) rotateX(4deg) scale(.95); }
  to { opacity: 1; transform: none; }
}
body.presenting.pr-chrome-book #prIntro.pr-book-index-leaving .pr-book-index-contents {
  transform-origin: left center;
  animation: prBookIndexTurnOut var(--pr-book-turn-ms, 500ms) cubic-bezier(.58, .02, .22, 1) both;
}
body.presenting.pr-chrome-book #prIntro.pr-book-index-leaving .pr-book-index-foreword {
  animation: prBookIndexFadeOut var(--pr-book-turn-ms, 500ms) ease both;
}
body.presenting.pr-chrome-book #prIntro.pr-book-index-paging .pr-book-index-contents {
  transform-origin: left center;
  animation: prBookIndexTurnOut var(--pr-book-turn-ms, 500ms) cubic-bezier(.58, .02, .22, 1) both;
}
body.presenting.pr-chrome-book #prIntro.pr-book-index-paging .pr-book-index-foreword {
  animation: prBookIndexPageHold var(--pr-book-turn-ms, 500ms) ease both;
}
@keyframes prBookIndexTurnOut { to { transform: rotateY(-176deg); filter: brightness(.72); opacity: .06; } }
@keyframes prBookIndexFadeOut { 70% { opacity: 1; } to { opacity: 0; } }
@keyframes prBookIndexPageHold { 48% { filter: brightness(.95); } }

/* The timed/recorded DOM title card uses the same physical cover.  Its flat
   children are re-ordered with display:contents so the title owns the top and
   optional cover art can sit beneath it without changing index.html. */
body.presenting.pr-chrome-book #prTitleCard {
  inset: 50% auto auto 50%;
  width: min(500px, 52vw);
  min-width: min(350px, calc(100% - 34px));
  height: min(78%, 720px);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  transform: translate(-50%, -50%);
  padding: clamp(42px, 6vh, 62px) clamp(34px, 5vw, 58px) 34px;
  color: var(--pr-book-cover-ink) !important;
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 58%, transparent);
  border-radius: 7px 18px 18px 7px;
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-deep) 48%, transparent), color-mix(in srgb, var(--pr-book-cover-ink) 6%, transparent) 7%, transparent 15%),
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--pr-book-cover-ink) 4%, transparent) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-ink) 3%, transparent) 0 1px, transparent 1px 10px),
    linear-gradient(145deg, color-mix(in srgb, var(--pr-book-cover) 82%, white), var(--pr-book-cover) 46%, var(--pr-book-cover-deep)) !important;
  box-shadow:
    9px 9px 0 -3px color-mix(in srgb, var(--pr-book-cream) 76%, var(--pr-book-rule)),
    14px 14px 0 -7px color-mix(in srgb, var(--pr-book-cream) 54%, var(--pr-book-rule)),
    0 0 0 100vmax color-mix(in srgb, var(--pr-book-cover-deep) 88%, transparent),
    0 36px 80px -24px rgba(0, 0, 0, .9);
  overflow: hidden;
}
/* Unlike the intro/end cards, this recorder-owned cover is absolutely
   positioned from the stage centre. Its animation must retain the
   translate(-50%, -50%) anchor at every keyframe: borrowing
   prBookCoverArrive ended at transform:none, leaving the cover's TOP-LEFT at
   50%/50% and clipping its lower-right half in recorded video. */
body.presenting.pr-chrome-book #prTitleCard.show {
  animation: prBookTitleCoverArrive 720ms cubic-bezier(.2, .78, .2, 1) both;
}
@keyframes prBookTitleCoverArrive {
  from {
    opacity: 0;
    transform: translate(-50%, calc(-50% + 24px)) rotateY(-7deg) rotateZ(-1deg) scale(.965);
  }
  to { opacity: 1; transform: translate(-50%, -50%); }
}
body.presenting.pr-chrome-book #prTitleCard #prTitleCardTail { display: contents; }
body.presenting.pr-chrome-book #prTitleCard #prTitleCardLead { display: none; }
body.presenting.pr-chrome-book #prTitleCardHeader {
  order: 0;
  margin: 14px 0 15px;
  max-width: 94%;
  color: var(--pr-book-gold) !important;
  font: 700 10.5px ui-monospace, 'SF Mono', Menlo, monospace !important;
  letter-spacing: .2em;
  overflow-wrap: anywhere;
}
body.presenting.pr-chrome-book #prTitleCardTitle {
  order: 1;
  max-width: 94%;
  color: var(--pr-book-cover-ink) !important;
  font-family: var(--pr-book-heading-font) !important;
  font-size: clamp(29px, 4.4vw, 50px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.022em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.pr-book-index-page h3:focus {
  outline: none;
  box-shadow: -4px 0 0 color-mix(in srgb, var(--pr-book-accent) 72%, transparent);
}
body.presenting.pr-chrome-book #prTitleCardImgFrame {
  order: 2;
  flex: 1 1 auto;
  width: min(76%, 340px);
  height: auto;
  min-height: 0;
  margin: 24px auto 14px;
}
body.presenting.pr-chrome-book #prTitleCardImg {
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 56%, transparent);
  border-radius: 6px;
  filter: drop-shadow(0 13px 14px color-mix(in srgb, var(--pr-book-cover-deep) 48%, transparent));
}
body.presenting.pr-chrome-book #prTitleCardFooter {
  order: 3;
  margin-top: auto;
  max-width: 88%;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 76%, transparent) !important;
  font-family: var(--pr-book-body-font) !important;
  font-size: clamp(12px, 1.1vw, 15px);
  font-style: italic;
  overflow-wrap: anywhere;
}
body.presenting.pr-chrome-book #prTitleCardBrand {
  order: 4;
  margin: 13px 0 0;
  color: var(--pr-book-gold);
  font-size: 15px;
}
body.presenting.pr-chrome-book #prTitleCard .eng-strip--title { display: none; }
body.presenting.pr-chrome-book #prTitleCard .pr-bi-spark,
body.presenting.pr-chrome-book #prTitleCard > .pr-brandin-glow { display: none; }

body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover {
  width: auto;
  min-width: 0;
  height: min(86%, 720px);
  max-width: calc(100% - 34px);
  aspect-ratio: var(--pr-book-custom-cover-ratio, 2 / 3);
  padding: 0 !important;
  background: #050816 !important;
}
body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover::before { content: none; }
body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover > :not(#prTitleCardImgFrame) { display: none !important; }
body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover #prTitleCardImgFrame {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: grid !important;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
}
body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover #prTitleCardImg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border: 0;
  border-radius: inherit;
  background: #050816;
  filter: none;
}

/* The measured safe rectangle normally fits at the publishing style's full
   hierarchy. On a short viewport or an unusually long authored title, this
   compact rhythm is the second pass used by fitNotebookDomCover: it recovers
   vertical room without hiding a field, scrolling a faux cover, or moving
   any content back across the decorative rule. */
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-eyebrow,
body.presenting.pr-chrome-book #prTitleCard.pr-book-cover-fit-tight #prTitleCardHeader {
  margin-top: 3px;
  margin-bottom: 7px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-title::after {
  margin-top: 9px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-meta {
  margin-top: 8px;
  gap: 5px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-meta span {
  padding: 3px 9px;
  font-size: 10px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-play {
  margin-top: 12px;
  padding: 9px 22px 9px 16px;
  font-size: 14px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-play-ico {
  width: 27px;
  height: 27px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-row {
  margin-top: 8px;
  gap: 6px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-intro-foot {
  margin-top: 8px;
  font-size: 9.5px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-brandin {
  gap: 2px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-brandin .pr-intro-mark {
  width: 29px;
  height: 29px;
}
body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-cover-fit-tight .pr-brandin-word {
  font-size: 14px;
}
body.presenting.pr-chrome-book #prTitleCard.pr-book-cover-fit-tight #prTitleCardImgFrame {
  margin-top: 10px;
  margin-bottom: 8px;
}
body.presenting.pr-chrome-book #prTitleCard.pr-book-cover-fit-tight #prTitleCardBrand {
  margin-top: 7px;
  font-size: 13px;
}

/* Back cover: a distinct closing colophon. The Index belongs only in the
   front matter; the last cover thanks the reader and offers honest next
   actions without adding collection or faux controls. */
body.presenting.pr-chrome-book #prEnd .pr-end-card {
  align-items: stretch;
  text-align: left;
  padding-bottom: 46px;
  animation: prBookBackClose var(--pr-book-turn-ms, 500ms) cubic-bezier(.2, .78, .2, 1) both;
}
@keyframes prBookBackClose {
  from { opacity: 0; transform: rotateY(84deg) translateX(4%); filter: brightness(.72); }
  to   { opacity: 1; transform: none; filter: none; }
}
body.presenting.pr-chrome-book #prEnd .pr-end-mark { display: none; }
body.presenting.pr-chrome-book #prEnd .pr-end-title {
  margin: 14px 0 0;
  color: var(--pr-book-cover-ink);
  font-family: var(--pr-book-heading-font) !important;
  font-size: clamp(26px, 4.2vh, 43px);
  line-height: 1.08;
  text-align: center;
  text-wrap: balance;
}
body.presenting.pr-chrome-book #prEnd .pr-end-title::after {
  content: "";
  display: block;
  width: 64px;
  height: 2px;
  margin: 17px auto 0;
  background: var(--pr-book-gold);
}
body.presenting.pr-chrome-book #prEnd .pr-end-sub {
  margin-top: 12px;
  color: var(--pr-book-gold);
  font: 700 10.5px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .1em;
  text-align: center;
  text-transform: uppercase;
}
body.presenting.pr-chrome-book #prEnd .pr-end-takeaways {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: none;
  margin: 22px 0 8px;
  overflow: hidden;
}
body.presenting.pr-chrome-book #prEnd .pr-end-h {
  margin-bottom: 10px;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 82%, transparent);
  font: 700 10px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .18em;
  text-align: center;
}
body.presenting.pr-chrome-book #prEndTakeList {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3px 20px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: book-page;
}
body.presenting.pr-chrome-book #prEndTakeList:has(li:nth-child(10)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.presenting.pr-chrome-book #prEndTakeList li {
  counter-increment: book-page;
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
  padding: 5px 0;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 90%, transparent);
  font-family: var(--pr-book-body-font);
  font-size: 12.5px;
  line-height: 1.25;
  opacity: 0;
  animation: prBookIndexIn 360ms cubic-bezier(.2, .75, .25, 1) calc(420ms + var(--book-i, 0) * 48ms) forwards;
}
body.presenting.pr-chrome-book #prEndTakeList li::before {
  content: counter(book-page, decimal-leading-zero);
  flex: none;
  color: var(--pr-book-gold);
  font: 650 9px ui-monospace, 'SF Mono', Menlo, monospace;
}
body.presenting.pr-chrome-book #prEndTakeList li span {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px dotted color-mix(in srgb, var(--pr-book-gold) 34%, transparent);
}
body.presenting.pr-chrome-book #prEndTakeList li b {
  flex: none;
  color: var(--pr-book-gold);
  font: 650 9.5px ui-monospace, 'SF Mono', Menlo, monospace;
}
@keyframes prBookIndexIn {
  from { opacity: 0; transform: translateX(-7px); }
  to { opacity: 1; transform: none; }
}
body.presenting.pr-chrome-book #prEnd .pr-end-share { justify-content: center; }
body.presenting.pr-chrome-book #prEnd .pr-end-ctas {
  flex: 0 0 auto;
  margin-top: 10px;
  gap: 6px;
}
body.presenting.pr-chrome-book #prEnd .pr-end-btn {
  color: color-mix(in srgb, var(--pr-book-cover-ink) 90%, transparent);
  background: color-mix(in srgb, var(--pr-book-cover-deep) 24%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-gold) 32%, transparent);
  padding: 7px 11px;
  font-size: 11.5px;
}
body.presenting.pr-chrome-book #prEnd .pr-end-primary {
  color: var(--pr-book-cover-deep);
  background: linear-gradient(180deg, color-mix(in srgb, var(--pr-book-gold) 68%, white), var(--pr-book-gold));
}
body.presenting.pr-chrome-book #prEnd .pr-end-brand {
  margin-top: 14px;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 54%, transparent);
  font-size: 10px;
  text-align: center;
}
body.presenting.pr-chrome-book #prBookCloseActions:not([hidden]) {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  margin: 22px 0 8px;
  text-align: center;
}
body.presenting.pr-chrome-book #prBookCloseActions > p {
  margin: 0;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 82%, transparent);
  font: italic clamp(14px, 1.5vw, 18px)/1.45 var(--pr-book-body-font);
}
.pr-book-close-action-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
body.presenting.pr-chrome-book .pr-book-close-action-row :is(a, button) {
  display: flex;
  min-width: 0;
  min-height: 76px;
  box-sizing: border-box;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 11px 8px;
  color: var(--pr-book-cover-ink);
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 38%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--pr-book-cover-deep) 25%, transparent);
  font: inherit;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
body.presenting.pr-chrome-book .pr-book-close-action-row :is(a, button):is(:hover, :focus-visible) {
  border-color: var(--pr-book-gold);
  background: color-mix(in srgb, var(--pr-book-cover-deep) 42%, transparent);
  outline: none;
  transform: translateY(-1px);
}
body.presenting.pr-chrome-book .pr-book-close-action-row b {
  color: var(--pr-book-gold);
  font: 750 12px ui-monospace, 'SF Mono', Menlo, monospace;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body.presenting.pr-chrome-book .pr-book-close-action-row span {
  color: color-mix(in srgb, var(--pr-book-cover-ink) 72%, transparent);
  font: 12px/1.25 var(--pr-book-body-font);
}
body.presenting.pr-chrome-book #prEnd[data-book-close="1"] #prEndTakeaways { display: none !important; }
body.presenting.pr-chrome-book #prEnd[data-book-close="1"] :is(#prEndQa, #prEndEdit, #prEndExplore) { display: none; }

/* The reading chrome uses ink and paper, not the generic cinema glass. */
body.presenting.pr-chrome-book:not(.pr-zen) #prTvHead {
  background: linear-gradient(90deg, var(--pr-book-cover-deep), var(--pr-book-cover) 52%, var(--pr-book-cover-deep));
  border-color: color-mix(in srgb, var(--pr-book-gold) 50%, transparent);
  box-shadow: 0 8px 22px -17px #000;
}
body.presenting.pr-chrome-book #prTvTitle,
body.presenting.pr-chrome-book #prTvStep { color: var(--pr-book-gold); }
body.presenting.pr-chrome-book #presentBar {
  background: color-mix(in srgb, var(--pr-book-cover-deep) 90%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-gold) 34%, transparent);
}
body.presenting.pr-chrome-book #prPlay {
  color: var(--pr-book-cover-deep);
  background: linear-gradient(180deg, color-mix(in srgb, var(--pr-book-gold) 68%, white), var(--pr-book-gold));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pr-book-gold) 17%, transparent), 0 10px 26px -12px color-mix(in srgb, var(--pr-book-cover-deep) 76%, black);
}
body.presenting.pr-chrome-book #prNarration {
  color: var(--pr-book-ink) !important;
  border: 1px solid color-mix(in srgb, var(--pr-book-rule) 58%, var(--pr-book-cream)) !important;
  border-radius: 4px 12px 12px 5px;
  background:
    repeating-linear-gradient(0deg, transparent 0 25px, color-mix(in srgb, var(--pr-book-rule) 12%, transparent) 26px 27px),
    linear-gradient(100deg,
      color-mix(in srgb, var(--pr-book-cream) 86%, var(--pr-book-rule)),
      color-mix(in srgb, var(--pr-book-cream) 92%, white) 9%,
      color-mix(in srgb, var(--pr-book-cream) 94%, white)) !important;
  box-shadow: 8px 13px 28px -20px rgba(0, 0, 0, .82) !important;
}
body.presenting.pr-chrome-book #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-book #prNarrationText,
body.presenting.pr-chrome-book #prNoteTitle,
body.presenting.pr-chrome-book #prNoteStep,
body.presenting.pr-chrome-book #prNarrationHead,
body.presenting.pr-chrome-book #prCaption,
body.presenting.pr-chrome-book #prSubtitle,
body.presenting.pr-chrome-book #prWhyDock,
body.presenting.pr-chrome-book #prZenTitleText,
body.presenting.pr-chrome-book #prStepTime {
  font-family: var(--pr-book-body-font) !important;
}
body.presenting.pr-chrome-book #prNarration[data-note-style] #prNarrationText,
body.presenting.pr-chrome-book #prNarrationText {
  color: var(--pr-book-ink) !important;
  background: color-mix(in srgb, var(--pr-book-cream) 74%, transparent) !important;
  border-color: color-mix(in srgb, var(--pr-book-rule) 24%, transparent) !important;
}
body.presenting.pr-chrome-book #prNoteTitle {
  color: var(--pr-book-ink) !important;
  font-family: var(--pr-book-heading-font) !important;
}
body.presenting.pr-chrome-book #prNoteStep {
  color: var(--pr-book-accent) !important;
  background: color-mix(in srgb, var(--pr-book-cream) 92%, white) !important;
  border: 1.5px solid var(--pr-book-rule) !important;
  border-radius: 7px 3px 8px 3px / 3px 8px 3px 7px !important;
  padding: 2px 9px !important;
}
body.presenting.pr-chrome-book #prWhyDock:not([hidden]),
body.pr-hand.pr-zen.presenting.pr-chrome-book:not(.pr-notes-bottom):not(.pr-guide-collapsed) #prWhyDock:not([hidden]) {
  color: var(--pr-book-ink) !important;
  background: color-mix(in srgb, var(--pr-book-cream) 68%, var(--pr-book-gold)) !important;
  border: 1px solid color-mix(in srgb, var(--pr-book-rule) 72%, var(--pr-book-gold)) !important;
  border-radius: 3px 7px 4px 6px !important;
  box-shadow: 2px 4px 8px color-mix(in srgb, var(--pr-book-ink) 18%, transparent) !important;
  transform: rotate(.45deg);
}
body.presenting.pr-chrome-book #prSubtitle,
body.presenting.pr-chrome-book #prCaption {
  color: var(--pr-book-ink);
  background: color-mix(in srgb, var(--pr-book-cream) 95%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-accent) 52%, transparent);
  border-left-color: var(--pr-book-accent);
  box-shadow: 0 14px 28px -20px #000;
}

/* Six publishing traditions share the mechanics above but not the same
   physical object. These recipes deliberately alter cover composition,
   binding, stock and furniture—not merely palette—while the authored ink
   remains untouched and readable. */
body.presenting.pr-chrome-book[data-book-style="literary"] {
  --pr-book-spread-paper:
    radial-gradient(76% 120% at 23% 46%, color-mix(in srgb, white 18%, transparent), transparent 72%),
    radial-gradient(76% 120% at 77% 46%, color-mix(in srgb, white 20%, transparent), transparent 72%),
    repeating-linear-gradient(1deg, color-mix(in srgb, var(--pr-book-ink) 1.8%, transparent) 0 1px, transparent 1px 6px),
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 82%, var(--pr-book-rule)), var(--pr-book-cream) 7% 43%,
      color-mix(in srgb, var(--pr-book-cream) 70%, var(--pr-book-ink)) 49.7%,
      color-mix(in srgb, var(--pr-book-cream) 96%, white) 55%, var(--pr-book-cream) 93%,
      color-mix(in srgb, var(--pr-book-cream) 80%, var(--pr-book-rule)));
}
body.presenting.pr-chrome-book[data-book-style="textbook"] {
  --pr-book-spread-paper:
    repeating-linear-gradient(0deg, transparent 0 31px, color-mix(in srgb, var(--pr-book-rule) 8%, transparent) 31px 32px),
    repeating-linear-gradient(90deg, transparent 0 47px, color-mix(in srgb, var(--pr-book-rule) 5%, transparent) 47px 48px),
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 90%, var(--pr-book-rule)), var(--pr-book-cream) 5% 44%,
      color-mix(in srgb, var(--pr-book-ink) 12%, var(--pr-book-cream)) 49.8%, var(--pr-book-cream) 56% 95%,
      color-mix(in srgb, var(--pr-book-cream) 90%, var(--pr-book-rule)));
}
body.presenting.pr-chrome-book[data-book-style="graphic"] {
  --pr-book-spread-paper:
    radial-gradient(circle, color-mix(in srgb, var(--pr-book-ink) 5%, transparent) 0 1px, transparent 1.2px) 0 0 / 16px 16px,
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 84%, var(--pr-book-rule)), var(--pr-book-cream) 5% 44%,
      color-mix(in srgb, var(--pr-book-ink) 18%, var(--pr-book-cream)) 49.85%, var(--pr-book-cream) 56% 95%,
      color-mix(in srgb, var(--pr-book-cream) 84%, var(--pr-book-rule)));
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] {
  --pr-book-spread-paper:
    radial-gradient(ellipse at 9% 82%, transparent 0 22px, color-mix(in srgb, var(--pr-book-rule) 8%, transparent) 23px 24px, transparent 25px 35px, color-mix(in srgb, var(--pr-book-rule) 6%, transparent) 36px 37px, transparent 38px),
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-ink) 2.2%, transparent) 0 1px, transparent 1px 7px),
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 78%, var(--pr-book-rule)), var(--pr-book-cream) 7% 43%,
      color-mix(in srgb, var(--pr-book-ink) 16%, var(--pr-book-cream)) 49.8%, var(--pr-book-cream) 57% 93%,
      color-mix(in srgb, var(--pr-book-cream) 78%, var(--pr-book-rule)));
}
body.presenting.pr-chrome-book[data-book-style="monograph"] {
  --pr-book-spread-paper:
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 91%, var(--pr-book-rule)), var(--pr-book-cream) 4% 46%,
      color-mix(in srgb, var(--pr-book-ink) 11%, var(--pr-book-cream)) 49.9%, var(--pr-book-cream) 54% 96%,
      color-mix(in srgb, var(--pr-book-cream) 91%, var(--pr-book-rule)));
}
body.presenting.pr-chrome-book[data-book-style="handbook"] {
  --pr-book-spread-paper:
    repeating-linear-gradient(0deg, transparent 0 30px,
      color-mix(in srgb, var(--pr-book-rule) 13%, transparent) 30px 31px),
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cream) 84%, var(--pr-book-rule)), var(--pr-book-cream) 5% 44%,
      color-mix(in srgb, var(--pr-book-ink) 17%, var(--pr-book-cream)) 49.8%,
      color-mix(in srgb, var(--pr-book-cream) 97%, white) 55% 95%,
      color-mix(in srgb, var(--pr-book-cream) 84%, var(--pr-book-rule)));
}

/* A sewn crease, case headband, saddle staples, field spiral, and lay-flat
   glue line respectively. The supplied reference most directly informs the
   Literary sewn/ribbon treatment; metal loops are no longer universal. */
body.presenting.pr-chrome-book[data-book-style="literary"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(24px, 3.3%, 38px);
  background:
    radial-gradient(circle, color-mix(in srgb, var(--pr-book-ribbon) 76%, var(--pr-book-ink)) 0 2px, transparent 2.5px)
      center 11px / 7px 28px repeat-y,
    linear-gradient(90deg, transparent, color-mix(in srgb, var(--pr-book-ink) 20%, transparent) 43%,
      color-mix(in srgb, var(--pr-book-ink) 42%, transparent) 49%, color-mix(in srgb, white 25%, transparent) 52%, transparent);
}
body.presenting.pr-chrome-book[data-book-style="textbook"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(20px, 2.8%, 32px);
  background:
    repeating-linear-gradient(0deg, var(--pr-book-accent) 0 5px, var(--pr-book-cream) 5px 10px, var(--pr-book-cover) 10px 15px) center / 5px 100% no-repeat,
    linear-gradient(90deg, transparent, color-mix(in srgb, var(--pr-book-ink) 30%, transparent) 48%, rgba(255,255,255,.22) 53%, transparent);
}
body.presenting.pr-chrome-book[data-book-style="graphic"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(18px, 2.4%, 29px);
  background:
    radial-gradient(ellipse at center, transparent 38%, color-mix(in srgb, var(--pr-book-rule) 70%, #777) 42% 48%, transparent 52%) center 34% / 17px 24px no-repeat,
    radial-gradient(ellipse at center, transparent 38%, color-mix(in srgb, var(--pr-book-rule) 70%, #777) 42% 48%, transparent 52%) center 66% / 17px 24px no-repeat,
    linear-gradient(90deg, transparent, color-mix(in srgb, var(--pr-book-ink) 44%, transparent) 48%, rgba(255,255,255,.18) 53%, transparent);
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(27px, 4.8%, 54px);
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(13px, 1.7%, 21px);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--pr-book-ink) 25%, transparent) 45%,
    color-mix(in srgb, var(--pr-book-ink) 38%, transparent) 49%, rgba(255,255,255,.16) 53%, transparent);
  filter: none;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#svgHost, #prBookIndex)::before {
  width: clamp(17px, 2.2%, 27px);
  background:
    repeating-linear-gradient(0deg, transparent 0 12px,
      color-mix(in srgb, var(--pr-book-ribbon) 86%, var(--pr-book-ink)) 12px 16px,
      transparent 16px 25px) center / 3px 100% no-repeat,
    linear-gradient(90deg, transparent,
      color-mix(in srgb, var(--pr-book-ink) 28%, transparent) 45%,
      color-mix(in srgb, var(--pr-book-ink) 42%, transparent) 49%,
      color-mix(in srgb, white 32%, transparent) 53%, transparent);
  filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--pr-book-ink) 34%, transparent));
}

body.presenting.pr-chrome-book[data-book-style="textbook"] .pr-book-index-page {
  background:
    linear-gradient(90deg, var(--pr-book-accent) 0 4px, transparent 4px),
    repeating-linear-gradient(0deg, transparent 0 31px, color-mix(in srgb, var(--pr-book-rule) 9%, transparent) 31px 32px),
    var(--pr-book-cream);
}
body.presenting.pr-chrome-book[data-book-style="graphic"] .pr-book-index-page {
  background:
    radial-gradient(circle, color-mix(in srgb, var(--pr-book-ink) 6%, transparent) 0 1px, transparent 1.2px) 0 0 / 16px 16px,
    var(--pr-book-cream);
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] .pr-book-index-page {
  background:
    radial-gradient(ellipse at 8% 88%, transparent 0 24px, color-mix(in srgb, var(--pr-book-rule) 9%, transparent) 25px 26px, transparent 27px 38px, color-mix(in srgb, var(--pr-book-rule) 7%, transparent) 39px 40px, transparent 41px),
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-ink) 2.2%, transparent) 0 1px, transparent 1px 7px),
    var(--pr-book-cream);
}
body.presenting.pr-chrome-book[data-book-style="monograph"] .pr-book-index-page {
  background: var(--pr-book-cream);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-page {
  background:
    repeating-linear-gradient(0deg, transparent 0 30px,
      color-mix(in srgb, var(--pr-book-rule) 13%, transparent) 30px 31px),
    var(--pr-book-cream);
}
body.presenting.pr-chrome-book[data-book-style="graphic"] .pr-book-index-kicker {
  letter-spacing: .08em;
  text-transform: uppercase;
}
body.presenting.pr-chrome-book[data-book-style="graphic"] .pr-book-index-kicker {
  display: inline-block;
  padding: 4px 7px;
  color: var(--pr-book-cream);
  background: var(--pr-book-accent);
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(.pr-book-running, .pr-book-index-kicker) {
  letter-spacing: .24em;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(.pr-book-running, .pr-book-index-kicker) {
  font-family: var(--pr-book-body-font);
  letter-spacing: .045em;
  text-transform: none;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-kicker {
  display: inline-block;
  width: max-content;
  padding: 2px 8px 3px;
  color: var(--pr-book-ink);
  border-radius: 4px 8px 5px 7px;
  background: color-mix(in srgb, var(--pr-book-gold) 58%, transparent);
  transform: rotate(-.7deg);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-page h3::after {
  content: "";
  display: block;
  width: min(74%, 230px);
  height: 7px;
  margin-top: 10px;
  border-radius: 999px 70% 999px 55%;
  background: color-mix(in srgb, var(--pr-book-gold) 70%, transparent);
  transform: rotate(-1deg);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-page h3 {
  margin-bottom: 15px;
  font-size: clamp(24px, 2.75vw, 38px);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-page h3::after {
  height: 5px;
  margin-top: 6px;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-list li {
  padding-block: 4px;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] .pr-book-ribbon { width: 12px; left: calc(50% - 6px); height: 22%; opacity: .68; }
body.presenting.pr-chrome-book[data-book-style="textbook"] .pr-book-ribbon { height: 34%; }
body.presenting.pr-chrome-book[data-book-style="graphic"] .pr-book-ribbon { width: 16px; left: calc(50% - 8px); height: 27%; }
body.presenting.pr-chrome-book[data-book-style="fieldguide"] .pr-book-ribbon { left: calc(50% + 9px); height: 31%; }
body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-ribbon { width: 11px; left: calc(50% - 5px); height: 24%; opacity: .82; }

/* Cover geometry: cloth classic, academic chapter grid, cropped comic panel,
   expedition buckram label, offset gallery block and soft-touch handbook.
   Applied equally to the opening cover, timed title cover and closing cover. */
body.presenting.pr-chrome-book[data-book-style="textbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard) {
  border-radius: 5px 14px 14px 5px;
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-deep) 72%, black) 0 11%, var(--pr-book-accent) 11% 13%, transparent 13%),
    repeating-linear-gradient(0deg, color-mix(in srgb, var(--pr-book-cover-ink) 4%, transparent) 0 1px, transparent 1px 36px),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--pr-book-cover-ink) 3%, transparent) 0 1px, transparent 1px 46px),
    linear-gradient(150deg, color-mix(in srgb, var(--pr-book-cover) 88%, white), var(--pr-book-cover) 56%, var(--pr-book-cover-deep)) !important;
}
body.presenting.pr-chrome-book[data-book-style="textbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::before {
  inset: 7% 6.5% 7% 16%;
  border-width: 2px 1px 1px 7px;
  border-radius: 2px 9px 9px 2px;
}
body.presenting.pr-chrome-book[data-book-style="textbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: "EDITION 01";
  position: absolute; z-index: 0; right: 8%; bottom: 7%;
  color: color-mix(in srgb, var(--pr-book-cover-ink) 52%, transparent);
  font: 700 9px ui-monospace, 'SF Mono', Menlo, monospace; letter-spacing: .18em;
}
body.presenting.pr-chrome-book[data-book-style="graphic"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard) {
  border-width: 2px;
  border-radius: 3px 10px 10px 3px;
  background:
    linear-gradient(146deg, transparent 0 57%, color-mix(in srgb, var(--pr-book-accent) 88%, transparent) 57.5% 72%, transparent 72.5%),
    radial-gradient(circle, color-mix(in srgb, var(--pr-book-cover-ink) 10%, transparent) 0 1.4px, transparent 1.6px) 0 0 / 14px 14px,
    linear-gradient(30deg, color-mix(in srgb, var(--pr-book-cover) 88%, white), var(--pr-book-cover) 48%, var(--pr-book-cover-deep)) !important;
}
body.presenting.pr-chrome-book[data-book-style="graphic"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::before {
  inset: 4.5%; border-width: 4px; border-radius: 1px 7px 7px 1px;
}
body.presenting.pr-chrome-book[data-book-style="graphic"] :is(#prIntro .pr-intro-title, #prEnd .pr-end-title, #prTitleCardTitle) {
  text-transform: uppercase; letter-spacing: .015em;
}
body.presenting.pr-chrome-book[data-book-style="graphic"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: ""; position: absolute; z-index: 0; right: 7%; bottom: 7%; width: 72px; height: 72px;
  border: 3px solid color-mix(in srgb, var(--pr-book-gold) 70%, transparent); border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--pr-book-cover-ink) 22%, transparent) 0 2px, transparent 2.2px) 0 0 / 10px 10px;
  transform: rotate(-8deg);
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard) {
  border: 2px solid color-mix(in srgb, var(--pr-book-gold) 46%, var(--pr-book-cover-deep));
  border-radius: 8px 16px 16px 8px;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--pr-book-gold) 38%, transparent) 0 18px, transparent 18px) top left / 48px 48px no-repeat,
    linear-gradient(225deg, color-mix(in srgb, var(--pr-book-gold) 30%, transparent) 0 18px, transparent 18px) top right / 48px 48px no-repeat,
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-cover-ink) 4%, transparent) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(92deg, color-mix(in srgb, var(--pr-book-cover-deep) 9%, transparent) 0 1px, transparent 1px 9px),
    linear-gradient(145deg, color-mix(in srgb, var(--pr-book-cover) 84%, white), var(--pr-book-cover) 48%, var(--pr-book-cover-deep)) !important;
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::before {
  inset: 13% 9% 12%;
  border: 1px dashed color-mix(in srgb, var(--pr-book-gold) 78%, transparent);
  background: color-mix(in srgb, var(--pr-book-cream) 7%, transparent);
}
body.presenting.pr-chrome-book[data-book-style="fieldguide"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: "N  ·  01"; position: absolute; z-index: 0; right: 10%; bottom: 8%;
  width: 52px; height: 52px; display: grid; place-items: center;
  color: var(--pr-book-gold); border: 1px solid color-mix(in srgb, var(--pr-book-gold) 68%, transparent); border-radius: 50%;
  font: 700 8px ui-monospace, 'SF Mono', Menlo, monospace; letter-spacing: .08em;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard) {
  align-items: flex-start !important;
  text-align: left;
  border-color: color-mix(in srgb, var(--pr-book-cover-ink) 14%, transparent);
  border-radius: 3px 12px 12px 3px;
  background:
    linear-gradient(90deg, var(--pr-book-cover-deep) 0 15%, var(--pr-book-gold) 15% 15.7%, transparent 15.7%),
    linear-gradient(155deg, color-mix(in srgb, var(--pr-book-cover) 94%, white), var(--pr-book-cover) 64%, var(--pr-book-cover-deep)) !important;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::before {
  inset: 8% 8% 18% 21%; border: 0; border-top: 1px solid var(--pr-book-gold); border-left: 1px solid var(--pr-book-gold); border-radius: 0;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(#prIntro .pr-intro-title, #prEnd .pr-end-title, #prTitleCardTitle) {
  align-self: stretch; max-width: 100%; text-align: left; letter-spacing: .04em;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] #prIntro .pr-intro-title::after,
body.presenting.pr-chrome-book[data-book-style="monograph"] #prEnd .pr-end-title::after {
  margin-left: 0; width: 42%;
}
body.presenting.pr-chrome-book[data-book-style="monograph"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: ""; position: absolute; z-index: 0; right: 8%; bottom: 8%; width: 28%; height: 9px; background: var(--pr-book-gold);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard) {
  align-items: flex-start !important;
  text-align: left;
  border-color: color-mix(in srgb, var(--pr-book-gold) 52%, transparent);
  border-radius: 8px 20px 20px 8px;
  background:
    linear-gradient(90deg, var(--pr-book-cover-deep) 0 13.5%, var(--pr-book-accent) 13.5% 15.2%, transparent 15.2%),
    linear-gradient(154deg, transparent 0 72%, color-mix(in srgb, var(--pr-book-gold) 24%, transparent) 72.3% 76.5%, transparent 76.8%),
    repeating-linear-gradient(2deg, color-mix(in srgb, var(--pr-book-cover-ink) 3.5%, transparent) 0 1px, transparent 1px 8px),
    linear-gradient(145deg, color-mix(in srgb, var(--pr-book-cover) 90%, white), var(--pr-book-cover) 54%, var(--pr-book-cover-deep)) !important;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::before {
  inset: 7% 7% 13% 18%;
  border: 0;
  border-top: 1px solid color-mix(in srgb, var(--pr-book-gold) 78%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--pr-book-gold) 58%, transparent);
  border-left: 5px solid var(--pr-book-accent);
  border-radius: 1px 12px 12px 2px;
  box-shadow: none;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: "";
  position: absolute;
  z-index: 0;
  right: 7%;
  bottom: 7.5%;
  width: 29%;
  height: 11px;
  border-radius: 999px 62% 999px 48%;
  background: color-mix(in srgb, var(--pr-book-gold) 82%, transparent);
  transform: rotate(-3deg);
  box-shadow: 0 8px 0 -3px color-mix(in srgb, var(--pr-book-accent) 78%, transparent);
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#prIntro .pr-intro-title, #prEnd .pr-end-title, #prTitleCardTitle) {
  align-self: stretch;
  max-width: 100%;
  text-align: left;
  letter-spacing: .005em;
}
body.presenting.pr-chrome-book[data-book-style="handbook"] :is(#prIntro .pr-intro-title, #prEnd .pr-end-title, #prTitleCardTitle)::after {
  content: "";
  display: block;
  width: 48%;
  height: 8px;
  margin-left: 0;
  border-radius: 999px 60% 999px 52%;
  background: color-mix(in srgb, var(--pr-book-gold) 76%, transparent);
  transform: rotate(-1deg);
  box-shadow: none;
}
body.presenting.pr-chrome-book[data-book-style="literary"] :is(#prIntro .pr-intro-card, #prEnd .pr-end-card, #prTitleCard)::after {
  content: ""; position: absolute; z-index: 0; right: 10%; bottom: 9%; width: 30px; height: 30px;
  border: 1px solid color-mix(in srgb, var(--pr-book-gold) 56%, transparent); transform: rotate(45deg);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--pr-book-gold) 8%, transparent);
}

/* Keep the Index as one open object at every width. Pagination is controlled
   by the book state machine, never by an inner scroll region. */
@media (max-width: 900px) {
  .pr-book-index-page {
    --pr-book-page-inset: clamp(27px, 4.5vw, 42px);
  }
  .pr-book-index-list li { gap: 6px; padding-block: 6px; }
}

@media (max-width: 720px), (max-height: 620px) {
  body.presenting.pr-chrome-book #prBookIndex {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    overflow: visible;
  }
  body.presenting.pr-chrome-book .pr-book-index-page {
    min-height: 0;
  }
  body.presenting.pr-chrome-book .pr-book-index-foreword {
    border-radius: 14px 2px 2px 14px;
  }
  body.presenting.pr-chrome-book .pr-book-index-contents {
    border-radius: 2px 14px 14px 2px;
  }
  .pr-book-index-page {
    --pr-book-page-inset: clamp(13px, 3.3vw, 25px);
    padding-top: 43px;
    padding-bottom: 28px;
  }
  .pr-book-running { top: 15px; left: 15px; right: 15px; font-size: 7px; }
  .pr-book-index-page h3 { margin-bottom: 12px; font-size: clamp(17px, 4.5vw, 27px); }
  .pr-book-index-kicker { font-size: 7.5px; }
  .pr-book-index-list { max-height: calc(100% - 68px); }
  .pr-book-index-list li { gap: 4px; padding-block: 4px; font-size: clamp(8.5px, 2.25vw, 12px); }
  .pr-book-index-list li::before, .pr-book-index-list li b { font-size: 7px; }
  .pr-book-index-leaf .pr-book-index-list {
    height: 100%;
    max-height: none;
  }
  .pr-book-index-leaf .pr-book-index-list li {
    padding-block: 2px;
    font-size: clamp(9px, 2.35vw, 13px);
  }
  .pr-book-index-leaf .pr-book-index-list li::before,
  .pr-book-index-leaf .pr-book-index-list li b {
    font-size: clamp(7px, 1.8vw, 10px);
  }
  .pr-book-index-position { display: none; }
  /* Handbook owns a deliberately larger desktop handwriting scale. Match
     that selector strength here so a short landscape screen still gets the
     same compact, fully contained Index measure as every other book style. */
  body.presenting.pr-chrome-book[data-book-style="handbook"] .pr-book-index-page h3 {
    margin-bottom: 12px;
    font-size: clamp(17px, 4.5vw, 27px);
  }
}

@media (max-height: 620px) {
  .pr-book-index-page { padding-top: 42px; padding-bottom: 28px; }
  .pr-book-running { top: 14px; }
  .pr-book-index-page h3 { margin-bottom: 13px; }
  .pr-book-index-list li { padding-block: 4px; }
  .pr-book-index-continue { padding-block: 7px; }
}

@media (max-width: 720px), (max-height: 620px) {
  body.presenting.pr-chrome-book #prIntro,
  body.presenting.pr-chrome-book #prEnd { padding: 12px; }
  body.presenting.pr-chrome-book #prIntro .pr-intro-card,
  body.presenting.pr-chrome-book #prEnd .pr-end-card {
    width: min(94vw, 460px);
    min-width: 0;
    height: min(94vh, 680px);
    max-height: 94vh;
    padding: 34px 25px 24px;
  }
  body.presenting.pr-chrome-book #prEnd .pr-end-card { padding-bottom: 38px; }
  body.presenting.pr-chrome-book #prIntro .pr-intro-title { font-size: clamp(24px, 7vw, 38px); }
  body.presenting.pr-chrome-book #prIntro .pr-brandin { display: none; }
  body.presenting.pr-chrome-book #prIntro .pr-intro-foot { margin-top: 12px; }
  body.presenting.pr-chrome-book #prTitleCard {
    width: min(88%, 460px);
    min-width: 0;
    height: min(86%, 680px);
    padding: 34px 26px 25px;
  }
  body.presenting.pr-chrome-book #prIntro .pr-intro-card.pr-book-custom-cover,
  body.presenting.pr-chrome-book #prTitleCard.pr-book-custom-cover {
    width: auto;
    height: min(94vh, 680px);
    padding: 0 !important;
  }
  body.presenting.pr-chrome-book #prEndTakeList:has(li:nth-child(10)) { grid-template-columns: 1fr; }
  .pr-book-close-action-row { grid-template-columns: 1fr; gap: 5px; }
  body.presenting.pr-chrome-book .pr-book-close-action-row :is(a, button) {
    min-height: 48px;
    flex-direction: row;
    justify-content: space-between;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.presenting.pr-chrome-book .pr-book-page-turn,
  body.presenting.pr-chrome-book .pr-book-page-stay { animation: none !important; display: none !important; }
  body.presenting.pr-chrome-book .pr-book-page-turn::after { animation: none !important; }
  body.presenting.pr-chrome-book #prIntro .pr-intro-card,
  body.presenting.pr-chrome-book #prIntro.pr-book-opening .pr-intro-card,
  body.presenting.pr-chrome-book #prIntro.pr-book-index-leaving .pr-book-index-contents,
  body.presenting.pr-chrome-book #prIntro.pr-book-index-leaving .pr-book-index-foreword,
  body.presenting.pr-chrome-book #prEnd .pr-end-card,
  body.presenting.pr-chrome-book #prEndTakeList li,
  body.presenting.pr-chrome-book .pr-book-index-list li {
    animation: none !important;
    opacity: 1;
    transform: none;
    filter: none;
  }
  /* #prTitleCard is anchored by left/top:50%; reduced motion removes only
     its arrival, never the centring transform that makes the cover fit. */
  body.presenting.pr-chrome-book #prTitleCard.show {
    animation: none !important;
    opacity: 1;
    transform: translate(-50%, -50%) !important;
    filter: none;
  }
}

/* ---- Visual Story inspector: collapsible sections (class-based — the
   section markup closes with plain divs, so <details> was not an option).
   The h3/h4 is the toggle; everything else hides while collapsed. */
.vs-inspector .vs-acc-h { cursor: pointer; user-select: none; display: flex; align-items: center; gap: 6px; }
.vs-inspector .vs-acc-h .vs-chev { margin-left: auto; font-size: 10px; opacity: .6; transition: transform .15s ease; transform: rotate(90deg); }
.vs-inspector .vs-collapsed > .vs-acc-h .vs-chev { transform: rotate(0deg); }
.vs-inspector .ins-section.vs-collapsed > :not(.vs-acc-h),
.vs-inspector .vs-adv.vs-collapsed > :not(.vs-acc-h) { display: none; }
.vs-inspector .vs-adv { margin-top: 10px; padding: 7px 9px; border: 1px dashed var(--border-soft); border-radius: 8px; }
.vs-inspector .vs-adv > h4 { margin: 0; font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* ===================================================================
   THEME TAB (right panel) — the dedicated pane for the document's look.
   The rich theme cards reuse the popover's .theme-card6 markup; here they
   stack in one column (the pane is narrower than the 340px popover and the
   card previews deserve the full width). The legacy fold keeps its compact
   two-up grid. Content is rendered by CommonSettings.renderThemePane().
   =================================================================== */
/* Descendant, not child: the cards now live inside the Themes <details>
   section, and the child combinator silently handed them the popover's
   two-column grid — the second column clipped off the 292px panel. */
#themePane .theme-grid:not(.theme-grid-legacy) { display: flex; flex-direction: column; gap: 8px; }
#themePane .theme-grid-legacy { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
#themePane .tp-hint { font-size: 11px; line-height: 1.5; }
#themePane .theme-wipe { margin: 2px 2px 0; }

/* ===================================================================
   EXPLAIN SETTINGS ACCORDION — each data-acc section collapses to its
   heading (chevron literal on purpose: build_dist.py inlines this file
   through re.sub, so a backslash-digit CSS escape in content: — or even
   in a comment — dies as a regex backreference).
   Only the first .pr-pop-h in a section becomes the toggle (present-plus
   adds .pr-acc-h); sub-heads and every control simply hide when closed,
   so all bindings and ids survive untouched.
   =================================================================== */
#prSettings .pr-pop-sec[data-acc] > .pr-acc-h { cursor: pointer; display: flex; align-items: center; gap: 8px; user-select: none; }
#prSettings .pr-pop-sec[data-acc] > .pr-acc-h::after { content: "▾"; margin-left: auto; font-size: 11px; opacity: .55; }
#prSettings .pr-pop-sec[data-acc] > .pr-acc-h:hover { color: #fff; }
#prSettings .pr-pop-sec[data-acc] > .pr-acc-h:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
#prSettings .pr-pop-sec.pr-acc-closed > .pr-acc-h::after { content: "▸"; }
#prSettings .pr-pop-sec.pr-acc-closed > .pr-acc-h { margin-bottom: 0; }
#prSettings .pr-pop-sec.pr-acc-closed > :not(.pr-acc-h) { display: none; }

/* ===================================================================
   EXPORT HUB — the Fine-tune fold's three cluster labels.
   =================================================================== */
.xh-grp { font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); margin: 16px 0 2px; padding-bottom: 5px; border-bottom: 1px solid var(--border-soft); }
.xh-more > .xh-grp:first-of-type { margin-top: 10px; }

/* ===================================================================
   COLOUR EDITIONS — the palette band device on the live book surfaces.
   The band gradient is published by syncNotebookBookStyle whenever the
   resolved publishing spec carries a palette (page tone Colour / Colour
   dark); data-book-edition on <body> is the gate, because CSS cannot test
   a custom property for absence. Covers get their band from the canvas
   painter, so the file and the room agree.
   =================================================================== */
body.presenting.pr-chrome-drawbook[data-book-edition] #prDrawIndexTitle {
  padding-bottom: 10px;
  border-bottom: 4px solid transparent;
  border-image: var(--pr-book-palette-band) 1;
}
body.presenting.pr-chrome-drawbook[data-book-edition] #prEnd h2 {
  padding-bottom: 12px;
  border-bottom: 5px solid transparent;
  border-image: var(--pr-book-palette-band) 1;
}
/* The Drawing Book's native branded front follows the PAGE TONE: a dark
   edition opens on a dark board, not a cream card inside a dark book. The
   vars carry the resolved publishing spec, so Default keeps today's ivory
   exactly and the dark tones inherit their near-black paper + white ink. */
body.presenting.pr-chrome-drawbook #prIntro:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front {
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--pr-book-cream, #fbfaf5) 94%, var(--pr-book-accent, #4f46e5)),
    var(--pr-book-cream, #fbfaf5) 60%);
  color: var(--pr-book-ink, #222a35);
}
body.presenting.pr-chrome-drawbook .pr-intro-card.pr-diagramium-front #prIntroTitle {
  color: var(--pr-book-ink, #222a35) !important;
}
/* No intro artwork: the topic list earns the full sheet width instead of
   truncating against an empty art column. */
body.presenting.pr-chrome-drawbook .pr-draw-index-body:has(.pr-draw-index-art[hidden]) {
  grid-template-columns: 1fr;
}

/* DARK EDITIONS (page tone Dark / Colour dark) reach EVERY surface of the
   show: desk, cover board, contents sheet, page paper, closing board. The
   light chrome above builds its ivory depth from WHITE glare overlays and a
   hardcoded ivory desk — on near-black paper the glare is a grey bloom and
   the desk stays cream around a dark card, which is what "not dark for the
   dark tone" looked like. body[data-book-dark] is published by
   syncNotebookBookStyle; the vars already carry the dark spec's colours. */
body.presenting.pr-chrome-drawbook[data-book-dark] #stage,
body.presenting.pr-chrome-drawbook[data-book-dark] #prIntro,
body.presenting.pr-chrome-drawbook[data-book-dark] #prEnd {
  background:
    radial-gradient(115% 120% at 50% 18%, rgba(255, 255, 255, 0.05), transparent 58%),
    linear-gradient(135deg, #111318, var(--pr-book-desk, #08090b));
}
body.presenting.pr-chrome-drawbook[data-book-dark] #svgHost,
body.presenting.pr-chrome-drawbook[data-book-dark] .pr-book-page-stay {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.045), transparent 42%),
    radial-gradient(120% 90% at 58% 42%, rgba(255, 255, 255, 0.03), transparent 62%),
    var(--pr-book-cream, #141519);
  box-shadow:
    2px 3px 0 -1px var(--pr-book-edge, #242830),
    0 24px 48px rgba(0, 0, 0, 0.6);
}
body.presenting.pr-chrome-drawbook[data-book-dark].pr-spot-fill #stage,
body.presenting.pr-chrome-drawbook[data-book-dark].pr-spot-fill #canvasWrap {
  background: var(--pr-book-cream, #141519);
}
body.presenting.pr-chrome-drawbook[data-book-dark] #prIntro .pr-intro-card,
body.presenting.pr-chrome-drawbook[data-book-dark] #prEnd .pr-end-card {
  background:
    radial-gradient(120% 160% at 14% 0%, rgba(255, 255, 255, 0.07), transparent 46%),
    linear-gradient(118deg, transparent 34%, rgba(255, 255, 255, 0.03) 48%, transparent 62%),
    linear-gradient(135deg, var(--pr-book-cover, #0d0e11), var(--pr-book-cover-deep, #08090b));
  box-shadow: 0 18px 58px rgba(0, 0, 0, 0.55);
}
body.presenting.pr-chrome-drawbook[data-book-dark] #prIntro .pr-intro-card::after {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 0 0 7px transparent,
    inset 0 0 0 8px color-mix(in srgb, var(--pr-book-gold, #c9b06a) 22%, transparent),
    inset 0 0 34px rgba(0, 0, 0, 0.3),
    0 1px 0 rgba(255, 255, 255, 0.04);
}
body.presenting.pr-chrome-drawbook[data-book-dark] #prIntro.pr-drawbook-indexing .pr-intro-card {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.045), transparent 44%),
    var(--pr-book-cream, #141519);
}
/* Interaction hygiene (Web Interface Guidelines pass, Sep 5): every control
   on the drawbook boards has a visible keyboard focus ring and no double-tap
   delay. Hover feedback lives with each control's own rules above. */
body.presenting.pr-chrome-drawbook :is(#prIntroPlay, .pr-draw-index-continue, #prEnd .pr-end-card :is(a, button)) {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
body.presenting.pr-chrome-drawbook :is(#prIntroPlay, .pr-draw-index-continue):focus-visible {
  outline: 2px solid var(--pr-book-accent, #4f46e5);
  outline-offset: 3px;
}
/* The native branded front no longer needs its own dark slab once the desk
   is dark: the cluster floats on the full-page board instead of sitting in
   a box (the "play slide" the operator wanted full-page dark). */
body.presenting.pr-chrome-drawbook[data-book-dark] #prIntro:not(.pr-drawbook-indexing) .pr-intro-card.pr-diagramium-front {
  background: transparent;
  box-shadow: none;
}

/* The Context pre-roll is part of the book too: it painted the generic
   Present sheet (white page, slate ink) whatever the page tone, so a dark
   edition opened on a white slide. It reads the same --pr-book-* vars as
   every other drawbook surface, in every tone. */
body.presenting.pr-chrome-drawbook #prContextTour {
  background: var(--pr-book-cream, #fbfaf5);
  color: var(--pr-book-ink, #222a35);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-copy {
  background: color-mix(in srgb, var(--pr-book-cream, #fbfaf5) 92%, transparent);
  border-color: color-mix(in srgb, var(--pr-book-muted, #6a6f77) 30%, transparent);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-title,
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-text,
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-loading {
  color: var(--pr-book-ink, #222a35);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-kicker {
  color: var(--pr-book-accent, #4f46e5);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-btn {
  background: var(--pr-book-cream, #fbfaf5);
  color: var(--pr-book-ink, #222a35);
  border-color: color-mix(in srgb, var(--pr-book-muted, #6a6f77) 45%, transparent);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-next {
  background: var(--pr-book-accent, #4f46e5);
  color: #fff;
  border-color: transparent;
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-progressrail {
  background: color-mix(in srgb, var(--pr-book-muted, #6a6f77) 28%, transparent);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-progressrail i,
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-dot[aria-current="step"] {
  background: var(--pr-book-accent, #4f46e5);
}
body.presenting.pr-chrome-drawbook #prContextTour .pr-ctx-dot {
  background: color-mix(in srgb, var(--pr-book-muted, #6a6f77) 45%, transparent);
}

/* =====================================================================
   STUDIO SHOW (operator, Sep 5 2026). Target ids are DOUBLED (#prIntroTitle#prIntroTitle):
   the book chrome states colour/face at (2,4,1) !important and a plain two-id
   selector lost; the repeat lifts ours to (3,1,1) with no DOM assumption. The Studio writes st.show; the live
   show reads it through <body> custom properties, each gated by its own
   class (applyShowLive in app.js) — a var with no value would compute the
   property to `unset` and take a slide's background with it, so a rule
   exists only while the value does. !important on purpose: these are
   explicit user choices over the theme's dressing, which the book chrome
   states at high specificity. The export paints the same values on canvas
   (drawTitleCard / drawDrawBookContentsSheet / notebookBackCoverCopy). */
body.show-title-bg #prIntro:not(.pr-drawbook-indexing) .pr-intro-card { background: var(--show-title-bg) !important; }
body.show-title-ink #prIntro:not(.pr-drawbook-indexing) .pr-intro-card,
body.show-title-ink #prIntro #prIntroTitle#prIntroTitle, body.show-title-ink #prIntro .pr-brandin,
body.show-title-ink #prIntro #prIntroBrand#prIntroBrand { color: var(--show-title-ink) !important; }
body.show-title-muted #prIntro #prIntroHeader#prIntroHeader, body.show-title-muted #prIntro #prIntroFooter#prIntroFooter, body.show-title-muted #prIntro #prIntroMeta#prIntroMeta,
body.show-title-muted #prIntro #prIntroMeta#prIntroMeta span { color: var(--show-title-muted) !important; }
body.show-title-accent #prIntro .pr-intro-card { --accent: var(--show-title-accent); --pr-book-accent: var(--show-title-accent); --iris: var(--show-title-accent); }
body.show-title-font #prIntro #prIntroTitle#prIntroTitle, body.show-title-font #prIntro #prIntroHeader#prIntroHeader,
body.show-title-font #prIntro #prIntroFooter#prIntroFooter { font-family: var(--show-title-font) !important; }
body.show-title-scale #prIntro #prIntroTitle#prIntroTitle, body.show-title-scale #prIntro #prIntroHeader#prIntroHeader, body.show-title-scale #prIntro #prIntroFooter#prIntroFooter,
body.show-title-scale #prIntro #prIntroMeta#prIntroMeta { zoom: var(--show-title-scale); }

body.show-contents-bg #prIntro.pr-drawbook-indexing .pr-intro-card,
body.show-contents-bg #prBookIndex .pr-book-index-page { background: var(--show-contents-bg) !important; }
body.show-contents-ink #prIntro #prDrawIndex#prDrawIndex, body.show-contents-ink #prIntro #prDrawIndexTitle#prDrawIndexTitle, body.show-contents-ink #prIntro #prDrawIndexList#prDrawIndexList,
body.show-contents-ink #prIntro #prBookIndex#prBookIndex, body.show-contents-ink #prIntro #prBookIndex#prBookIndex h3 { color: var(--show-contents-ink) !important; }
body.show-contents-muted #prIntro #prDrawIndex#prDrawIndex .pr-draw-index-running, body.show-contents-muted #prIntro #prBookIndex#prBookIndex .pr-book-index-kicker,
body.show-contents-muted #prIntro #prBookIndex#prBookIndex .pr-book-running { color: var(--show-contents-muted) !important; }
body.show-contents-accent #prDrawIndex, body.show-contents-accent #prBookIndex { --pr-book-accent: var(--show-contents-accent); --accent: var(--show-contents-accent); }
body.show-contents-font #prIntro #prDrawIndex#prDrawIndex, body.show-contents-font #prIntro #prDrawIndexTitle#prDrawIndexTitle, body.show-contents-font #prIntro #prBookIndex#prBookIndex,
body.show-contents-font #prIntro #prBookIndex#prBookIndex h3 { font-family: var(--show-contents-font) !important; }
body.show-contents-scale #prIntro #prDrawIndex#prDrawIndex .pr-draw-index-copy, body.show-contents-scale #prIntro #prBookIndex#prBookIndex .pr-book-index-page { zoom: var(--show-contents-scale); }

body.show-intro-bg #prContextTour, body.show-intro-bg #prContextTour .pr-ctx-copy { background: var(--show-intro-bg) !important; }
body.show-intro-ink #prContextTour, body.show-intro-ink #prContextTour .pr-ctx-title,
body.show-intro-ink #prContextTour .pr-ctx-text { color: var(--show-intro-ink) !important; }
body.show-intro-muted #prContextTour .pr-ctx-kicker { color: var(--show-intro-muted) !important; }
body.show-intro-accent #prContextTour { --iris: var(--show-intro-accent); --pr-book-accent: var(--show-intro-accent); --accent: var(--show-intro-accent); }
body.show-intro-font #prContextTour .pr-ctx-title, body.show-intro-font #prContextTour .pr-ctx-text { font-family: var(--show-intro-font) !important; }
body.show-intro-scale #prContextTour .pr-ctx-copy { zoom: var(--show-intro-scale); }

body.show-end-bg #prEnd { background: var(--show-end-bg) !important; -webkit-backdrop-filter: none; backdrop-filter: none; }
body.show-end-bg #prEnd .pr-end-card { background: var(--show-end-bg) !important; }
body.show-end-ink #prEnd .pr-end-card, body.show-end-ink #prEnd #prEndTitleH#prEndTitleH, body.show-end-ink #prEnd #prBookCloseActions#prBookCloseActions b,
body.show-end-ink #prEnd #prEndBrand#prEndBrand { color: var(--show-end-ink) !important; }
body.show-end-muted #prEnd #prEndSub#prEndSub, body.show-end-muted #prEnd .pr-end-brand, body.show-end-muted #prEnd #prBookCloseActions#prBookCloseActions p,
body.show-end-muted #prEnd #prBookCloseActions#prBookCloseActions span { color: var(--show-end-muted) !important; }
body.show-end-accent #prEnd { --accent: var(--show-end-accent); --pr-book-accent: var(--show-end-accent); --iris: var(--show-end-accent); }
body.show-end-font #prEnd #prEndTitleH#prEndTitleH, body.show-end-font #prEnd #prEndSub#prEndSub, body.show-end-font #prEnd #prBookCloseActions#prBookCloseActions { font-family: var(--show-end-font) !important; }
body.show-end-scale #prEnd #prEndTitleH#prEndTitleH, body.show-end-scale #prEnd #prEndSub#prEndSub, body.show-end-scale #prEnd #prBookCloseActions#prBookCloseActions { zoom: var(--show-end-scale); }

/* The brand slot: a logo and/or a name where the Diagramium lockup stands. */
body.show-brand #prIntro .pr-brandin, body.show-brand #prEnd .pr-end-mark { display: none !important; }
.pr-show-brand { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 14px; color: inherit; }
.pr-show-brand[hidden], .pr-show-brand img[hidden], .pr-show-brand span[hidden] { display: none; }
.pr-show-brand img { height: clamp(40px, 6vh, 72px); max-width: 260px; object-fit: contain; }
.pr-show-brand span { font-weight: 800; font-size: clamp(18px, 2.2vw, 30px); letter-spacing: -0.02em; }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-show-brand {
  position: absolute; top: 8.2%; left: 10.2%; margin: 0;
}
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-show-brand img { height: clamp(32px, 3.1vw, 46px); }
body.presenting.pr-chrome-drawbook #prIntro .pr-intro-card:not(.pr-book-custom-cover) .pr-show-brand span { font-size: clamp(18px, 2vw, 29px); }
.pr-book-close-static { display: flex; flex-direction: column; }

/* ---- Studio mode (js/studio-mode.js) --------------------------------- */
.btn-studio svg { width: 16px; height: 16px; vertical-align: -3px; margin-right: 4px; }
.studio-root { position: fixed; inset: 0; z-index: 120; background: var(--chrome); color: var(--text); display: flex; flex-direction: column; }
.studio-root[hidden] { display: none; }
.st-top { display: flex; align-items: center; gap: 12px; padding: 10px 16px; border-bottom: 1px solid var(--border); background: var(--chrome-2); flex-wrap: wrap; }
.st-top h2 { font-size: 15px; margin: 0; font-weight: 700; }
.st-top .st-doc { color: var(--muted); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 34ch; }
.st-top .st-spacer { flex: 1; }
.st-body { flex: 1; display: grid; grid-template-columns: 224px minmax(0, 1fr) 372px; min-height: 0; }
.st-rail { border-right: 1px solid var(--border); padding: 12px 10px; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; background: var(--panel); }
.st-tab { display: flex; align-items: center; gap: 10px; text-align: left; padding: 9px 10px; border-radius: 10px; border: 1px solid transparent; background: transparent; color: var(--text); font: inherit; cursor: pointer; }
.st-tab:hover { background: var(--panel-2); }
.st-tab[aria-selected="true"] { background: var(--panel-2); border-color: var(--border); }
.st-tab .st-num { flex: 0 0 22px; width: 22px; height: 22px; border-radius: 7px; background: var(--chrome-3); display: grid; place-items: center; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.st-tab[aria-selected="true"] .st-num { background: var(--iris); color: var(--on-signal, #221503); }
.st-tab b { display: block; font-size: 13px; }
.st-tab small { display: block; color: var(--muted); font-size: 11px; }
.st-tab .st-dot { margin-left: auto; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.st-stage { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 20px; background: var(--panel-2); min-width: 0; overflow: auto; }
.st-canvas-wrap { width: min(100%, 1120px); box-shadow: var(--shadow); border-radius: 12px; overflow: hidden; border: 1px solid var(--border); background: #000; }
.st-canvas-wrap.portrait { width: min(100%, 400px); }
.st-canvas-wrap canvas { display: block; width: 100%; height: auto; }
.st-cap { font-size: 12px; color: var(--muted); text-align: center; max-width: 720px; line-height: 1.45; margin: 0; }
.st-props { border-left: 1px solid var(--border); overflow-y: auto; padding: 14px 16px 24px; background: var(--panel); display: flex; flex-direction: column; gap: 14px; }
.st-props h3 { margin: 0; font-size: 13px; font-weight: 700; }
.st-props h4 { margin: 6px 0 0; font-size: 11.5px; font-weight: 700; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.st-help { font-size: 11.5px; color: var(--muted); line-height: 1.45; margin: 0; }
.st-field { display: flex; flex-direction: column; gap: 4px; }
.st-field > label { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.st-props input[type="text"], .st-props textarea, .st-props select {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 13px; padding: 7px 9px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--chrome-2); color: var(--text);
}
.st-props textarea { min-height: 76px; resize: vertical; line-height: 1.4; }
.st-colors { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.st-color { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--chrome-2); }
.st-color input[type="color"] { width: 28px; height: 28px; border: 0; padding: 0; background: none; border-radius: 6px; cursor: pointer; }
.st-color.unset input[type="color"] { opacity: .38; }
.st-color span { flex: 1; font-size: 12px; min-width: 0; }
.st-color button { font: inherit; font-size: 11px; color: var(--muted); background: none; border: 0; cursor: pointer; padding: 2px 4px; }
.st-color button:hover { color: var(--text); }
.st-range { display: flex; align-items: center; gap: 10px; }
.st-range input { flex: 1; }
.st-range output { font-size: 12px; min-width: 40px; text-align: right; color: var(--muted); }
.st-img { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.st-img img { width: 72px; height: 48px; object-fit: contain; border-radius: 6px; border: 1px solid var(--border); background: var(--chrome-2); }
.st-img img[hidden] { display: none; }
.st-btn { font: inherit; font-size: 12.5px; padding: 7px 12px; border-radius: 9px; border: 1px solid var(--border); background: var(--chrome-2); color: var(--text); cursor: pointer; }
.st-btn:hover { background: var(--chrome-3); }
.st-btn.primary { background: var(--iris); color: var(--on-signal, #221503); border-color: transparent; }   /* --accent aliases --iris, which is near-white in the default palette: white text on it was invisible (operator, Sep 6 2026) */
.st-btn.primary:hover { filter: brightness(1.08); }
.st-btn.danger { color: #c0392b; }
.st-btn:disabled { opacity: .5; cursor: default; }
.st-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.st-actions-list { display: flex; flex-direction: column; gap: 8px; }
.st-action-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: 6px; padding: 8px; border: 1px solid var(--border-soft); border-radius: 8px; }
.st-action-row input.st-url { grid-column: 1 / 3; }
.st-tpl-list { display: flex; flex-direction: column; gap: 6px; }
.st-tpl { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--chrome-2); font-size: 12.5px; }
.st-tpl b { flex: 1; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-tpl small { color: var(--muted); white-space: nowrap; }
.st-file { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.st-summary { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: 12.5px; }
.st-summary dt { color: var(--muted); }
.st-summary dd { margin: 0; font-weight: 600; }
body.studio-open { overflow: hidden; }
@media (max-width: 1100px) { .st-body { grid-template-columns: 184px minmax(0, 1fr) 328px; } }
@media (max-width: 860px) {
  .st-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; }
  .st-rail { flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); }
  .st-tab small, .st-tab .st-dot { display: none; }
  .st-props { border-left: 0; border-top: 1px solid var(--border); max-height: 44vh; }
}

/* ---- a Visual Learning lesson is forward / back only ----------------------
   body.lesson-locked (js/courses-home.js, on top of .sample-locked): the
   operator's brief for the read-only lessons — "keep everything hidden, no
   settings, theme etc, just navigate forward or backwards". What stays:
   Prev · Play/Pause · Next, the step/time readout, full screen and Exit. The
   share doors go too: a lesson is not a catalogue row, so the play-only URL
   they copy would not resolve. */
body.lesson-locked #prRestart, body.lesson-locked #prFirst, body.lesson-locked #prLast,
body.lesson-locked #prSpeedCycle, body.lesson-locked #prLikeBtn, body.lesson-locked #prMuteToggle,
body.lesson-locked #prVoiceToggle, body.lesson-locked #prCaptionToggle, body.lesson-locked #prSmartToggle,
body.lesson-locked #prAudienceCycle, body.lesson-locked #prNarrationToggle, body.lesson-locked #prFocusToggle,
body.lesson-locked #prConnectorMotionToggle, body.lesson-locked #prThemeToggle, body.lesson-locked #prThemePop,
body.lesson-locked #prToolLaser, body.lesson-locked #prToolPen, body.lesson-locked #prToolSpot,
body.lesson-locked #prMore, body.lesson-locked #prSettings, body.lesson-locked #prPin, body.lesson-locked #prZenToggle,
body.lesson-locked #prShortcutsBtn, body.lesson-locked #prShortcuts, body.lesson-locked #prRecordPop,
body.lesson-locked #prIntroSettings, body.lesson-locked #prIntroMute,
body.lesson-locked #prMobileMute, body.lesson-locked #prMobileNotes,
body.lesson-locked #prBookShare, body.lesson-locked #prEndShare, body.lesson-locked #prSharePop,
body.lesson-locked #prEndEdit, body.lesson-locked #prEndExplore, body.lesson-locked #prEndQa, body.lesson-locked #prQa { display: none !important; }
/* The Drawing Book's closing row re-asserts its buttons with an #prEnd-rooted
   rule of its own (styles.css, `.pr-book-close-action-row :is(a, button)`), so
   the lesson's Share door needs the same root to lose. */
body.presenting.lesson-locked #prEnd .pr-book-close-action-row #prBookShare { display: none !important; }

/* Explainer scenes (js/explainer.js): the step caption chip would only
   repeat the scene's own title, so it yields while a scene is on stage
   (app.js renderPresentAt toggles body.pr-explainer per settled step). */
body.presenting.pr-explainer #prCaption { display: none !important; }

/* The Slides tab (Explain sections) — one row per slide, a checkbox each. */
#slidesPane { padding: 10px 12px 16px; }
#slidesPane .sl-head { font-weight: 700; font-size: 12.5px; margin: 2px 0 4px; }
#slidesPane .sl-help { font-size: 11px; line-height: 1.4; margin-bottom: 8px; }
#slidesPane .sl-group { font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin: 12px 0 2px; }
#slidesPane .sl-row { display: flex; align-items: flex-start; gap: 9px; padding: 7px 2px; border-bottom: 1px solid var(--border-soft); cursor: pointer; }
#slidesPane .sl-row input { margin-top: 3px; flex: none; }
#slidesPane .sl-row.off { opacity: .55; cursor: default; }
#slidesPane .sl-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
#slidesPane .sl-copy b { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#slidesPane .sl-copy small { font-size: 11px; color: var(--muted); line-height: 1.35; }
#slidesPane .sl-row .btn-ghost { flex: none; }

/* The wordmark face: Outfit (SIL OFL 1.1, no Reserved Font Name; notice in
   pages/licenses.html §5). Subset to the ten letters of "Diagramium" (upper
   and lower case), weights 500–800, inlined as a 2.6 KB data URI so the app,
   the public pages and the offline single-file build all draw the same mark
   with no request (CSP font-src already allows data:). Only the wordmark
   uses it — any other text in this family would fall back glyph by glyph.
   Source + licence: assets/fonts/Outfit-Wordmark.woff2, Outfit-OFL.txt. */
@font-face {
  font-family: 'Diagramium Wordmark';
  font-style: normal; font-weight: 500 800; font-display: swap;
  src: url(data:font/woff2;base64,d09GMgABAAAAAApMABQAAAAAE3AAAAngAAEZmgAAAAAAAAAAAAAAAAAAAAAAAAAAGkwbg0IcKj9IVkFSUT9NVkFSRAZgP1NUQVRUAIEUL0QRCAqJEIciMIcwATYCJAM4Cx4ABCAFiQAHIAwHGwsRswM1YxwYwyZABP/18YZIHetYWsjkPA5yCmf84yGC+IT4Lhx6sKt9zlQWv8L7p3JMR2d4e9AkaJDGsuG+lZFN+e3LpX7wz8Hz/P7Ac+/78CCybmnRSGRampOAN/x72svmtD3MTOEkY6GVk5Ed/Hv+AziYX2dRPX+w2XsskSeJUP/n59KX5P+7vOMcMJTdNLupCTshmw6FrpCtkiNX4uUKHGqOEgDHdFaZFsbqJRWfxPwVKI0cEc3/RoAk8AH8v/1+1bl4dB2kWYheOYRMCTP/+0XcH66hiXUiIQ1ilsRWmkZC322i61KTme2GEoc4xEFWRIb6unu8djcEQ264q1WkGAQHwSNCSEgRBEjuJD8DY1piROAN8XfnegECRJRVm7Zt37Uve6aOmjudPTgA1iKATBk3ezomAGqDg7ooEXvfZE5tAQyFVTQbhMHgkaCIPdGbPgG9wYg9AGqfwdhrzTkO3QQ8Z/Dtoz8Ce6EtUxOKVVwA7kqgGo9mcqI8B6+RvQexXTAJSb+9AGQllDXaAmx0iENA0Mg+dcP+xNKvuMmab29D4IB0RO1L91FslV+fmBTFcJx5UP1UkyrUZoOa+AjSXq2bSlYCHAfINzJseRUNbXqJ4AryxrTIDeCo6KXv431qlicQCsczuWK5AoaM2DGRF6orifoBAkCAoexXTpwLQL78qxQAC38T8IHMpKfHckMcbS1fXdDVGwigSzofGQ6vkgShBdV/ASCkh1aq7+V/wi05A+p28nAdoKQQQRAsyssBitIFE/yKIkBAXiVVLc3x5CtPjq8DMatAzySGRhoomJy8TA1c6f+HczIktCKnpBYsQrR0ufIVq1D9AOn7bC+8c8447YQjDtlju202W29tQsChIidFJGGwVPKVx3LpEhHxIJfhQ6s1QQpnokKqVBBrkkNBdhMoCopBRgHkIQBwAPYpikMTmxk0TqQkeH6ehEmRePyEBAW31S94iIP4fMQVsFM3wSqDok+OlkWHJYZHRZAKSflwCikpFqIAO0Q6sbwsxNJSBHepF8GYF3xEZEOSQfrxJWMhltmAVEnU3aHOxxcWWDY2P5oMUUo0sWPxybLhXJIBrO8ZByd46yVCpBPzEDHHHccOsvIpCbHZ92LRJ+nxsS52Y1nZnLJx3Mb3PyEufyo6PjF3q8l+UGwMRNJ7pEtj70yAUA+/B9C/fLpfiD5LenJ7J2N9XSvleBdEdJv8TtDWgeeS9Ik5WvHz28CfQdVnBTSXGKj1icyUjlKjTl89xcwswujBi6h5I+zSYdtxpYK/xLc688V/0SBBW1sCws6vwhxfNW3jtF3c/HBWZRa4kP9cVSQILFGrBMVFAuXz/Fc6Ak1LwVq0Gqw1NYVAteSOyg5wxFTV6pOagbdrtTiRltGO6yJPif4tl+9zWYGqImFAqUYTWJYrkgZl8bAsjZJPz0/Y1xx35Vw40E3DXnLD3LZQ5yOso/Lb6eWMsAue/raOpD7ArnIZF7CHWc+kmSie4C/A4zO5UkOk9LyUH8rHyy4GxJuGNitVTaEPKx/waRo1wmIrEaqG173uo1BlY6MSGJpK8iSBZUHK+Px5UolPFIsbjh5HOeHRLI9cgSZcTHeVDFCRATcJne6GPMX1J2FWZVZZU7IDzOrKcVelsl/tjkq0Uv8as3yzAqJkQiHKKfcLXRfnCP2L5XL/QicS+0Uz2WF4DcYJtxdxzUUekKlU8gME6XWgIo69oJ2SHdzHQeEQxjpi5zQMCDL7mS3Oecxwet1BrvmwQ8MZfH44/Z7gi/cbOf52Xg7CQqNs0Eg6Vzb2SyRFJIaVRXicO6lUT/4PwAsAmQpSMDRFaF1i5p426sxBMLMSaxGakoyuAYAAggC1ZQDUBQVV1UOzIzY7757A0kEGyqp2dO7TFgHlAZKCokwmL8H1DE67u9XZF7gXdyECIZQanMdCRtTz5QHJ9Zyy9ArTMN12ONJpKJcQprNoSSRATaVUOqyoE9razT2cCR6IOxBw+mLpXCBIR31OWe71IFAe6++Al4yTTi93CC5rdyA1p7O1EL+ywYdaJRedqDKso4PNFS0WJzo6ovVusEg5ItAnSQqZ2BcPgU8smGZmhLeDM88fHe56+W9QId9eqRLm77VUyu/lTaHEmsuxDAsSuVcEFHO3VwAAQZbzAq8UCsPhVXLU7nYhLK5SxNdLRJFuboTDG5tfi2BRnaCl8qasfcys3W4sU+2kVxL+ZQrk6LsO5MSgFgJru6lfElyKpzAzNA0QfwJ0S0M4kx+BtLwU/Ti7OyO5zVJ+8IoBE2sTEDnPQrrk3RyiYGMdeV8XyoamalosNB6H0s2NJD06Rhfayz2kkdogthrB1Nfnc2UyEBLXsizl7YgYaiz/O5Ch14tQ/XRLLXuqUV+5Byy1Ii4PPovmZsb9vds+VYY7YH26vx/24ubGuqq0UPXx43B4dxeXPlFD2gcv0sjiK/W8l7zgFPuKsT+RbeHlBcGN6BqcqPBAcINgfXnrYszPzzejaFxM0ujiBaOt+aURTx2rhWFZTm1rUQY4SrcqFoRrT9oAouAj1DRtbu4aciFntNZRN5HIlOq1KpCjXIW4UtCCNU30hhJJSATvIc31TG/3oPzseQpEzBgLy/SZXKtcJh3JTYCq1lfp/HOu2tKg3yiiS/Cn5yAurnoQwYQiIgqxo92dYMTV25HqcjJgxDFGLOODZYkTp+rgw2sK07u7RiPjNAGCO1uvhwAJAAMATGS91Y/7P7lXVJ7jLgGAg/3/MwAA6Wj6q52CD66SXgQeCoDARxz1MJKRaAIEdZBMD+qycwruqa7nUKk4de6MbnOvtEPari3Oa0Fxr6l7wxC0T7O51NLSjHoc8P3o9HwpdHJCYC8wKuS3lyoZ56ihqksjHSp1aewn9chfbRqQs440pGwDaUz1ltKE8u2nqZSWazSj/j7TnBJTkeYSmLojCuXjRCCqqQZPvyP1yXl9aUBgxl48JPf9vN5HGdmCv11SVsslpzlkgNZdey7TnKbZFEnxQ/88dkl132g7CjN8W7nSaSsKF8TXe7/wh4bCPpHAzOuKIzRdJ0tQyNOI+5+4o9zTf+wSlFS1w+wf3mEwLMKJi0ZRaxThYArY1wZRd+4qtKDcePIq6658uG6GO/xv7tGRjDxqxj+6+P8Johjg8O1GkrIMz+TpHkEYxUWT2IxT2VyFLLYZyiYyBPbAMGgW21YFkXPgH2Njh/6T6rxBSLYNKUvGdHEUUJb0qjB6wQSFAbQ3Crau3/pKUWk/foxiSzN+dUJUcHwYSVY/o7vF5nbb5LBlOH+NR3l0MsBhRTieyA/ZLIwWxb03X+lyzvTtwWUjQZgYe42BYe8gxfynFcPQ3XJlJir9GTvci5TrP8+hAwY=) format('woff2');
}

/* Bricolage Grotesque — the Studio theme's heading face, bundled under the
   SIL Open Font License 1.1 (assets/fonts/BricolageGrotesque-OFL.txt;
   notice in pages/licenses.html §5). `local()` first, so an installed copy
   is never re-fetched; the browser loads a file only when a page actually
   sets the family, i.e. under the Studio theme. Inter, the body face, is
   NOT bundled — it is named by its stack and falls back to the system UI
   sans (see assets/fonts/README.md). */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal; font-weight: 400; font-display: swap;
  src: local('Bricolage Grotesque'), local('BricolageGrotesque-Regular'),
       url('assets/fonts/BricolageGrotesque-Regular.ttf') format('truetype');
}
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal; font-weight: 700; font-display: swap;
  src: local('Bricolage Grotesque Bold'), local('BricolageGrotesque-Bold'),
       url('assets/fonts/BricolageGrotesque-Bold.ttf') format('truetype');
}

/* ---- The Explainer outro, live (body.pr-explainer-end; operator, Sep 7 2026).
   A scene deck's end slide wears the film's outro: one near-black canvas
   with a breath of depth, the mark, one payoff line in the bold grotesque
   with a single amber phrase, the document's name in Inter, and the
   interactive controls kept but QUIET — Explore more is the one amber pill,
   Replay / Q&A / Edit are plain text. No Subscribe / Share / Feedback rows,
   no course-complete copy, no coloured rules. Both aspects share the stack;
   the phone tightens the type and keeps the safe area at the foot. ---- */
body.presenting.pr-explainer-end #prEnd {
  background: radial-gradient(ellipse 70% 55% at 50% 42%, rgba(255,255,255,0.05), rgba(255,255,255,0.015) 55%, rgba(255,255,255,0) 100%), #0D0F12 !important;
}
/* FULL SCREEN, not a tile (operator, Sep 8 2026): the card is the whole
   stage — no board, no glare, no shadow, no radius, no aspect box. */
body.presenting.pr-explainer-end #prEnd {
  padding: 0 !important;
  -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
}
body.presenting.pr-explainer-end #prEnd .pr-end-card {
  color: #F5F5F3 !important;
  display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;
  position: relative;
  width: 100% !important; height: 100% !important; max-width: none !important; max-height: none !important;
  aspect-ratio: auto !important;
  background: transparent !important;
  border: 0 !important; border-radius: 0 !important; box-shadow: none !important;
  transform: none !important;
  padding: clamp(28px, 6vh, 64px) clamp(24px, 6vw, 96px) clamp(40px, 9vh, 96px) !important;
  overflow: hidden;
}
body.presenting.pr-explainer-end #prEnd .pr-end-url {
  display: inline-block; margin-top: clamp(10px, 2vh, 18px);
  color: rgba(245,245,243,0.9); font-weight: 600;
}
body.presenting.pr-explainer-end #prEnd .pr-end-mark {
  width: clamp(40px, 4.6vw, 64px); height: clamp(40px, 4.6vw, 64px);
  color: #F5F5F3; margin: 0 0 clamp(18px, 3vh, 30px);
  --mark: #FFB547;
}
body.presenting.pr-explainer-end #prEnd .pr-end-card h2,
body.presenting.pr-explainer-end #prEnd .pr-end-title {
  font-family: 'Bricolage Grotesque', 'Bricolage Grotesque Variable', 'Avenir Next', 'Segoe UI Variable Display', 'Helvetica Neue', Arial, sans-serif !important;
  font-weight: 800 !important;
  font-size: clamp(34px, 5.4vw, 76px) !important;
  letter-spacing: -0.025em !important;
  line-height: 1.06 !important;
  color: #F5F5F3 !important;
  text-shadow: none !important;
  text-wrap: balance;
  max-width: 14em;
  margin: 0 !important;
}
body.presenting.pr-explainer-end #prEnd .pr-end-hook { color: #FFB547; }
body.presenting.pr-explainer-end #prEnd .pr-end-made { color: #B8BDC7; font-weight: 700; }
/* the simple card's own imprint line is the heading — no second one */
body.presenting.pr-explainer-end #prEnd .pr-end-card h2:has(.pr-end-made) ~ .pr-end-brand { display: none !important; }
body.presenting.pr-explainer-end #prEnd .pr-end-sub {
  margin-top: clamp(12px, 2.2vh, 22px) !important;
  font: 500 clamp(14px, 1.5vw, 22px)/1.4 Inter, 'Inter Variable', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;
  color: #B8BDC7 !important;
  max-width: 34em;
}
body.presenting.pr-explainer-end #prEnd .pr-end-takeaways,
body.presenting.pr-explainer-end #prEnd #prBookCloseActions,
body.presenting.pr-explainer-end #prEnd #prEndShare { display: none !important; }
body.presenting.pr-explainer-end #prEnd .pr-end-ctas {
  margin-top: clamp(26px, 5vh, 48px) !important;
  gap: clamp(8px, 1.2vw, 18px);
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
body.presenting.pr-explainer-end #prEnd .pr-end-card .pr-end-btn {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  color: #B8BDC7 !important;
  font: 500 clamp(13px, 1.15vw, 17px)/1 Inter, 'Inter Variable', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;
  padding: 10px 14px !important;
  border-radius: 999px !important;
  order: 2;
}
body.presenting.pr-explainer-end #prEnd .pr-end-card .pr-end-btn:hover { color: #F5F5F3 !important; background: rgba(255,255,255,0.06) !important; transform: none; }
body.presenting.pr-explainer-end #prEnd .pr-end-card #prEndExplore {
  order: 1;
  flex-basis: 100%;
  align-self: center;
  width: max-content;
  margin: 0 auto 6px;
  background: rgba(255,181,71,0.13) !important;
  color: #FFB547 !important;
  font-weight: 600 !important;
  padding: 13px 26px !important;
}
body.presenting.pr-explainer-end #prEnd .pr-end-card #prEndExplore:hover { background: rgba(255,181,71,0.2) !important; }
body.presenting.pr-explainer-end #prEnd .pr-end-card .pr-end-brand {
  position: absolute; left: 0; right: 0; bottom: max(env(safe-area-inset-bottom, 0px), 5vh);
  margin: 0 !important;
  font: 500 clamp(11px, .95vw, 14px)/1 Inter, 'Inter Variable', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;
  color: rgba(184,189,199,0.62) !important;
}
body.presenting.pr-explainer-end #prEnd .pr-end-brand .dbrand,
body.presenting.pr-explainer-end #prEnd .pr-end-brand .um { color: rgba(245,245,243,0.82) !important; }
body.presenting.pr-explainer-end #prEnd [data-tip]::after { content: none; }
body.presenting.pr-explainer-end.pr-portrait #prEnd .pr-end-card h2 { font-size: clamp(30px, 9vw, 60px) !important; }
/* the phone stacks its controls, so the imprint flows under them instead of
   pinning to the foot (it overlapped the wrapped row) */
body.presenting.pr-explainer-end.pr-portrait #prEnd .pr-end-card .pr-end-brand {
  position: static; margin-top: clamp(22px, 5vh, 44px) !important;
}
body.presenting.pr-explainer-end.pr-portrait #prEnd .pr-end-card { padding-bottom: max(env(safe-area-inset-bottom, 0px), 11vh) !important; }

/* ==================================================================
   Landing v4.6 — the refinement pass (Sep 2026).
   Same desk, tidied: the v4.6 palette lives in the token pins above
   (paper #FAF7EF, ink #171821, body #55545A, marker #F4A51C / #DB8910,
   pale highlighter #FBE6A6, navy preview #11152A, edge #D9D3C6). This
   block holds what the pins cannot express — the ground, the header,
   the Privacy menu, the two card variants, the dimmed grid behind the
   dense scenes — and every rule is scoped to the desk pages so the
   editor never sees it. Rules of the pass: sans for reading and UI,
   serif italic only for the brand phrase, mono only for technical
   labels (file names, scene numbers, format stamps, lesson metadata);
   the marker colours controls and a few deliberate marks, never a word.
   ================================================================== */

/* ---- The ground: paper + the notebook lines, nothing layered on top.
   The v2 dot grid and the orange radial wash (#homePage::before) are
   retired — two grids and a gradient under the same hero. ---- */
:root #homePage::before { content: none; }
/* (These pages used to repaint --mark with the accent — marigold — so the
   logo was a different orange here than in the editor, the public pages,
   the favicon and the brand pack. Removed Sep 27 2026: ONE mark colour.) */

/* ---- Dense card scenes sit on a 38% paper wash, so the grid drops by
   about a third behind them; the hero and the prose scenes keep it at
   full strength. Full-bleed via the 100vw trick (#homePage clips x). ---- */
#homePage .lp3 .lp-courses, #homePage .lp3 .lp-tech, #homePage .lp3 .lp-videos,
#homePage .lp3 #lpTools, #homePage .lp3 .home-cards { position: relative; }
#homePage .lp3 .lp-courses::before, #homePage .lp3 .lp-tech::before, #homePage .lp3 .lp-videos::before,
#homePage .lp3 #lpTools::before, #homePage .lp3 .home-cards::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(-1 * clamp(18px, 4vw, 64px)); right: calc(-1 * clamp(18px, 4vw, 64px));
  background: color-mix(in srgb, var(--paper) 38%, transparent);
  pointer-events: none; z-index: -1;
}

/* ---- Header: plain text links, one quiet secondary button, one marker
   CTA. The scrolled bar is paper, not glass. ---- */
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top.is-scrolled,
:is(#explorePage, #searchPage, #rolesPage) .lp-top {
  background: var(--glass-bg); border-bottom-color: var(--edge);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-brandline .lock-icon { color: var(--ink); }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav a,
:is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav-action { color: var(--slate); font-weight: 500; }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav a:hover,
:is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav-action:hover { color: var(--ink); background: var(--panel-2); }
/* the current page carries the marker as an underline — the one place the
   orange marks navigation */
:is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav a[aria-current="page"] {
  color: var(--ink); background: none; box-shadow: inset 0 -2px 0 var(--iris);
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-tbtn {
  color: var(--ink); border-color: var(--edge); background: transparent;
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-tbtn:hover { border-color: var(--ink); background: #fff; }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-tbtn-cta {
  background: var(--iris); color: var(--ink); border: 1.5px solid var(--ink); box-shadow: 2px 2px 0 var(--ink);
  transition: transform .16s var(--ease-out), box-shadow .16s var(--ease-out), background .16s;
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-tbtn-cta:hover {
  background: var(--iris-deep); border-color: var(--ink); filter: none;
  transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink);
}
/* The home bar is three things: nav, Sign in, Open editor. The saved-doc
   shortcut keeps its hook (js/open-diagram.js) but lives in the hero's
   "Already started something?" panel, not in the bar. */
#homePage .lp-toolbar .od-top-btn { display: none !important; }
/* the collapsed nav is a paper sheet, not glass */
@media (max-width: 1079px) {
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav {
    background: #fff; border-color: var(--edge); border-radius: 12px;
    box-shadow: var(--shadow); -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}

/* ---- The Privacy menu (home nav). A disclosure under a plain nav item on
   a laptop; below 1080 the pillnav is the menu and these rows flatten into
   it (display: contents), so a phone sees Usage counts / Clear local data /
   Privacy Policy as three ordinary rows. js/topbar-menu.js toggles
   .is-open + aria-expanded. ---- */
.lp-privnav { position: relative; display: flex; align-items: center; }
.lp-privnav-btn { display: inline-flex; align-items: center; gap: 6px; width: auto; }
.lp-privnav-caret {
  width: 6px; height: 6px; margin-top: -3px; flex: none;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .15s var(--ease-out);
}
.lp-privnav-btn[aria-expanded="true"] { color: var(--ink); background: var(--panel-2); }
.lp-privnav-btn[aria-expanded="true"] .lp-privnav-caret { transform: rotate(225deg); margin-top: 2px; }
.lp-privnav-menu {
  display: none; position: absolute; z-index: 80; top: calc(100% + 10px); right: 0;
  min-width: 224px; padding: 6px; flex-direction: column; gap: 2px;
  background: #fff; border: 1px solid var(--edge); border-radius: 12px; box-shadow: var(--shadow);
}
.lp-privnav-menu.is-open { display: flex; }
.lp-privnav-menu .pillnav-action[hidden] { display: none !important; }
@media (min-width: 1080px) {
  .lp-privnav-menu .pillnav-action, .lp-privnav-menu a {
    display: flex; width: 100%; padding: 9px 11px; border-radius: 8px;
    font-size: 13.5px; font-weight: 500; color: var(--slate); text-align: left; white-space: nowrap;
  }
  /* 1080–1200: eight text links + two buttons only fit the bar with the
     links set a shade tighter (measured: 41px over at exactly 1080). */
  @media (max-width: 1200px) {
    :is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav a,
    :is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav .lp-privnav-btn { padding: 7px 8px; font-size: 13.5px; }
    :is(#homePage, #explorePage, #searchPage, #rolesPage) .pillnav { margin-right: 2px; }
    :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-brandline .beta-badge { display: none; }
  }
}
@media (max-width: 1079px) {
  .lp-privnav, .lp-privnav-menu, .lp-privnav-menu.is-open { display: contents; }
  .lp-privnav-btn { display: none !important; }
}

/* ---- Type: the small labels go sans; mono stays where it means "code". ---- */
#homePage .lp3 .lp-kicker { font-family: var(--font); font-size: 12px; letter-spacing: .1em; color: var(--slate); font-weight: 650; }
#homePage .lp3 .lp-editors-label { font-family: var(--font); font-size: 11.5px; letter-spacing: .1em; color: var(--slate-2); font-weight: 650; }
#homePage .lp3 .lp-editors-links a { color: var(--slate); font-weight: 500; font-size: 14px; }
#homePage .lp3 .lp-editors-links a:hover { color: var(--ink); background: var(--panel-2); }
#homePage .lp3 .lp-editors-links a + a::before { background: var(--edge); }
#homePage .lp3 .lp-hero-fine { font-family: var(--font); font-size: 13.5px; color: var(--slate-2); letter-spacing: 0; }
#homePage .lp3 .lp-stage-ghost { color: var(--slate-2); }
#homePage .lp3 .lp3-pillar { border-left-color: var(--ink); }
#homePage .lp3 .lp-faq-a p { color: var(--slate); font-size: 15px; }
#homePage .lp3 .lp-quiet-note { font-size: 14px; }
#homePage .lp3 .lp-quiet-note .link-btn { color: var(--iris-ink); }
#homePage .lp3 .lp-foot-h { font-family: var(--font); font-size: 11.5px; letter-spacing: .1em; color: var(--slate-2); font-weight: 700; }
#homePage .lp3 .lp-foot-tag { color: var(--slate); }
#homePage .lp3 .lp-foot-col a, #homePage .lp3 .lp-foot-col .link-btn { color: var(--slate); font-size: 14px; }
#homePage .lp3 .lp-foot-mark { color: var(--ink); }
#homePage .lp3 .lp-foot-mono, #homePage .lp3 .lp-foot-links, #homePage .lp3 .lp-foot-links .link-btn,
#homePage .lp3 .lp-foot-maker-row { font-family: var(--font); font-size: 13px; color: var(--slate-2); }
#homePage .lp3 .lp-foot-social a { opacity: 1; color: var(--slate); font-size: 13px; }
#homePage .lp3 .lp-foot-social a:hover { color: var(--ink); }
#homePage .lp3 .lp-foot-maker { color: var(--slate); }

/* ---- The two card variants, one family. Shared: 10px radius, 1px --edge,
   the same lift + ink border on hover, the same title type. Lessons: a
   white card with the lesson's own dark poster edge to edge. Editable
   diagrams: a cream notebook leaf (ruled body) with a SMALLER dark preview
   inset at the top — see the tech-band rules in the v4 block. ---- */
#homePage .lp3 .lp-course { background: #fff; padding: 0; }
#homePage .lp3 .lp-course .lp-sample-art.lp-course-art { border-radius: 0; }
#homePage .lp3 .lp-course .lp-sample-body { margin: 0; background: none; padding: 12px 14px 14px; }
#homePage .lp3 .lp-course-grid-compact .lp-sample-body { padding: 12px 13px 13px; }
#homePage .lp3 .lp-sample-art img { transition: opacity .3s ease; }
#homePage .lp3 .lp-sample:hover .lp-sample-art.has-img img { filter: none; }

/* ---- v4.6b: the Visual Learning doors (Sep 8 2026). A third, quieter
   link in the hero's CTA row and a CTA pair on the /visual-learning hero,
   both opening the 27th editor (/learn, mode visuallearning). ---- */
#homePage .lp3 .lp-btn-link {
  background: none; border-color: transparent; color: var(--ink); padding-inline: 8px;
  text-decoration: underline; text-decoration-color: var(--iris); text-underline-offset: 4px; text-decoration-thickness: 2px;
}
#homePage .lp3 .lp-btn-link:hover { color: var(--ink); text-decoration-color: var(--ink); transform: none; box-shadow: none; }
/* ---- How it works (#lpHow; operator, Sep 27 2026) ----
   The home page's one direction: pick a type, start from a ready-made,
   press Explain — three numbered cards, then the editors as a quiet row of
   links. Tokens are the desk pins (--panel/--edge/--ink/--slate/--iris-*),
   the same the rest of the page uses; nothing new is invented. */
#homePage .lp3 .lp-how-steps {
  list-style: none; margin: clamp(22px, 3vw, 34px) 0 0; padding: 0;
  display: grid; gap: clamp(14px, 1.6vw, 20px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
}
#homePage .lp3 .lp-how-step {
  position: relative; padding: clamp(20px, 2.4vw, 28px);
  background: var(--panel); border: 1px solid var(--edge); border-radius: 16px;
  box-shadow: var(--shadow-sm);
}
#homePage .lp3 .lp-how-n {
  display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 999px;
  background: var(--iris-soft); color: var(--iris-ink); font-weight: 750; font-size: 15px;
  margin-bottom: 14px;
}
#homePage .lp3 .lp-how-step h3 {
  margin: 0 0 6px; font-size: clamp(17px, 1.5vw, 19px); font-weight: 680;
  letter-spacing: -0.01em; line-height: 1.3; color: var(--ink);
}
#homePage .lp3 .lp-how-step p { margin: 0; color: var(--slate); line-height: 1.6; font-size: 15px; }
/* ---- Editor doors (.lp-eds; operator, Sep 27 2026) ----
   A sliding rail of the most-used editors, right under the hero: each card
   shows a small picture of its diagram type, so the eye finds "Flowchart" by
   its shape before it reads the word. Native horizontal scroll with snap
   (swipe and trackpad just work); js/landing.js adds the arrows and a slow
   auto-advance that stops the moment a person touches the rail. */
/* Tight to the hero (operator, Sep 27 2026): the hero and the editor strip
   read as one first screen, so neither carries the scene-sized padding the
   rest of the page uses. */
/* A little more air between the first screen's sections (operator, Sep 28
   2026 — hero, editor strip and reel had been pulled too close). */
#homePage .lp3 .lp-hero { padding: clamp(20px, 4vh, 44px) 0 clamp(28px, 4.5vh, 48px); }
#homePage .lp3 .lp-eds { padding-block: 0 clamp(36px, 5vw, 64px); }
/* The highlighted phrase is ONE unit: "animated diagrams." broke across two
   lines at 1280px (it needs ~9.4x the font size), which split the marker in
   two. On the two-column layout the size follows the column and the phrase
   never wraps; the single-column phone layout already fits it. */
@media (min-width: 980px) {
  #homePage .lp3 .home-hero { font-size: clamp(38px, 4.1vw, 64px); }
  #homePage .lp3 .home-hero .lp-warm { white-space: nowrap; }
}
#homePage .lp3 .lp-eds-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px;
}
#homePage .lp3 .lp-eds-title {
  margin: 0; white-space: nowrap; font-family: var(--font); font-size: 12px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--slate-2);
}
#homePage .lp3 .lp-eds-ctrl { display: flex; align-items: center; gap: 8px; }
#homePage .lp3 .lp-eds-all {
  margin-right: 6px; font-size: 14px; font-weight: 650; color: var(--iris-ink); text-decoration: none; white-space: nowrap;
}
#homePage .lp3 .lp-eds-all:hover { text-decoration: underline; text-underline-offset: 3px; }
#homePage .lp3 .lp-eds-arrow {
  display: grid; place-items: center; width: 38px; height: 38px; padding: 0; border-radius: 999px;
  background: var(--panel); border: 1.5px solid var(--ink); color: var(--ink); cursor: pointer;
  box-shadow: 2px 2px 0 var(--ink);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), opacity var(--dur-2);
}
#homePage .lp3 .lp-eds-arrow svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
#homePage .lp3 .lp-eds-arrow:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
#homePage .lp3 .lp-eds-arrow:active { transform: translate(1px, 1px); box-shadow: 0 0 0 var(--ink); }
#homePage .lp3 .lp-eds-arrow:focus-visible { outline: 2px solid var(--iris); outline-offset: 2px; }
#homePage .lp3 .lp-eds-arrow[disabled] { opacity: .35; cursor: default; transform: none; box-shadow: 2px 2px 0 var(--ink); }
/* The rail bleeds to the page edge on the right so a half-card says "more
   this way"; the mask fades it instead of cutting it. */
#homePage .lp3 .lp-eds-rail {
  margin-right: calc(-1 * clamp(16px, 4vw, 56px));
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 64px), transparent);
          mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 64px), transparent);
}
#homePage .lp3 .lp-eds-track {
  display: flex; gap: 14px; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-padding-inline: 2px; scrollbar-width: none;
  padding: 4px 64px 12px 2px; outline: none;
}
#homePage .lp3 .lp-eds-track::-webkit-scrollbar { display: none; }
#homePage .lp3 .lp-eds-track:focus-visible { outline: 2px solid var(--iris); outline-offset: 4px; border-radius: 14px; }
#homePage .lp3 .lp-ed {
  position: relative; flex: 0 0 clamp(148px, 13vw, 168px); scroll-snap-align: start;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel); border: 1.5px solid var(--ink); border-radius: 14px;
  color: var(--ink); text-decoration: none; box-shadow: 3px 3px 0 var(--ink);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
#homePage .lp3 .lp-ed:hover { transform: translate(-2px, -3px) rotate(-.6deg); box-shadow: 5px 6px 0 var(--ink); }
#homePage .lp3 .lp-ed:focus-visible { outline: 2px solid var(--iris); outline-offset: 3px; }
#homePage .lp3 .lp-ed-art {
  position: relative; display: grid; place-items: center; aspect-ratio: 150 / 96; padding: 30px 12px 6px;
  background: var(--panel-2); border-bottom: 1.5px solid var(--ink); overflow: hidden;
}
#homePage .lp3 .lp-ed-art svg { width: 100%; height: 100%; transition: transform var(--dur-3) var(--ease-out); }
#homePage .lp3 .lp-ed:hover .lp-ed-art svg { transform: scale(1.07); }
/* A sheen crosses every picture once when the rail first comes into view
   (.lp-eds.is-lit, js/landing.js) — the moment that says "these are live". */
#homePage .lp3 .lp-ed-art::after {
  content: ""; position: absolute; inset: -20% auto -20% -60%; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.75), transparent);
  transform: skewX(-18deg); opacity: 0; pointer-events: none;
}
#homePage .lp3 .lp-eds.is-lit .lp-ed-art::after { animation: lpEdSheen 1.1s var(--ease-out) calc(var(--k, 0) * 90ms) 1 both; }
@keyframes lpEdSheen { 0% { left: -60%; opacity: 0; } 15% { opacity: 1; } 100% { left: 125%; opacity: 0; } }
/* The count: how many ready-made diagrams wait behind the door. Filled from
   the live catalogue; hidden until then, never shown as 0. */
#homePage .lp3 .lp-ed-count {
  position: absolute; top: 8px; left: 8px; z-index: 1;
  padding: 3px 8px 3px 7px; border-radius: 999px;
  background: var(--iris); color: var(--on-signal, #1a1206); border: 1.5px solid var(--ink);
  box-shadow: 2px 2px 0 var(--ink);
  font-size: 11px; font-weight: 750; line-height: 1.2; letter-spacing: .01em; white-space: nowrap;
  animation: lpEdPop .5s cubic-bezier(.34, 1.7, .5, 1) calc(var(--k, 0) * 70ms) both;
}
#homePage .lp3 .lp-ed-count[hidden] { display: none; }
@keyframes lpEdPop { from { opacity: 0; transform: scale(.4) rotate(-12deg); } to { opacity: 1; transform: none; } }
#homePage .lp3 .lp-ed-body { display: flex; flex-direction: column; gap: 2px; padding: 9px 11px 10px; }
#homePage .lp3 .lp-ed-name { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
#homePage .lp3 .lp-ed-desc { font-size: 12px; color: var(--slate); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
#homePage .lp3 .lp-ed-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 6px; }
#homePage .lp3 .lp-ed-go { font-size: 12px; font-weight: 700; color: var(--iris-ink); white-space: nowrap; }
#homePage .lp3 .lp-ed-stat { font-size: 11.5px; font-weight: 600; color: var(--slate-2); white-space: nowrap; }
#homePage .lp3 .lp-ed-stat[hidden] { display: none; }
#homePage .lp3 .lp-ed:hover .lp-ed-go span { display: inline-block; transform: translateX(3px); transition: transform var(--dur-2) var(--ease-out); }
@media (max-width: 560px) {
  #homePage .lp3 .lp-eds-all { display: none; }
  #homePage .lp3 .lp-ed { flex-basis: 58vw; }
}
@media (prefers-reduced-motion: reduce) {
  #homePage .lp3 .lp-ed, #homePage .lp3 .lp-eds-arrow, #homePage .lp3 .lp-ed-art svg { transition: none; }
  #homePage .lp3 .lp-ed:hover, #homePage .lp3 .lp-ed:hover .lp-ed-art svg { transform: none; }
  #homePage .lp3 .lp-ed-count, #homePage .lp3 .lp-eds.is-lit .lp-ed-art::after { animation: none; }
}

/* ---- The example reel (#lpSvgShow; Sep 27 2026) ----
   Same rail as the editor strip (.lp-eds*), different cards: an animated
   export in a 16:10 frame and a two-part caption (type, then subject). About
   30% smaller than the old four-up tiles, so a laptop shows five and the
   rail says "there is more" by itself. */
#homePage .lp3 .lp-reel-sec { padding-top: 0; }
#homePage .lp3 .lp-eds + .lp-reel-sec { margin-top: 0; }
#homePage .lp3 .lp-live-dot {
  display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 999px; vertical-align: 1px;
  background: var(--iris); border: 1.5px solid var(--ink); animation: lpLive 1.8s ease-in-out infinite;
}
@keyframes lpLive { 50% { transform: scale(.6); opacity: .55; } }
#homePage .lp3 .lp-rail-hint { margin-right: 6px; font-size: 12.5px; color: var(--slate-2); white-space: nowrap; }
#homePage .lp3 .lp-reel-card {
  flex: 0 0 clamp(200px, 17vw, 232px); scroll-snap-align: start;
  display: flex; flex-direction: column; gap: 8px; padding: 0; margin: 0;
  background: none; border: 0; text-align: left; cursor: zoom-in; color: var(--ink); font: inherit;
}
#homePage .lp3 .lp-reel-stage {
  position: relative; display: block; aspect-ratio: 16 / 10; overflow: hidden;
  background: var(--panel); border: 1.5px solid var(--ink); border-radius: 12px; box-shadow: 3px 3px 0 var(--ink);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
#homePage .lp3 .lp-reel-stage img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
#homePage .lp3 .lp-reel-card:hover .lp-reel-stage { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 var(--ink); }
#homePage .lp3 .lp-reel-card:focus-visible { outline: none; }
#homePage .lp3 .lp-reel-card:focus-visible .lp-reel-stage { outline: 2px solid var(--iris); outline-offset: 3px; }
#homePage .lp3 .lp-reel-name { display: flex; flex-direction: column; gap: 1px; font-size: 13.5px; font-weight: 650; line-height: 1.3; padding-left: 2px; }
#homePage .lp3 .lp-reel-kind { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--iris-ink); }
#homePage .lp3 .lp-reel-free {
  position: absolute; top: 7px; right: 7px; padding: 2px 8px; border-radius: 999px;
  background: var(--iris); color: var(--on-signal, #1a1206); border: 1.5px solid var(--ink);
  font-size: 11px; font-weight: 750;
}
#homePage .lp3 .lp-eds-track.is-dragging { scroll-snap-type: none; cursor: grabbing; user-select: none; }
#homePage .lp3 .lp-eds-track.is-dragging * { cursor: grabbing; }
@media (max-width: 560px) {
  #homePage .lp3 .lp-rail-hint { display: none; }
  #homePage .lp3 .lp-reel-card { flex-basis: 64vw; }
}
@media (prefers-reduced-motion: reduce) {
  #homePage .lp3 .lp-live-dot { animation: none; }
  #homePage .lp3 .lp-reel-stage { transition: none; }
}

/* ---- "animated", animated (hero h1; operator, Sep 27 2026 — for review) ----
   The one word that names the product's difference moves: its letters rise
   in one by one on load, then a small wave runs through them every few
   seconds. Letters are plain inline spans (no aria-hidden copy), so the h1
   still reads "animated" to a screen reader and a crawler. transform only —
   the line box never moves, so nothing around it reflows. */
#homePage .lp3 .lp-aw { display: inline-block; white-space: nowrap; }
#homePage .lp3 .lp-aw-l {
  display: inline-block; transform-origin: 50% 85%;
  animation: lpAwIn .62s cubic-bezier(.34, 1.6, .5, 1) calc(.25s + var(--i) * .07s) both,
             lpAwWave 6.4s ease-in-out calc(2.2s + var(--i) * .08s) infinite;
}
@keyframes lpAwIn {
  from { opacity: 0; transform: translateY(.45em) rotate(-8deg) scale(.8); }
  to   { opacity: 1; transform: none; }
}
@keyframes lpAwWave {
  0%, 10%, 100% { transform: none; }
  4% { transform: translateY(-.14em) rotate(-3deg); }
  7% { transform: translateY(.03em); }
}
@media (prefers-reduced-motion: reduce) {
  #homePage .lp3 .lp-aw-l { animation: none; }
}

/* ---- The header band (operator, Sep 27 2026) ------------------------------
   Every marketing header (home, Explore, Search, Roles) sits on one KRAFT
   band (#efe5cf) — the same kraft as the tape holding the hero's demo sheet,
   a clear step darker than the paper page, closed by an ink rule. It went
   dark navy first and read as a separate object on the paper; kraft keeps it
   the page's own material. Ink text; the CTA wears the page's sticker style
   (ink border + hard offset shadow). All colours are the --hdr-* tokens, so a
   re-tint is one edit. The phone drop-down and the Privacy pop-up stay white
   panels. */
:root { --hdr-bg: #efe5cf; --hdr-ink: #171821; --hdr-dim: #45464f; --hdr-line: #171821;
  --hdr-btn-line: rgba(23, 24, 33, .30); --hdr-hover: rgba(23, 24, 33, .07); --hdr-cta-ink: #171821;
  --hdr-cta-line: #171821; --hdr-cta-shadow: 2px 2px 0 #171821; }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top,
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top.is-scrolled {
  background: var(--hdr-bg); border-bottom: 1px solid var(--hdr-line);
  -webkit-backdrop-filter: none; backdrop-filter: none; --wordmark: var(--hdr-ink);
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-brandline .wordmark { color: var(--hdr-ink); }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-brandline .lock-icon { color: var(--hdr-ink); }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .beta-badge {
  color: var(--hdr-dim); background: transparent; border-color: var(--hdr-line);
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-tbtn {
  color: var(--hdr-ink); border-color: var(--hdr-btn-line); background: transparent;
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-tbtn:hover { border-color: var(--hdr-ink); background: var(--hdr-hover); }
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-tbtn-cta,
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-tbtn-cta:hover {
  background: var(--iris); color: var(--hdr-cta-ink); border: 1.5px solid var(--hdr-cta-line, var(--iris)); box-shadow: var(--hdr-cta-shadow, none); transform: none;
}
:is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-tbtn-cta:hover { background: var(--iris-bright, var(--iris)); border-color: var(--iris-bright, var(--iris)); }
@media (min-width: 1080px) {
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .pillnav > a,
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .pillnav > .pillnav-action,
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-privnav-btn { color: var(--hdr-dim); }
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .pillnav > a:hover,
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .pillnav > .pillnav-action:hover,
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-privnav-btn:hover,
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .lp-privnav-btn[aria-expanded="true"] {
    color: var(--hdr-ink); background: var(--hdr-hover);
  }
  :is(#homePage, #explorePage, #searchPage, #rolesPage) .lp-top .pillnav > a[aria-current="page"] { color: var(--hdr-ink); background: none; }
}
/* The editor's lockup, same rule: the mark's strokes match the word instead
   of a grey (it was --slate, #c4c4c4, beside a white word). */
.brand .brand-mark { color: var(--wordmark); }

/* ---- Open source band (#lpOss; operator, Sep 28 2026) ----
   One card on the desk: the pitch on the left, two links on the right. Same
   ink edge + hard offset shadow as the editor doors; tokens only. */
#homePage .lp3 .lp-oss { padding-block: 0 clamp(36px, 5vw, 64px); }
#homePage .lp3 .lp-oss-card {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 18px 32px; align-items: center;
  padding: clamp(20px, 3vw, 30px) clamp(20px, 3vw, 34px);
  background: var(--panel); border: 1.5px solid var(--ink); border-radius: 16px; box-shadow: 3px 3px 0 var(--ink);
}
#homePage .lp3 .lp-oss-eyebrow {
  font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--slate-2);
}
#homePage .lp3 .lp-oss-title { margin: 6px 0 8px; font-size: clamp(24px, 2.6vw, 32px); line-height: 1.15; letter-spacing: -.02em; color: var(--ink); }
#homePage .lp3 .lp-oss-text { margin: 0; max-width: 62ch; color: var(--slate); font-size: 16px; line-height: 1.55; }
#homePage .lp3 .lp-oss-actions { display: flex; flex-direction: column; gap: 10px; }
#homePage .lp3 .lp-oss-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; white-space: nowrap;
  padding: 11px 18px; border-radius: 999px; border: 1.5px solid var(--ink); background: var(--panel);
  color: var(--ink); font-weight: 700; font-size: 15px; text-decoration: none; box-shadow: 2px 2px 0 var(--ink);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
#homePage .lp3 .lp-oss-btn svg { width: 18px; height: 18px; fill: currentColor; }
#homePage .lp3 .lp-oss-btn.is-primary { background: var(--ink); color: var(--paper); }
#homePage .lp3 .lp-oss-btn:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
#homePage .lp3 .lp-oss-btn:focus-visible { outline: 2px solid var(--iris); outline-offset: 3px; }
@media (max-width: 760px) {
  #homePage .lp3 .lp-oss-card { grid-template-columns: 1fr; }
  #homePage .lp3 .lp-oss-actions { flex-direction: row; flex-wrap: wrap; }
}
@media (prefers-reduced-motion: reduce) { #homePage .lp3 .lp-oss-btn { transition: none; } }
