/* demo.css — the /demo STAGE, not the components. Every product surface inside the stage is styled by
   demo-surfaces.css, which is generated from the app's own CSS; nothing here restyles a component.
   ⚠ The only rules below that touch app markup are LAYOUT for the fixed viewport the app is shown in (the app
   assumes a 100vh window; the stage gives it a 1280×800 one). Colour, type and spacing stay the app's. */

:root {
  --dm-field: #100d0a;
  --dm-field-2: #1a1410;
  --dm-cream: #f6f0e6;
  --dm-cream-2: #cfc6b9;
  --dm-cream-3: #9a9082;
  --dm-terra: #e07a54;
  --dm-terra-d: #c65a36;
  --dm-line: rgba(239, 233, 223, 0.10);
  --dm-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --dm-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
  --dm-sans: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --dm-ease: cubic-bezier(.2, .7, .1, 1);
}

html, body { margin: 0; background: var(--dm-field); color: var(--dm-cream); }
body { font-family: var(--dm-sans); -webkit-font-smoothing: antialiased; }
*, *::before, *::after { box-sizing: border-box; }

/* ── the page around the stage ───────────────────────────────────────────────────────────────────── */
.dm-page { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; padding: 18px 20px 22px; gap: 14px; }
.dm-top { display: flex; align-items: center; justify-content: space-between; max-width: 1400px; width: 100%; margin: 0 auto; }
.dm-brand { display: inline-flex; align-items: center; gap: 9px; color: var(--dm-cream); text-decoration: none;
  font-family: var(--dm-serif); font-size: 17px; }
.dm-brand svg { width: 20px; height: 20px; }
.dm-top-cta { font-family: var(--dm-mono); font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--dm-cream-2); text-decoration: none; border-bottom: 1px solid transparent; padding-bottom: 2px; }
.dm-top-cta:hover { color: var(--dm-terra); border-bottom-color: var(--dm-terra); }
.dm-box { position: relative; flex: 1 1 auto; width: 100%; max-width: 1400px; margin: 0 auto; min-height: 240px; aspect-ratio: 16 / 9; max-height: calc(100dvh - 140px); }
.dm-box.is-45 { aspect-ratio: 4 / 5; max-width: 720px; }

/* controls: play/pause · scrub · replay */
.dm-controls { display: flex; align-items: center; gap: 14px; max-width: 1400px; width: 100%; margin: 0 auto; }
.dm-btn { appearance: none; background: none; border: 1px solid rgba(239, 233, 223, 0.22); color: var(--dm-cream);
  border-radius: 999px; height: 34px; min-width: 34px; padding: 0 12px; font: 500 12px/1 var(--dm-mono); letter-spacing: .06em;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer; }
.dm-btn:hover { border-color: var(--dm-terra); color: var(--dm-terra); }
.dm-btn:focus-visible { outline: 2px solid var(--dm-terra); outline-offset: 2px; }
.dm-btn svg { width: 12px; height: 12px; fill: currentColor; }
.dm-scrub { position: relative; flex: 1 1 auto; height: 34px; display: flex; align-items: center; }
.dm-scrub input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0; }
.dm-track { position: relative; height: 3px; width: 100%; background: rgba(239, 233, 223, 0.14); border-radius: 3px; }
.dm-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--dm-terra); border-radius: 3px; }
.dm-tick { position: absolute; top: -3px; width: 1px; height: 9px; background: rgba(239, 233, 223, 0.28); }
.dm-knob { position: absolute; top: 50%; width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; border-radius: 50%; background: var(--dm-cream); }
.dm-scrub input:focus-visible + .dm-track { outline: 2px solid var(--dm-terra); outline-offset: 6px; }
.dm-time { font: 500 12px/1 var(--dm-mono); color: var(--dm-cream-3); min-width: 88px; text-align: right; font-variant-numeric: tabular-nums; }

/* capture + loop: the stage is the whole page */
.dm-cap .dm-top, .dm-cap .dm-controls, .dm-loop .dm-top, .dm-loop .dm-controls { display: none; }
.dm-cap .dm-page, .dm-loop .dm-page { padding: 0; min-height: 0; height: 100vh; }
.dm-cap .dm-box, .dm-loop .dm-box { max-width: none; max-height: none; height: 100vh; aspect-ratio: auto; }

/* ── the stage: a fixed logical frame, scaled to fit (demo-engine.js fitStage) ────────────────────── */
.dm-stage { position: absolute; left: 50%; top: 50%; transform-origin: 50% 50%; overflow: hidden;
  background: radial-gradient(120% 90% at 78% 12%, #221a14 0%, var(--dm-field) 55%, #0b0907 100%); }
.dm-stage.dm-jump, .dm-stage.dm-jump * { transition: none !important; }

/* headlines — two elements, cross-faded (ruled 2026-09-14, cut 4: "Three chapter turns").
   .dm-copy is the full-screen headline, shown only in a chapter turn's intro; .dm-caption is the large line top-left
   above the frame, where every other headline dissolves in place. Nothing changes size or position between them. */
.dm-copy { position: absolute; transition: opacity .6s var(--dm-ease); }
.dm-stage:not(.is-intro) .dm-copy { opacity: 0; }
.dm-kicker { position: relative; height: 16px; font: 500 15px/1 var(--dm-mono); letter-spacing: .16em; color: var(--dm-terra); }
.dm-kicker span, .dm-head { position: absolute; left: 0; top: 0; opacity: 0; transform: translateY(14px);
  transition: opacity .55s var(--dm-ease), transform .7s var(--dm-ease); }
.dm-kicker span.is-on, .dm-head.is-on { opacity: 1; transform: none; }
.dm-heads { position: relative; margin-top: 26px; }
.dm-head, .dm-capline { margin: 0; font-family: var(--dm-serif); font-weight: 500; letter-spacing: -0.012em; color: var(--dm-cream);
  font-variation-settings: 'opsz' 144; text-wrap: balance; }
.dm-caption { position: absolute; transition: opacity .6s var(--dm-ease); }
.dm-stage.is-intro .dm-caption { opacity: 0; }
.dm-capline { position: absolute; left: 0; top: 0; opacity: 0; transition: opacity .6s var(--dm-ease); }
.dm-capline.is-nowrap { white-space: nowrap; }
.dm-capline.is-on { opacity: 1; }

/* the screen: a quiet window around the real app (logical size = its play size; the intro is a transform) */
.dm-screen { position: absolute; border-radius: 14px; overflow: hidden; background: #0d0b09; transform-origin: 0 0;
  transition: transform .95s var(--dm-ease);
  box-shadow: 0 0 0 1px rgba(239, 233, 223, 0.10), 0 40px 120px rgba(0, 0, 0, 0.55), 0 12px 30px rgba(0, 0, 0, 0.35); }
.dm-chrome { position: absolute; left: 0; right: 0; top: 0; height: 44px; display: flex; align-items: center; gap: 14px; padding: 0 16px;
  background: #1b1612; border-bottom: 1px solid rgba(239, 233, 223, 0.08); }
.dm-dots { display: flex; gap: 7px; }
.dm-dots i { width: 11px; height: 11px; border-radius: 50%; background: rgba(239, 233, 223, 0.16); }
.dm-url { position: relative; flex: 1 1 auto; max-width: 560px; margin: 0 auto; height: 26px; border-radius: 7px; background: rgba(239, 233, 223, 0.06);
  font: 400 13px/26px var(--dm-sans); color: var(--dm-cream-3); text-align: center; }
.dm-url span { position: absolute; inset: 0; opacity: 0; transition: opacity .35s var(--dm-ease); }
.dm-url span.is-on { opacity: 1; }
.dm-url b { color: var(--dm-cream-2); font-weight: 400; }
/* ⭐ WHOSE SCREEN THIS IS (2026-09-15: "make that more of an obvious transition so viewer knows what they are seeing"). A demo
   label, not app chrome: it names the viewer in the window bar and changes, with a chapter turn, when the fund's side begins.
   The fund's label is the one filled terracotta, so the switch reads at a glance. */
.dm-who { position: absolute; right: 16px; top: 9px; height: 26px; }
.dm-who span { position: absolute; right: 0; top: 0; height: 26px; display: inline-flex; align-items: center; padding: 0 12px; white-space: nowrap;
  border-radius: 13px; font: 600 12px/1 var(--dm-sans); letter-spacing: .06em; text-transform: uppercase; opacity: 0;
  transform: translateY(-4px); transition: opacity .45s var(--dm-ease), transform .45s var(--dm-ease); }
.dm-who span.is-on { opacity: 1; transform: none; }
.dm-who .dm-who-f { color: var(--dm-cream-2); background: rgba(239, 233, 223, 0.08); box-shadow: inset 0 0 0 1px rgba(239, 233, 223, 0.18); }
.dm-who .dm-who-v { color: #fff; background: var(--dm-terra-d); }
/* 4:5 is 1080 wide: the URL narrows so the label keeps its room beside it */
.dm-stage.is-45 .dm-url { max-width: 380px; margin-left: 40px; }
.dm-screen.is-fund .dm-chrome { background: #2a1a12; }
.dm-stage.is-intro .dm-screen { transform: var(--screen-intro); }
/* ⛔ FULLY HIDDEN, NEVER DIMMED (Bret, 2026-09-15). `visibility: hidden` rather than a low opacity: a faint shell
   is the bug, not a softer version of it, and opacity would still composite the rounded corner and the chrome bar
   against the card. ⚠ `visibility` also leaves layout untouched, so the shell is exactly where the push-in expects
   it the instant this comes off. */
.dm-stage.is-prereveal .dm-screen { visibility: hidden; }
.dm-stage.is-45 .dm-screen { border-radius: 0; }
.dm-viewport { position: absolute; left: 0; right: 0; top: 44px; bottom: 0; overflow: hidden; background: #f5f2ed; }
.dm-viewport:has(.dm-scene[data-scene="cascade"].is-on), .dm-viewport:has(.dm-scene[data-scene="p"].is-on) { background: #15110d; }

/* scenes inside the viewport: 1280×800 app pixels, moved by the camera */
.dm-scene { position: absolute; left: 0; top: 0; width: var(--app-w); height: var(--app-h); transform-origin: 0 0; opacity: 0;
  transition: opacity .45s var(--dm-ease); pointer-events: none; }
.dm-scene.is-on { opacity: 1; }
.dm-app, .dm-p { width: var(--app-w); height: var(--app-h); overflow: hidden; position: relative; }

/* ⚠ LAYOUT ONLY: the app is a 100vh shell; the stage gives it a fixed window. */
.dm-app .app { height: var(--app-h); }
.dm-app .toast { position: absolute; }
.dm-app .gl-moment { position: absolute; }
.dm-app .fit-overlay { position: absolute; overflow: visible; }
.dm-p { overflow: hidden; height: calc(var(--app-h) + 100px); background: #15110d; }
.dm-app.dm-tall, .dm-app.dm-tall .app { height: var(--app-tall); }
.dm-cascade { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.dm-app.dm-pg { background: #100d0a; }
.dm-pg-tri { position: absolute; inset: 0; }
/* ⚠ THE ONE TIMING DEPARTURE FROM THE APP'S PLAYGROUND: the triangle entry runs at 70% of its 3 s so the grounded Venn
   lands inside the ~2–3 s the bridge was ruled to give it. The keyframes and easing are the app's. */
@media (prefers-reduced-motion: no-preference) {
  .dm-pg .pg-tri.anim .tri-a, .dm-pg .pg-tri.anim .tri-b { animation-duration: 2.1s; }
  .dm-pg .pg-tri.anim .lens { animation-duration: .6s; animation-delay: 1.8s; }
  .dm-pg .pg-tri.anim .labels { animation-duration: .5s; animation-delay: 2.05s; }
}
.dm-p-scroll { will-change: transform; }
/* ⭐ THE FUND'S SHOW-INTEREST BLOCK ON THE PERCH PAGE (2026-09-15). Hand-written HERE and never in
   demo-surfaces.css, which is GENERATED from the app's own stylesheets and carries a `--check` that fails on
   drift — a rule added there would be wiped by the next regeneration, or turn the check red.
   ⛔ It has no app counterpart to be derived FROM: production `/p/` has no such control (see sceneP's note), so
   this is demo-only styling by necessity, not by shortcut. It borrows the page's own tokens so it still reads as
   part of the perch rather than as something pasted onto it. */
.dm-p .p-act { margin: 40px 0 8px; padding: 26px; border-radius: 10px;
  background: var(--paper-2); border: 1px solid var(--line); }
.dm-p .p-act-btn { font: 600 16px/1 var(--sans, inherit); color: #fff; background: var(--accent);
  border: 0; border-radius: 8px; padding: 14px 22px; cursor: pointer; }
.dm-p .p-act-note { margin: 12px 0 0; font-size: 14px; color: var(--ink-3); }
.dm-p .p-act-head { margin: 0 0 6px; font-family: var(--serif); font-weight: 500; font-size: 21px; color: var(--ink); }
.dm-p .p-act-sub { margin: 0; font-size: 15px; color: var(--ink-2); }
/* ⛔ THE BUTTON WRAPPER IS DELIBERATELY *NOT* `.dm-alt`. That class is `display:none !important` until `.dm-show`
   is added, so a wrapper carrying it would start INVISIBLE and the fund would click nothing — caught before the
   first render, and worth stating because every other two-state pair in this file DOES use `.dm-alt`.
   ⭐ The pair is asymmetric on purpose: the button starts visible and is removed by `.dm-gone`; the confirmation
   starts hidden as `.dm-alt` and is revealed by `.dm-show`. Both flip on the same cue, so there is no frame where
   the block is empty and the page jumps. */
/* beat 4: the drafted fields land one at a time (a cue adds .is-in) */
.dm-land { opacity: 0; transform: translateY(10px); transition: opacity .35s ease, transform .35s ease; }
.dm-land.is-in { opacity: 1; transform: none; }

/* beat 4's transformation (2026-09-15): the Details view recedes, the deck's title slide grows into the backdrop band, and the
   founder perch broadsheet assembles one accepted field at a time. The broadsheet's own look is the app's (demo-surfaces.css,
   rules rooted at .perch); only the entrance is set here. */
.dm-details { transition: opacity .6s var(--dm-ease), transform .8s var(--dm-ease); transform-origin: 50% 20%; }
.dm-details.dm-recede { opacity: 0; transform: scale(.965); }
.dm-perchview { position: absolute; left: 0; top: 0; width: var(--app-w); min-height: var(--app-tall); z-index: 30; opacity: 0;
  background: #15110d; transition: opacity .6s var(--dm-ease); }
.dm-perchview.is-on { opacity: 1; }
.dm-perchview .perch { min-height: var(--app-tall); }
.dm-pv { opacity: 0; transform: translateY(16px); transition: opacity .55s var(--dm-ease), transform .7s var(--dm-ease); }
.dm-pv.is-in { opacity: 1; transform: none; }
.dm-pv-bd { transform: none; transition: opacity .9s var(--dm-ease); }
.dm-morph { position: absolute; left: 0; top: 0; width: 320px; height: 180px; z-index: 35; transform-origin: 0 0; opacity: 0;
  transform: var(--m-from); border-radius: 6px; box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35); pointer-events: none;
  transition: transform .9s var(--dm-ease), opacity .45s var(--dm-ease), border-radius .9s var(--dm-ease); }
.dm-morph.is-up { opacity: 1; }
.dm-morph.is-go { transform: var(--m-to); border-radius: 0; }
.dm-morph.is-done { opacity: 0; }

/* a class a cue turns on to reveal one of several alternates (state text that changes over time).
   ⚠ It only ever HIDES. Shown, an element keeps whatever display the app's own CSS gives it — forcing one here
   overrode `.gl-moment`'s flex centring on the first render. */
.dm-alt:not(.dm-show) { display: none !important; }
.dm-gone { display: none !important; }

/* the dragged file, as the OS draws it */
.dm-ghost { position: absolute; left: 0; top: 0; display: flex; align-items: center; gap: 10px; padding: 8px 14px 8px 8px;
  background: rgba(255, 255, 255, 0.96); border-radius: 8px; box-shadow: 0 14px 40px rgba(0, 0, 0, 0.28), 0 0 0 1px rgba(0, 0, 0, 0.08);
  font: 500 13px/1.2 var(--dm-sans); color: #2d2520; opacity: 0; transition: opacity .2s ease; z-index: 30; }
.dm-ghost.is-on { opacity: 1; }
.dm-ghost .dm-doc { width: 30px; height: 38px; border-radius: 3px; background: #fff; border: 1px solid rgba(0, 0, 0, 0.12); position: relative; overflow: hidden; }
.dm-ghost .dm-doc img { width: 100%; display: block; }
.dm-ghost .dm-doc em { position: absolute; left: 0; right: 0; bottom: 0; font: 700 7px/11px var(--dm-sans); font-style: normal; text-align: center; color: #fff; background: #c9372c; }

/* the pointer */
.dm-cursor { position: absolute; left: 0; top: 0; width: 26px; height: 26px; z-index: 40; opacity: 0; pointer-events: none;
  transition: opacity .25s ease; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35)); }
.dm-cursor.is-on { opacity: 1; }
.dm-cursor svg { width: 100%; height: 100%; transition: transform .12s ease; transform-origin: 4px 3px; }
.dm-cursor.is-press svg { transform: scale(.86); }
.dm-caret { display: inline-block; width: 1.5px; height: 17px; background: #2d2520; vertical-align: text-bottom; animation: dm-blink 1.06s steps(1) infinite; }
@keyframes dm-blink { 50% { opacity: 0; } }

/* ── the close card: the door ─────────────────────────────────────────────────────────────────────── */
.dm-close { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: 0;
  transition: opacity .7s var(--dm-ease); pointer-events: none; background: radial-gradient(90% 80% at 50% 40%, #221a14 0%, var(--dm-field) 60%, #0b0907 100%); }
.dm-close.is-on { opacity: 1; pointer-events: auto; }
.dm-close-in { width: 1024px; max-width: calc(100% - 64px); text-align: left; transform: translateY(18px); transition: transform .9s var(--dm-ease); }
.dm-close.is-on .dm-close-in { transform: none; }
.dm-close-mark { display: flex; align-items: center; gap: 12px; margin-bottom: 34px; font-family: var(--dm-serif); font-size: 26px; color: var(--dm-cream); }
.dm-close-mark svg { width: 34px; height: 34px; }
.dm-close-h { margin: 0 0 34px; font-family: var(--dm-serif); font-weight: 500; font-size: 104px; line-height: .98; letter-spacing: -0.03em;
  color: var(--dm-cream); font-variation-settings: 'opsz' 144; }
.dm-close-h em { font-style: normal; color: var(--dm-terra); }
.dm-close .dm-start { background: transparent; }
/* ⭐ THE DOOR MATCHES THE HEADLINE'S WEIGHT (Bret, 2026-09-14): the email field and Start free ~56px tall, the block ~1.6×
   /start's width, a larger label; same vertical order, same centring. Sizes only — the form is /start's own markup.
   ⏳ The same change is owed on /start itself once the loop embed lands there. */
.dm-close .dm-start .s-form { width: 1024px; max-width: 100%; }
.dm-close .dm-start .s-label { color: var(--dm-cream-3); font-size: 18px; letter-spacing: .08em; margin-bottom: 12px; }
.dm-close .dm-start .s-email { background: #fffdfa; height: 56px; font-size: 22px; padding: 0 20px; border-radius: 11px; margin-bottom: 14px; }
.dm-close .dm-start .s-cta { background: var(--dm-terra-d); height: 56px; font-size: 22px; padding: 0 20px; border-radius: 11px; }
.dm-close .dm-start .s-err { font-size: 17px; }
.dm-stage.is-45 .dm-close-in { max-width: calc(100% - 160px); }

@media (prefers-reduced-motion: reduce) {
  .dm-head, .dm-kicker span, .dm-scene, .dm-close, .dm-close-in { transition-duration: .01s !important; }
  .dm-caret { animation: none; }
}
@media (max-width: 720px) {
  .dm-page { padding: 12px 16px 16px; }
  .dm-time { display: none; }
}

/* ── SOUND (2026-09-15) ───────────────────────────────────────────────────────────────────────────────
   The unmute control sits with the other transport buttons and reads its own state. ⚠ It shows the CURRENT
   state as a word ("Sound off" / "Sound on"), not the action — a button labelled "Unmute" beside a muted
   video is ambiguous about which one it is describing. */
.dm-sound .dm-sound-on { display: none; }
.dm-sound[aria-pressed="true"] .dm-sound-on { display: inline; }
.dm-sound[aria-pressed="true"] .dm-sound-off { display: none; }
.dm-sound[aria-pressed="true"] { color: var(--dm-terra); border-color: var(--dm-terra); }

/* ── THE POSTER (2026-09-16) ──────────────────────────────────────────────────────────────────────────
   Covers the stage until the first press. ⚠ It is a real <button>, not a div with a click handler: it has
   to be reachable by keyboard and announce itself, because it is now the ONLY way into the cinematic.
   ⛔ Hidden in capture and loop, which still autoplay — the recorder would film the poster over frame 0,
   and the 20-second loop is a silent autoplay surface with no controls at all. */
.dm-poster { position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px; cursor: pointer;
  background: rgba(16, 13, 10, 0.34); border: 0; color: var(--dm-cream);
  transition: opacity .3s ease, visibility .3s; }
.dm-poster[hidden] { display: none; }
.dm-poster-btn { width: 76px; height: 76px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; background: var(--dm-terra); color: #fff; box-shadow: 0 6px 26px rgba(0,0,0,.34);
  transition: transform .18s ease; }
.dm-poster-btn svg { width: 30px; height: 30px; margin-left: 4px; }
.dm-poster:hover .dm-poster-btn { transform: scale(1.06); }
.dm-poster-label { font-family: var(--dm-mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--dm-cream); opacity: .9; }
.dm-cap .dm-poster, .dm-loop .dm-poster { display: none; }
/* ⚖️ 2026-10-04 (Bret): at phone width the opening title spans the stage's centre, where the play button sat on top of
   "Get found." The button moves into the empty lower part of the box instead — the film itself is untouched.
   ⚠ It has to come AFTER the base rule above: same specificity, so source order decides. */
/* ⚖️ 2026-10-04: the play button sits UNDER the opening title at EVERY size. It began as a phone fix; with the desktop rail beside it
   the player is narrower, the scaled title's last letters reached the centred button at 1100–1440 too (measured: glyphs 35px past
   the button's edge), so a width threshold would only move the collision. Under the title, it cannot meet it. */
.dm-poster { justify-content: flex-end; padding-bottom: 8%; }
/* the stage is the positioning context for the poster */
.dm-box { position: relative; }


/* ── EMBEDDED IN /how-it-works (`?embed=1`, 2026-09-21) ──────────────────────────────────────────────
   ⭐ ONE RULE, AND IT HIDES CHROME ONLY. The host page carries its own nav and its own CTA, so the demo's
   would be a second brand mark and a second "Start free" inside somebody else's section.
   ⛔ THE PLAYER, THE CONTROLS AND THE POSTER ALL STAY. The poster especially: it is the gesture that
   licenses unmuted audio, and a framed demo with no way in is a still image.
   ⚠ Scoped to the class the head script sets, so bare /demo is untouched — which is the ruled requirement,
   not a nicety. */
.dm-embed .dm-top { display: none; }
.dm-embed .dm-page { padding-top: 0; }

/* ── THE HUB (2026-10-01) — below the cinematic: the Playground flagship, then each feature, then the investor row ──────────
   Generated into demo.html by scripts/build-learn-pages.mjs. ⚠ Hidden wherever the page is a player rather than a page: the
   /how-it-works frame (dm-embed), the recorder (dm-cap) and the 20 s loop (dm-loop). */
.dm-embed .dm-hub, .dm-cap .dm-hub, .dm-loop .dm-hub { display: none; }
.dm-hub { max-width: 1400px; margin: 0 auto; padding: 40px 20px 72px; }
.hub-h { font: 500 26px/1.15 var(--dm-serif); color: var(--dm-cream); margin: 52px 0 18px; }
.hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 22px; }
.hub-card { background: var(--dm-field-2); border: 1px solid var(--dm-line); border-radius: 14px; overflow: hidden; display: flex; flex-direction: column; }
.hub-play { position: relative; display: block; width: 100%; padding: 0; border: 0; background: #000; cursor: pointer; aspect-ratio: 16 / 10; }
.hub-play.is-video { cursor: auto; }
.hub-play img, .hub-play video { display: block; width: 100%; height: 100%; object-fit: cover; }
.hub-play video { object-fit: contain; background: #000; }
.hub-badge { position: absolute; left: 50%; top: 50%; width: 54px; height: 54px; margin: -27px 0 0 -27px; border-radius: 50%;
  background: var(--dm-terra-d); color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .35); transition: transform .2s var(--dm-ease); }
.hub-badge svg { width: 22px; height: 22px; margin-left: 3px; }
.hub-play:hover .hub-badge, .hub-play:focus-visible .hub-badge { transform: scale(1.08); }
.hub-play:focus-visible { outline: 2px solid var(--dm-terra); outline-offset: 2px; }
.hub-dur { position: absolute; right: 10px; bottom: 10px; font: 500 11px/1 var(--dm-mono); letter-spacing: .06em; color: var(--dm-cream);
  background: rgba(16, 13, 10, .78); padding: 5px 7px; border-radius: 6px; }
.hub-txt { padding: 16px 18px 20px; }
.hub-t { font: 500 19px/1.25 var(--dm-serif); margin: 0 0 6px; color: var(--dm-cream); }
.hub-why { font-size: 14px; line-height: 1.55; color: var(--dm-cream-2); margin: 0; }
.hub-more { display: inline-block; margin-top: 12px; font: 500 12px/1 var(--dm-mono); letter-spacing: .06em; color: var(--dm-terra); text-decoration: none; }
.hub-more:hover { text-decoration: underline; }
.hub-eyebrow { font: 500 12px/1 var(--dm-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--dm-terra); margin-bottom: 10px; }
/* the flagship: the video beside its words on a wide screen, stacked on a narrow one */
.hub-flag { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); align-items: center; }
.hub-flag .hub-txt { padding: 28px 32px; }
.hub-flag .hub-t { font-size: 32px; line-height: 1.1; margin-bottom: 12px; }
.hub-flag .hub-why { font-size: 16px; }
@media (max-width: 760px) {
  .dm-hub { padding: 28px 16px 56px; }
  .hub-flag { grid-template-columns: 1fr; }
  .hub-flag .hub-txt { padding: 18px 18px 22px; }
  .hub-flag .hub-t { font-size: 26px; }
  .hub-h { font-size: 22px; margin-top: 40px; }
  .hub-grid { grid-template-columns: 1fr; gap: 16px; }
}

/* ── the rail, categories, links and the scroll cue (Bret 2026-10-04) ─────────────────────────────────────────────────── */
.hub-anchor { display: block; position: relative; top: -12px; }
/* ⚖️ 2026-10-04 (Bret, the first screen): the category chips, IN THE FLOW under the player controls — so they can never cover
   the film's play button or its controls at any width. The box gives up one row of height for them (below), which keeps them
   on the first screen. Phone: one sideways-swipe row, never wrapping. They hide once the film plays (demo-hub.js); visibility,
   not display, so the layout does not jump under a running film. */
.hub-chips { display: flex; justify-content: center; gap: 8px; max-width: 1400px; width: 100%; margin: 0 auto; flex: none;
  transition: opacity .3s var(--dm-ease), visibility .3s; }
.hub-chips.is-off { opacity: 0; visibility: hidden; }
.hub-chip { display: inline-flex; align-items: center; gap: 8px; flex: none; padding: 8px 14px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--dm-line); background: var(--dm-field-2); color: var(--dm-cream); text-decoration: none; font: 500 13px/1 var(--dm-sans); }
.hub-chip:hover { border-color: var(--dm-terra); }
.hub-chip-n { font: 500 11px/1 var(--dm-mono); color: var(--dm-terra); }
.dm-box { max-height: calc(100dvh - 196px); }   /* 140 for the bar + controls, +56 for the chips row */
.dm-embed .hub-chips, .dm-cap .hub-chips, .dm-loop .hub-chips { display: none; }
.dm-embed .dm-box { max-height: calc(100dvh - 140px); }   /* no chips row there, so no row given up */
@media (max-width: 760px) {
  .hub-chips { justify-content: flex-start; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    margin: 0 -16px; padding: 0 16px; width: auto; mask-image: linear-gradient(90deg, #000 88%, transparent); }
  .hub-chips::-webkit-scrollbar { display: none; }
}
.dm-top-links { display: flex; align-items: center; gap: 22px; }
.dm-top-all { font-family: var(--dm-mono); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--dm-cream-2);
  text-decoration: none; border-bottom: 1px solid transparent; }
.dm-top-all:hover { color: var(--dm-cream); border-bottom-color: var(--dm-cream-2); }
.hub-rail-group.is-open .hub-rail-h { color: var(--dm-cream); }

.hub-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 40px; align-items: start; }
.hub-main > .hub-sec:first-child .hub-h { margin-top: 0; }
.hub-rail { position: sticky; top: 20px; max-height: calc(100vh - 40px); overflow: auto; padding: 4px 4px 16px 0; }
.hub-rail-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.hub-rail-title { font: 500 12px/1 var(--dm-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--dm-cream-2); }
.hub-rail-x { display: none; }
.hub-search { width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--dm-line);
  background: var(--dm-field-2); color: var(--dm-cream); font: 400 14px/1.2 var(--dm-sans); }
.hub-search::placeholder { color: var(--dm-cream-2); opacity: .7; }
.hub-search:focus { outline: 2px solid var(--dm-terra); outline-offset: 1px; }
.hub-rail-group { margin-top: 18px; }
.hub-rail-h { font: 500 11px/1 var(--dm-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--dm-terra); margin: 0 0 6px; }
.hub-rail-group ul { list-style: none; margin: 0; padding: 0; }
.hub-rail-a { display: flex; justify-content: space-between; gap: 10px; padding: 7px 8px; border-radius: 8px; color: var(--dm-cream);
  text-decoration: none; font: 400 14px/1.3 var(--dm-sans); }
.hub-rail-a:hover { background: var(--dm-field-2); }
.hub-rail-a.is-current { background: var(--dm-field-2); box-shadow: inset 2px 0 0 var(--dm-terra); }
.hub-rail-d { flex: none; font: 500 11px/1.3 var(--dm-mono); color: var(--dm-cream-2); }
.hub-none { margin-top: 18px; font-size: 14px; color: var(--dm-cream-2); }
.hub-card { scroll-margin-top: 24px; transition: box-shadow .3s var(--dm-ease), border-color .3s var(--dm-ease); }
.hub-card.is-target { border-color: var(--dm-terra); box-shadow: 0 0 0 2px var(--dm-terra); }
.hub-browse { display: none; }
.hub-sec[hidden], .hub-card[hidden], .hub-rail-group[hidden], .hub-rail-group li[hidden] { display: none; }

@media (max-width: 760px) {
  .hub-layout { display: block; }
  .hub-browse { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 6px; padding: 10px 16px; border-radius: 999px;
    border: 1px solid var(--dm-line); background: var(--dm-field-2); color: var(--dm-cream); font: 500 14px/1 var(--dm-sans); cursor: pointer; }
  .hub-rail { position: fixed; inset: 0 auto 0 0; width: min(86vw, 340px); max-height: none; z-index: 40; padding: 18px 16px 28px;
    background: var(--dm-field); border-right: 1px solid var(--dm-line); transform: translateX(-105%); transition: transform .25s var(--dm-ease); }
  .rail-open .hub-rail { transform: none; box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .55); }
  .hub-rail-x { display: block; border: 0; background: none; color: var(--dm-cream); font-size: 26px; line-height: 1; cursor: pointer; padding: 0 4px; }
  @media (prefers-reduced-motion: reduce) { .hub-rail { transition: none; } }
}
.hub-flag + .hub-grid { margin-top: 24px; }   /* Start here: the flagship, then the topics that start here (MCP) */
.dm-top-all, .dm-top-cta { white-space: nowrap; }
@media (max-width: 420px) {   /* a 360-wide phone: both top links on one line beside the mark */
  .dm-top-links { gap: 12px; }
  .dm-top-all, .dm-top-cta { font-size: 11px; letter-spacing: .03em; }
}

/* ── DESKTOP: THE RAIL ON THE FIRST SCREEN, AND A PLAYLIST (Bret 2026-10-04, re-ruled) ─────────────────────────────────────────
   ≥1024: the "All walkthroughs" rail is a fixed column on the left from the top of the page (it scrolls inside itself when
   taller than the window); the cinematic and everything else sit to its right at whatever width remains. A rail pick plays in
   the main spot (demo-hub.js): .dm-wt over the stage, .dm-wt-bar in place of the cinematic's controls. The chips row is the
   phone/tablet answer to "there are many walkthroughs" and is not needed beside the rail itself.
   ⚠ Scoped away from the player-only modes: dm-embed (on <html>), dm-cap and dm-loop (on <body>) keep their own layout. */
.dm-wt, .dm-wt-bar { display: none; }
@media (min-width: 1024px) {
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) { --dm-rail-w: 280px; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-page,
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-hub { margin-left: var(--dm-rail-w); }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-hub { max-width: 1400px; margin-right: auto; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .hub-layout { display: block; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .hub-rail { position: fixed; top: 0; left: 0; bottom: 0; z-index: 30;
    width: var(--dm-rail-w); max-height: none; box-sizing: border-box; padding: 20px 16px 28px; overflow: auto;
    background: var(--dm-field); border-right: 1px solid var(--dm-line); }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .hub-rail-top { margin-top: 6px; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .hub-chips { display: none; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-box { max-height: calc(100dvh - 140px); }   /* no chips row here */
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .hub-main > .hub-sec:first-child .hub-h { margin-top: 0; }
  /* the playlist */
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-wt:not([hidden]) { display: block; position: absolute; inset: 0; z-index: 8;
    background: #000; border-radius: inherit; overflow: hidden; }
  .dm-wt video { display: block; width: 100%; height: 100%; object-fit: contain; background: #000; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-page.wt-on .dm-controls { display: none; }
  html:not(.dm-embed) body:not(.dm-cap):not(.dm-loop) .dm-page.wt-on .dm-wt-bar { display: flex; align-items: center; gap: 14px;
    max-width: 1400px; width: 100%; margin: 0 auto; min-height: 34px; }
  .dm-wt-now { font: 500 11px/1 var(--dm-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--dm-terra); flex: none; }
  .dm-wt-title { font: 500 16px/1.3 var(--dm-serif); color: var(--dm-cream); flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dm-wt-back { flex: none; appearance: none; background: none; border: 1px solid rgba(239, 233, 223, 0.22); color: var(--dm-cream);
    border-radius: 999px; height: 34px; padding: 0 14px; font: 500 12px/1 var(--dm-mono); letter-spacing: .06em; cursor: pointer; }
  .dm-wt-back:hover { border-color: var(--dm-terra); color: var(--dm-terra); }
  .dm-wt-back:focus-visible { outline: 2px solid var(--dm-terra); outline-offset: 2px; }
}
