/* ═══════════════════════════════════════════════════════════════════════
   HudHud onboarding — "The Hoopoe's Day". One continuous day, dawn → dusk,
   staged as a Creed-style sky: full-bleed dawn, one wide floating editor,
   photoreal nature at the edges dissolving into paper. Single file.
   Brief: thoughts/tasks/onboarding-redesign/02-redesign-brief.md
   Thread-UI ground truth: thoughts/tasks/onboarding-redesign/03-thread-card-ground-truth.md
   Tokens mirror electron-app/src/styles/tokens.css (+ onboarding-site sky anchors).
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  --bg-primary: #FAFAF8;
  --bg-secondary: #F5F5F2;
  --bg-tertiary: #EDEDEA;
  --bg-elevated: #FFFFFF;
  /* the page ground = the app's workspace field (--bg-secondary in
     tokens.css), so the page sits on the same surface the editor card sits
     on in the real app — the old marketing cream (#F5F0E6) read warmer than
     any surface the product actually shows */
  --bg-canvas: #F5F5F2;

  --text-primary: #1D1D1F;
  --text-secondary: #6E6E73;
  --text-muted: #AEAEB2;
  --text-faint: rgba(29, 29, 31, 0.36);

  --accent: #C45D35;
  --accent-hover: #A84E2D;
  --accent-soft: rgba(196, 93, 53, 0.10);
  --accent-soft-2: rgba(196, 93, 53, 0.18);

  --divider: #D1D1D6;
  --divider-light: #E5E5EA;
  --hairline: rgba(29, 29, 31, 0.08);
  --hairline-strong: rgba(29, 29, 31, 0.14);

  --status-green: #34C759;
  --status-orange: #FF9500;
  --status-red: #FF3B30;
  /* Gold — agent artifact work (embed build/patch veil). Distinct from the
     orange "AI is working" activity pulse. */
  --status-gold: #ffd60a;

  /* AI experience — app values verbatim (the quiet presence, never a second accent) */
  --ai-label-color: rgba(0, 0, 0, 0.30);
  --ai-connector: rgba(0, 0, 0, 0.18);
  --ai-dot: rgba(196, 93, 53, 0.45);

  --font-body: Charter, 'Bitstream Charter', 'Iowan Old Style', 'Hoefler Text', Georgia, serif;
  --font-ui: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-code: 'SF Mono', ui-monospace, 'JetBrains Mono', Menlo, Consolas, monospace;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-xl: 14px;
  --radius-pill: 999px;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);

  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.08);
  --shadow-window: 0 1px 0 rgba(255, 255, 255, 0.85) inset,
                   0 0 0 1px rgba(29, 29, 31, 0.05),
                   0 2px 6px rgba(60, 40, 20, 0.06),
                   0 24px 48px -16px rgba(60, 40, 20, 0.16),
                   0 64px 120px -40px rgba(60, 40, 20, 0.30);

  /* Sky seam anchors + fallbacks — the skyscapes are inlined below; these
     tokens pin the horizon seams and stand in if the images fail. */
  --sky-dawn-high: #B7C4D4;
  --sky-dawn-glow: #E8C9A8;
  --sky-dawn-warm: #D99A6C;
  --sky-dusk-high: #6E6178;
  --sky-dusk-rose: #B87A6E;
  --sky-dusk-amber: #E8B183;
}
html { -webkit-text-size-adjust: 100%; scroll-behavior: auto; }
body {
  background: var(--bg-canvas);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* clip, not hidden: `hidden` would make the body a scroll container and kill
     the hero field's position: sticky */
  overflow-x: clip;
}

/* ── Page bar: brand + the day clock (scroll-linked readout) ──────────────
   Rides the dawn sky at the top of the page, so it wears only a whisper of
   scrim — the sky is the chrome now. */
.page-bar {
  position: fixed; inset: 0 0 auto 0; z-index: 80;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 18px clamp(20px, 4vw, 44px);
  font-family: var(--font-ui); font-size: 12px; letter-spacing: 0.02em;
  color: var(--text-secondary); pointer-events: none;
  background: linear-gradient(to bottom, rgba(250, 250, 248, 0.5) 0%, rgba(250, 250, 248, 0) 100%);
}

/* ── Section scaffolding ──────────────────────────────────────────────── */
.section {
  position: relative; width: 100%;
  display: flex; flex-direction: column; align-items: center;
  padding: clamp(64px, 10vh, 128px) clamp(20px, 4vw, 48px);
  overflow: hidden;   /* nature lives at the edges; it never spills between sections */
}
.sect-head { position: relative; z-index: 2; max-width: 720px; text-align: center; margin: 0 auto; }
.eyebrow {
  font-family: var(--font-ui); font-size: 11px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
}
.sect-head h2 {
  font-family: var(--font-body); font-size: clamp(30px, 4.4vw, 40px);
  line-height: 1.15; font-weight: 700; letter-spacing: -0.01em;
  margin: 14px 0 12px; text-wrap: balance;
}
.sect-head .sub {
  font-family: var(--font-body); font-size: 18px; color: var(--text-secondary);
  max-width: 54ch; margin: 0 auto;
}
/* Settle-in: one gentle rise per section head / card, played once. */
.settle { opacity: 0; transform: translateY(12px); }
[data-played] .settle, .settle[data-played] {
  opacity: 1; transform: none;
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}

.dusk-hoopoe-far {
  position: absolute; top: 21%; right: 24%; width: 34px; z-index: 1;
  opacity: 0.5; pointer-events: none;
}
.dusk-hoopoe-far path { fill: #403236; }

/* ═══ §1 — HERO: the desk, and the "One Tone" wallpaper on it ════════════
   One of the files under src/styles/ that is NOT a slice of the merged
   design source; post-merge-fixes.css and close.css are the others.
   `build.mjs` names all three in NON_SLICES. (The staging-era provenance
   harness that consumed that array retired with the staging tree in
   b47fe941a.)

   Two things live here, and the second cannot exist without the first.

   ① THE DESK. The hero's chrome used to sit on the viewport: menu bar pinned
      to the top edge, dock at the bottom, the editor centred on bare paper
      between them. There was nowhere to put a wallpaper — the "desktop" was
      the browser window. So the desktop becomes an object: 1140px wide at a
      1600px reference viewport, 35px corners, the editor 74px inside it, the
      menu bar and dock inside ITS edges instead of the viewport's.

   ② THE WALLPAPER. "One Tone" — a single warm-to-cool wash on stone, ported
      from the Arc wallpaper recreation (`wallpaper-1-recreation.html`, the
      4800×3428 CSS+SVG rebuild of wallpapers.png) with twelve of its fourteen
      blobs deleted. Same canvas, same `--blob-<name>-*` names, same shared
      five-stop falloff, same separate grain plate: putting a third blob back
      is adding variables, not restructuring.

   Static in this pass. How the wallpaper ARRIVES — whether it is already
   there on the bare-paper beat or fades in with the chrome — is a second
   pass, and nothing here presumes an answer.
   ══════════════════════════════════════════════════════════════════════ */

/* ── ① the desk ─────────────────────────────────────────────────────────
   It wraps the menu bar, the window, the dock and the taskbar, so all four
   keep their own rules verbatim: they are `position: absolute` against the
   nearest positioned ancestor, and this is now it.

   Nothing here overrides a hero.css declaration, which is why this file can
   sit early in the cascade and let hero.css keep the last word on the hero.
   The two places it does have to bend the existing layout avoid the fight:
     * `max-width` — a property .mz-window does not set — folds its
       `width: min(1460px, 90vw)` into the desk's content box.
     * `--mz-doc-h` is redeclared on the desk, a CLOSER ancestor of .mz-doc
       than .mz-hero, so inheritance settles it and specificity never comes
       up. That also means it would silently outrank the ≤900px override in
       orphan-deep-dive.css — hence the min-width guard. ── */
.mz-desk {
  position: relative;
  flex: none;                    /* a column flex item shrinks by default, and
                                    a squashed desk clips the document rather
                                    than losing its insets */
  /* The desk is the fixed point; the page flexes around it (Omar, 2026-08-08).
     Three regimes, one expression:
       · wide (≳1565px): 78% of the page — the old 65% proportion grown 20%.
       · moderate: a 1220px floor, so the desk stops shrinking with the
         viewport and instead fills toward the edges.
       · narrow (<1220px): the floor exceeds the viewport and the desk CROPS
         at both edges like a real desktop behind a window — the field's
         overflow:hidden does the cutting, centred by align-items. The
         `100% + 100px` arm caps the crop at 50px a side, which keeps the
         editor window (desk minus its 74px insets) fully on screen with
         ~24px of page showing beside it down to the ~1024px scope floor.
     --mz-desk-crop mirrors that per-side crop for the chrome pinned to the
     desk's edges (menu bar, taskbar) to pad themselves back into view. */
  width: max(78%, min(1220px, calc(100% + 100px)));
  --mz-desk-crop: min(50px, max(0px, calc((1220px - 100vw) / 2)));
  /* 74px on three sides is the editor's agreed inset. The bottom is 100px
     because the dock lives in it: the dock is 56px tall and sits 12px off the
     desk's floor, so a 74px inset left only 6px between the editor's bottom
     edge and the dock's top. 100px opens that to 32px. */
  padding: 74px 74px 100px;
  border-radius: 10.5px;         /* 35px reduced by 70% */
  overflow: hidden;              /* the wallpaper stops at the corners */
}
/* max-width folds .mz-window's own `width: min(1460px, 90vw)` into the desk;
   the auto margins centre it when that width is the SMALLER of the two, which
   happens above ~2475px viewport. Without them the slack all falls on the
   right and the editor sits visibly left of the desk's centre. */
.mz-window { max-width: 100%; margin-inline: auto; }
@media (min-width: 901px) {
  /* The document is 20% taller than the desk first shipped with: the window
     (52px chrome + this) goes 512 → 614 at a 900px viewport.

     The subtrahend, not a multiplier, is what sets it — 338 = the previous
     440 less the 102px of growth — because the figure has to stay a function
     of viewport height. .mz-field centres its children under
     `overflow: hidden`, so an over-tall assembly is clipped at BOTH ends and
     the menu bar is the first thing to go off the top.

     The 102px is paid for, not borrowed: 106px from .mz-field's now-vestigial
     top and bottom padding (it reserved bands for a menu bar and dock that
     are inside the desk now) and 24px from .mz-below, against 128px of new
     desk height — 102 here plus the 26px the dock gap took. Both credits are
     in hero.css. Measured slack at 1600×900 afterwards: ~26px. */
  .mz-desk { --mz-doc-h: clamp(250px, calc(100vh - 338px), 1080px); }
}
@media (max-width: 900px) {
  /* Below the breakpoint where the page stops pinning scenes, a 74px inset is
     most of the width. The narrow layout keeps orphan-deep-dive.css's own
     document height, which is why this block does not touch --mz-doc-h. */
  .mz-desk { width: 94vw; padding: 18px; --mz-desk-crop: 0px; }
}

/* ── ② the wallpaper ────────────────────────────────────────────────────
   "Savanna" — a photographic Mediterranean oak savanna at golden hour
   (public/wallpaper-savanna.jpg, 1536×1024): five holm oaks strung along a
   hazy horizon just above the frame's midline, dry golden grassland below,
   a big quiet ivory-gold sky above. It replaced the "One Tone" blob SVG —
   the photo brings its own grain and its own falloff, so the whole blob /
   falloff / grain-plate system retired with it.

   The crop: `cover` against a desk that is WIDER than 3:2, so the photo
   loses top and bottom, never the sides — all five oaks stay in frame at
   every viewport. The focus point sits at 52% vertical, pinning the tree
   line into the visible band between the menu bar and the editor window's
   top edge; the grassland fills the aprons beside and below the window. */
.mz-wall {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  background-image: url("wallpaper-savanna.jpg");
  background-size: cover;
  background-position: 50% 52%;
  background-repeat: no-repeat;
  pointer-events: none;

  /* The desk is not there from the first frame. Beats 0–1 are the document on
     bare page ground — prose directly on paper, nothing behind it — and the
     savanna arrives with the chrome, on .mz-elev's own timing, so the desk and
     the editor's card materialize as one object rather than the document
     turning out to have been sitting on a desk all along.

     Nothing else paints the desk: no background, no shadow, no border. So
     this single opacity is the whole of the desk's VISIBLE presence. Its
     layout is still in force at `pre` — the desk's width and padding go on
     constraining .mz-window — which is deliberate: the document must not
     resize when the photo fades in. */
  opacity: 0;
  transition: opacity calc(0.9s * var(--mzs)) var(--ease);
}
[data-mz="mz"] .mz-wall,
[data-mz="settled"] .mz-wall { opacity: 1; }

/* ═══ §1 — HERO: "The Materialize" ═══════════════════════════════════════
   The page opens as bare warm paper — one document, one margin note. On the
   first touch (keystroke / Tab / scroll / hint) macOS assembles AROUND the
   text: NO wallpaper, the field stays paper. Materialize is elevation +
   chrome only, so the document never moves or reflows. Turn 6 of the hero
   wireframes; timings from 3b, scroll/pin from 4b, seam from 4a.
   ══════════════════════════════════════════════════════════════════════ */
a { color: var(--accent); }

.mz-hero {
  --mzs: 1;                                   /* choreography speed: 1 = 1.3s, .69 = compressed */
  --mz-doc-h: clamp(325px, calc(1.3 * (100vh - 300px)), 1170px);   /* fixed: the window never resizes on a tab swap */
  position: relative; width: 100%; min-height: 100vh;
}
.mz-field {
  position: relative; height: 100vh; min-height: 520px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 14px 0 0;             /* was 32px 0 74px, reserving the menu bar's
                                    band and the dock's band. Both now sit
                                    INSIDE the desk (hero-wallpaper.css), so
                                    the field no longer holds room for them,
                                    and the reclaimed ~92px is what pays for
                                    the taller document. The 14px that stays
                                    keeps the desk off the viewport's top
                                    edge — at 0 it very nearly touches it. */
  overflow: hidden;              /* the menu bar and dock leave through the edges */
  isolation: isolate;
}

/* ── the menu bar: arrives at t+150ms, carries the status and the day clock ── */
.mz-menubar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 4; height: 28px;
  display: flex; align-items: center; gap: 17px; padding: 0 calc(14px + var(--mz-desk-crop, 0px));
  font-family: var(--font-ui); font-size: 12px; color: var(--text-primary);
  background: rgba(250, 250, 248, 0.72); border-bottom: 1px solid var(--hairline);
  backdrop-filter: blur(14px) saturate(1.6); -webkit-backdrop-filter: blur(14px) saturate(1.6);
  opacity: 0; transform: translateY(-100%);
  transition: opacity calc(0.7s * var(--mzs)) var(--ease-out) calc(0.15s * var(--mzs)),
              transform calc(0.7s * var(--mzs)) var(--ease-out) calc(0.15s * var(--mzs));
}
.mz-mb-app { font-weight: 600; letter-spacing: -0.01em; }
.mz-mb-menu { color: var(--text-secondary); }
.mz-mb-right { margin-left: auto; display: flex; align-items: center; gap: 16px; }
.mz-mb-status { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-secondary); }
.mz-status-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex: none; transition: background 0.3s var(--ease); }
.mz-status-dot--drafting  { background: var(--text-muted); }
.mz-status-dot--executing { background: var(--status-orange); }
.mz-osclock, .mz-tb-clock {
  font-family: var(--font-ui); font-size: 12px; letter-spacing: 0.02em;
  color: var(--text-secondary); white-space: nowrap;
  font-feature-settings: "tnum" 1; font-variant-numeric: tabular-nums;
}
.mz-clock-day { color: var(--text-faint); margin-right: 6px; }

/* ── the window: chrome space is reserved from the first frame, so nothing
      shifts when it materializes. Elevation is its own layer (.mz-elev) — the
      seam scrubs that layer instead of animating a box-shadow. ── */
.mz-window {
  position: relative; z-index: 2; width: min(1533px, 94.5vw);
  margin-top: clamp(10px, 2.5vh, 28px);
  display: flex; flex-direction: column; font-family: var(--font-ui);
}
.mz-elev {
  position: absolute; inset: 0; z-index: 0; border-radius: var(--radius-xl);
  background: var(--bg-primary); box-shadow: var(--shadow-window);
  opacity: 0; transition: opacity calc(0.9s * var(--mzs)) var(--ease);
}
/* ── the glass: a frosted rim between the window and the wallpaper, a slim
      ~1.25% band past each edge. The panel itself is transparent —
      you don't see its size, you see the wallpaper turn glossy and blurred
      through it, the way a macOS sheet frosts the scenery around its edge.
      It lives on .mz-window, NOT under .mz-elev: an ancestor mid-opacity-fade
      forms a backdrop root and backdrop-filter would stop sampling the
      wallpaper during the materialize transition. Same [data-mz] gate, its
      own opacity. ── */
.mz-window::before {
  content: ""; position: absolute; inset: -0.875%; z-index: -1;
  border-radius: calc(var(--radius-xl) + 6px);
  /* barely-there sheen so the glass reads glossy, not milky */
  background: linear-gradient(135deg,
    rgba(255, 255, 255, 0.16),
    rgba(255, 255, 255, 0.04) 50%,
    rgba(255, 255, 255, 0.10));
  -webkit-backdrop-filter: blur(14px) saturate(1.35) brightness(1.05);
  backdrop-filter: blur(14px) saturate(1.35) brightness(1.05);
  box-shadow: 0 24px 48px rgba(29, 29, 31, 0.16), 0 6px 18px rgba(29, 29, 31, 0.10),
              0 1px 0 rgba(255, 255, 255, 0.35) inset;
  opacity: 0; transition: opacity calc(0.9s * var(--mzs)) var(--ease);
  pointer-events: none;
}
[data-mz="mz"] .mz-window::before, [data-mz="settled"] .mz-window::before { opacity: 1; }
[data-mz="mz"] .mz-menubar, [data-mz="settled"] .mz-menubar { opacity: 1; transform: none; }
[data-mz="mz"] .mz-elev, [data-mz="settled"] .mz-elev { opacity: 1; }
/* ── the chrome band: the editor's objective tab bar, reproduced from
      electron-app/src/objectives/ui/tabBar/ (tabBarStyles.css + tabBar-row.ts).
      It is the window's SINGLE top chrome row — the app retired its separate
      title strip, so no filename sits above it and the tabs ARE the switcher.
      Geometry is the component's, in this page's tokens: --chrome-row-h 52px
      with --chrome-row-air 8px of air at the TOP, so the 44px run lands on the
      band's bottom edge and the active tab meets the document.
      Colour is the app's own relationship: the band carries the workspace
      field (--bg-secondary, the app's body fill) and the document below carries
      the card (--bg-primary, painted by .mz-elev), so the active tab taking the
      card fill with no border between IS the merge. It arrives with the chrome,
      on the same gate the title strip used. The band replaces a 38px strip with
      52px, which grows the window 14px OUTWARD — .mz-doc's height is fixed, so
      the document loses nothing. ── */
.mz-tabbar {
  position: relative; z-index: 2; flex: none; height: 52px;
  box-sizing: border-box; padding-top: 8px;
  display: flex; align-items: stretch; overflow: hidden;
  background: var(--bg-secondary);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  font-size: 12px; color: var(--text-secondary);
  -webkit-user-select: none; user-select: none;
  opacity: 0;
  transition: opacity calc(0.7s * var(--mzs)) var(--ease) calc(0.25s * var(--mzs));
}
[data-mz="mz"] .mz-tabbar, [data-mz="settled"] .mz-tabbar { opacity: 1; }
.mz-tabbar .traffic { flex: none; align-items: center; padding: 0 8px 0 14px; }
.mz-tabrun { display: flex; align-items: stretch; min-width: 0; }
.mz-tab {
  display: flex; align-items: center; gap: 5px; padding: 0 8px 0 10px;
  /* uniform across states — widening only the active tab would reflow the run
     under the cursor on every activation */
  min-width: 96px; max-width: 200px; box-sizing: border-box; flex: none;
  border: 0; background: transparent; cursor: pointer; font: inherit;
  /* one step below the window's --radius-xl: the active tab reads as a smaller
     protrusion of the same object rather than a differently-cornered block. Set
     on the base, so an inactive hover tints the same silhouette. */
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  transition: background 0.14s var(--ease);
}
.mz-tab:not(.is-on):hover { background: var(--bg-tertiary); }
.mz-tab.is-on { background: var(--bg-primary); }   /* card fill — no seam against the document */
/* leading signal dot: bare renders nothing, a modifier paints a 6px circle.
   The pulse is stilled by responsive.css's reduced-motion block, which zeroes
   every animation on the page. */
.mz-tab-dot { flex: none; width: 6px; height: 6px; display: none; }
.mz-tab-dot--executing, .mz-tab-dot--attention, .mz-tab-dot--delivering { display: block; border-radius: 50%; }
.mz-tab-dot--executing { background: var(--status-orange); animation: mz-tab-pulse 1.5s ease-in-out infinite; }
.mz-tab-dot--attention { background: var(--status-orange); }
.mz-tab-dot--delivering { background: var(--status-green); }
@keyframes mz-tab-pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
.mz-tab-title {
  flex: 1; min-width: 0; text-align: left;
  font-family: var(--font-ui); font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mz-tab.is-on .mz-tab-title { color: var(--text-primary); font-weight: 500; }
/* persistent × on the active tab, hover-revealed on the others — the component's
   rule. Decorative here: the hero holds exactly three objectives and closing one
   would leave a hole, so the × renders and a click on it does nothing. */
.mz-tab-close {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: var(--radius-sm);
  color: var(--text-muted); opacity: 0;
  transition: opacity 0.14s var(--ease), background 0.14s var(--ease);
}
.mz-tab:hover .mz-tab-close, .mz-tab.is-on .mz-tab-close { opacity: 1; }
.mz-tab-close:hover { background: var(--bg-secondary); color: var(--text-primary); }
.mz-tab-add {
  flex: none; align-self: center; margin-left: 4px; width: 30px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radius-sm); background: transparent;
  color: var(--text-muted); font-family: var(--font-ui); font-size: 15px; line-height: 1;
  transition: background 0.14s var(--ease), color 0.14s var(--ease);
}
.mz-tab-add:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.mz-caption-btns {
  display: none; margin-left: auto; align-self: center; gap: 14px;
  padding-right: 12px; color: var(--text-muted); font-size: 10px;
}
[data-platform="win"] .mz-caption-btns { display: flex; }
[data-platform="win"] .traffic { display: none; }
[data-platform="win"] .mz-tabbar { border-radius: 8px 8px 0 0; }
[data-platform="win"] .mz-tabbar .mz-tabrun { padding-left: 6px; }
[data-platform="win"] .mz-elev { border-radius: 8px; }
[data-platform="win"] .mz-doc { border-radius: 0 0 8px 8px; }
[data-platform="win"] .mz-window::before { border-radius: 12px; }

/* ── the document: prose + its margin threads. Fixed height, native scroll ── */
.mz-doc {
  position: relative; z-index: 2; flex: none; height: var(--mz-doc-h);
  overflow: hidden auto; overscroll-behavior: contain;
  /* the gutter is reserved in both states, so the scrollbar arriving with the
     window cannot narrow the column and reflow the headline on a platform
     with classic (non-overlay) scrollbars */
  scrollbar-gutter: stable;
  /* clip the scroll container to the window's bottom corners — without this
     its scrollbar track paints square over .mz-elev's rounded bottom-right */
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
  padding: clamp(24px, 3.4vh, 40px) clamp(18px, 3vw, 34px) 30px clamp(22px, 3.4vw, 44px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
.mz-doc.is-out { opacity: 0; transform: translateY(10px); }
.mz-doc.is-in  { opacity: 0; transform: translateY(14px); transition: none; }
.mz-doc-inner {
  display: grid; grid-template-columns: minmax(0, 660px) 304px;
  justify-content: center; gap: clamp(38px, 5.5vw, 80px); align-items: start;
}
.mz-prose { position: relative; font-family: var(--font-body); min-width: 0; }
.mz-file {
  font-family: var(--font-code); font-size: 11px; letter-spacing: 0.02em;
  color: var(--text-faint); margin-bottom: clamp(10px, 1.6vh, 18px);
}
/* the reserve copy holds the final wrapping so the typewriter cannot reflow
   a single line of the document */
.mz-h1wrap { position: relative; }
.mz-h1 {
  font-family: var(--font-body); font-weight: 700;
  font-size: clamp(25px, 2.55vw, 37px); line-height: 1.26;
  letter-spacing: -0.015em; margin: 0; text-wrap: pretty;
}
.mz-h1--reserve { visibility: hidden; }
.mz-h1--live { position: absolute; inset: 0; }
.mz-para {
  font-size: clamp(14px, 1.08vw, 16px); line-height: 1.68;
  margin: 0 0 11px; text-wrap: pretty;
}
/* the rest of the objective — it is not a placeholder waiting for a click, it
   arrives with the desktop (item 5), so it is laid out from the first frame
   and only unveils. Nothing reflows. */
/* collapsed until it arrives: in beat 0–1 the page is bare paper with no
   window around it, and anything taller than the frame would show the frame's
   scrollbar floating over that paper with nothing to belong to. The rail is
   the other half of that — beats 0–1 carry ONE thread, and the rest must not
   hold their space until the desktop is there to hold them. The first thread
   is exempt: it is the one that lands in beat 1, and an element leaving
   display:none has no starting frame to transition from, which is why its
   arrival read as instant. */
[data-mz="pre"] .mz-rail .mz-note:not(.is-on):not(:first-child) { display: none; }
.mz-body {
  margin-top: clamp(10px, 1.5vh, 16px);
  max-height: 0; overflow: hidden; opacity: 0;
  transition: opacity 0.7s var(--ease);
}
.mz-body.is-on { max-height: none; overflow: visible; opacity: 1; }
.mz-body > * { opacity: 0; transform: translateY(6px); }
.mz-body.is-on > * {
  opacity: 1; transform: none;
  transition: opacity 0.5s var(--ease) calc(var(--bi) * 0.07s),
              transform 0.5s var(--ease-out) calc(var(--bi) * 0.07s);
}
.mz-h2 {
  font-family: var(--font-body); font-weight: 650;
  font-size: clamp(15px, 1.22vw, 18px); line-height: 1.4; letter-spacing: -0.008em;
  margin: clamp(18px, 2.4vh, 26px) 0 9px; color: var(--text-primary);
}
.mz-list {
  font-size: clamp(14px, 1.08vw, 16px); line-height: 1.68;
  margin: 0 0 11px; padding-left: 1.35em; text-wrap: pretty;
}
.mz-list li { margin-bottom: 5px; }
.mz-list li::marker { color: var(--text-faint); }
.mz-ghostline {
  font-size: clamp(14px, 1.08vw, 16px); line-height: 1.68;
  margin: 13px 0 0; opacity: 0; transition: opacity 0.55s var(--ease);
}
.mz-ghostline.is-on { opacity: 1; }
.mz-ghostline.is-committed .ghost-run { color: var(--text-primary); font-style: normal; opacity: 1; }
.mz-ghostline.is-committed .ghost-hint { opacity: 0; }
.mz-ghostline .ghost-hint { transition: opacity 0.3s var(--ease); }
.mz-caret {
  display: inline-block; width: 1.5px; height: 0.92em; background: var(--text-primary);
  vertical-align: -0.06em; margin-left: 2px;
  animation: cursor-blink 1.1s steps(1) infinite;
}
/* accent = signal: the anchored phrase, the note pill, the CTA. Nothing else. */
.mz-anchor {
  border-bottom: 1px dashed rgba(196, 93, 53, 0);
  transition: border-color 0.45s var(--ease);
}
.mz-anchor.is-on { border-bottom-color: rgba(196, 93, 53, 0.55); }

/* the margin — chromeless notes on hand-drawn connectors (the app's real
   anatomy). Three to five threads per objective, each tethered to the passage
   it is about, each demonstrating a different way the collaborator works:
   a question, a counter-argument, a constraint it brings, a suggestion, and
   one artifact it drew to make its point. */
.mz-rail { position: relative; min-width: 0; }
.mz-note {
  position: relative; font-family: var(--font-ui);
  opacity: 0; transform: translateX(-30px);
  transition: opacity 0.6s var(--ease), transform 0.68s var(--ease-out);
}
.mz-note.is-on { opacity: 1; transform: none; }
.mz-note::before {
  content: ""; position: absolute; left: -4px; top: 14px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--ai-dot);
}
.mz-note .mn-connector {
  position: absolute; top: 14px; height: 5px; color: var(--ai-connector);
  overflow: visible; pointer-events: none; opacity: 0;
  transition: opacity 0.5s var(--ease) 0.32s;
}
.mz-note.is-on .mn-connector { opacity: 1; }
.mz-note-inner { padding-left: 10px; }
.mz-note[data-type="warning"] .mz-note-inner { border-left: 2px solid rgba(255, 59, 48, 0.3); margin-left: -2px; }
.mz-note-crumb {
  margin-left: 7px; min-width: 0; font-family: var(--font-code); font-size: 9px;
  letter-spacing: 0.02em; color: var(--text-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mz-note-foot { display: flex; align-items: baseline; }
.mz-note-act {
  display: inline-block; white-space: nowrap; margin: 7px 0 0 10px; font-family: var(--font-ui);
  font-size: 10.5px; color: var(--text-secondary); text-decoration: none;
  opacity: 0.45; transition: opacity 0.15s var(--ease);
}
.mz-note-act:hover { opacity: 1; color: var(--text-secondary); }
.mz-note-foot .mn-count { margin-left: auto; }

/* the whole card is the hit target, because in the app clicking a margin card
   is the entire gesture for opening its thread — "open thread →" is this
   page's own label for something the card already does. While a thread is
   open the rest of the rail dims and the card it came from stays lit: the
   app's spotlight, and the reason the bubble is placed beside the margin
   rather than over it. */
.mz-note { cursor: pointer; }
.mz-note.is-dimmed { opacity: 0.38; filter: saturate(0.9); }
.mz-note.is-source .mn-connector { color: var(--accent); opacity: 1; }

/* the expanded thread lives beside the margin, inside the window. Its own
   anatomy (.thread-bubble / .tb-*) is the shipping component's and is defined
   with the rest of the editor's parts; what the hero adds is placement. It
   drags by its titlebar exactly as the app's does — the grab cursor is the
   component's own — but it still does not resize, so the grabber stays off. */
.mz-window .thread-bubble { z-index: 6; }
.mz-window .thread-bubble.dragging { transition: none; }
.mz-window .thread-bubble.dragging .tb-header { cursor: grabbing; }
.mz-window .thread-bubble::after { display: none; }   /* the resize grabber — unsupported here, and it lands on the send button */
.mz-window .tb-msg-body .mz-embed { width: 296px; max-width: 100%; margin-top: 8px; }
.mz-window .tb-msg.ai .tb-msg-body { max-width: 100%; }

/* the artifact the collaborator drew, in the margin where it was drawn — the
   same three tiers §2 names at full size: annotatable, manipulable, view-only */
.mz-embed {
  margin: 9px 0 2px 10px; border: 1px solid var(--divider-light); border-radius: 10px;
  overflow: hidden; background: var(--bg-elevated);
  box-shadow: 0 2px 8px -3px rgba(60, 40, 20, 0.14);
}
.mz-embed-head { display: flex; align-items: center; gap: 6px; padding: 8px 9px 6px; }
.mz-eicon {
  width: 14px; height: 14px; border-radius: 4px; flex: none; font-size: 7.5px;
  background: var(--bg-tertiary); color: var(--text-secondary);
  display: inline-flex; align-items: center; justify-content: center;
}
.mz-etitle {
  font-family: var(--font-ui); font-size: 10.5px; font-weight: 600; letter-spacing: -0.005em;
  color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mz-etier {
  margin-left: auto; flex: none; font-family: var(--font-code); font-size: 7px;
  letter-spacing: 0.08em; padding: 2px 6px; border-radius: var(--radius-pill); white-space: nowrap;
}
.mz-etier--an { color: var(--accent); background: var(--accent-soft); }
.mz-etier--ma { color: #C97A05; background: rgba(255, 149, 0, 0.12); }
.mz-etier--se { color: var(--text-muted); background: var(--bg-tertiary); }
.mz-embed-body { padding: 0 8px 2px; }
.mz-embed-foot {
  display: flex; align-items: center; gap: 6px; padding: 6px 9px;
  margin-top: 7px; border-top: 1px solid var(--divider-light);
}
.mz-edot { width: 4px; height: 4px; border-radius: 50%; flex: none; background: var(--status-green); }
.mz-ehint {
  font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.03em; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mz-ecta { margin-left: auto; flex: none; font-family: var(--font-ui); font-size: 9.5px; font-weight: 600; color: var(--accent); }

/* the three artifacts themselves — the conflict rendered in place, the two
   lockups at the size they are met, the pilot's two arms */
.mz-cf { font-family: var(--font-ui); font-size: 9.5px; padding: 3px 0 4px; }
.mz-cf-row {
  display: flex; flex-direction: column; gap: 2px; padding: 5px 7px; border-radius: 5px;
  border-left: 2px solid var(--accent); background: rgba(196, 93, 53, 0.05);
}
.mz-cf-row.is-other {
  margin-top: 5px; border-left-color: var(--divider); background: var(--bg-tertiary);
}
.mz-cf-src { font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.03em; color: var(--text-faint); }
.mz-cf-txt { color: var(--text-secondary); }
.mz-cf-txt em { font-style: normal; font-weight: 650; color: var(--text-primary); }
.mz-cf-acts { display: flex; gap: 5px; margin-top: 7px; }
.mz-cf-act {
  padding: 2.5px 7px; border-radius: var(--radius-pill); border: 1px solid var(--divider-light);
  font-size: 8.5px; color: var(--text-muted); white-space: nowrap;
}
.mz-cf-act.is-on { border-color: transparent; background: var(--accent); color: #FFF; font-weight: 600; }
.mz-bp { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 6px 2px 8px; }
.mz-bp-col { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.mz-bp-tag { font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.1em; color: var(--text-faint); }
.mz-bp-lock { font-size: 13px; letter-spacing: -0.02em; }
.mz-bp-lock--b { font-family: var(--font-ui); font-weight: 650; color: #2C3A43; }
.mz-bp-lock--c { font-family: var(--font-body); font-weight: 500; font-style: italic; color: #3F7A5E; }
.mz-bp-fav {
  width: 24px; height: 24px; border-radius: 6px; display: inline-flex;
  align-items: center; justify-content: center; font-size: 11px; color: #FFF;
}
.mz-bp-fav--b { background: #2C3A43; font-family: var(--font-ui); font-weight: 650; }
.mz-bp-fav--c { background: #3F7A5E; font-family: var(--font-body); font-style: italic; }
.mz-bp-sz { font-family: var(--font-code); font-size: 7px; color: var(--text-faint); }
.mz-cv { display: block; width: 100%; height: 82px; padding: 4px 0 2px; }

/* ── item 4: highlight → act. The shipping editor's selection surface —
      a capsule while the agent reads the selection, the verbs it coined, each
      bound to one of three closed routes, and the ask stud. The beat plays the
      ✎ route through to an accepted proposal; the pills stay live after. ── */
.mz-selt {
  border-radius: 2px; box-decoration-break: clone; -webkit-box-decoration-break: clone;
  transition: background 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.mz-selt.is-sel { background: rgba(196, 93, 53, 0.16); box-shadow: 0 0 0 1px rgba(196, 93, 53, 0.22); }
.mz-selt.is-landed { background: rgba(52, 199, 89, 0.16); }
.mz-sel {
  position: absolute; z-index: 5; width: 300px;
  font-family: var(--font-ui); opacity: 0; transform: translateY(-4px);
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease-out);
}
.mz-sel.is-shown { opacity: 1; transform: none; }
.mz-sel-capsule {
  display: inline-block; padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--bg-elevated); border: 1px solid var(--hairline);
  box-shadow: 0 3px 12px -6px rgba(60, 40, 20, 0.4);
  font-size: 10px; color: var(--text-muted); white-space: nowrap;
}
.mz-sel.is-open:not(.is-working) .mz-sel-capsule { display: none; }
.mz-sel.is-open:not(.is-working) .mz-sel-pills { display: inline-flex; }
.mz-sel.is-parked { pointer-events: none; }
.mz-sel.is-parked .mz-sel-capsule, .mz-sel.is-parked .mz-sel-pills,
.mz-sel.is-parked .mz-sel-shelf, .mz-sel.is-parked .mz-ask { display: none; }
.mz-sel-pills {
  display: none;
  align-items: center; gap: 3px; padding: 3px; border-radius: var(--radius-pill);
  background: var(--bg-elevated); border: 1px solid var(--hairline);
  box-shadow: 0 4px 16px -8px rgba(60, 40, 20, 0.45);
}
.mz-pill {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px;
  border-radius: var(--radius-pill); font-family: var(--font-ui); font-size: 10.5px;
  color: var(--text-secondary); white-space: nowrap; cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.mz-pill:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.mz-pill.is-armed { background: var(--accent-soft); color: var(--accent); }
.mz-pill-glyph { font-size: 9px; opacity: 0.65; }
.mz-stud {
  flex: none; width: 20px; height: 20px; border-radius: 50%; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; color: var(--accent); background: var(--accent-soft);
}
.mz-sel-shelf {
  margin-top: 5px; padding: 7px 9px; border-radius: 9px;
  background: var(--bg-elevated); border: 1px solid var(--hairline);
  box-shadow: 0 6px 18px -10px rgba(60, 40, 20, 0.45);
  font-size: 10.5px; line-height: 1.5; color: var(--text-secondary);
  opacity: 0; transform: translateY(-3px); pointer-events: none;
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
.mz-sel-shelf.is-on { opacity: 1; transform: none; }
.mz-shelf-foot {
  display: block; margin-top: 5px; font-family: var(--font-code); font-size: 8px;
  letter-spacing: 0.05em; color: var(--text-faint);
}
.mz-ask { display: none; align-items: center; gap: 6px; margin-top: 5px; padding: 4px 5px 4px 10px;
  border-radius: var(--radius-pill); background: var(--bg-elevated);
  border: 1px solid var(--hairline); box-shadow: 0 4px 16px -8px rgba(60, 40, 20, 0.45); }
.mz-sel.is-asking .mz-ask { display: flex; }
.mz-ask-in {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  font-family: var(--font-ui); font-size: 11px; color: var(--text-primary);
}
.mz-ask-chip {
  flex: none; padding: 2px 7px; border-radius: var(--radius-pill);
  font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.06em;
  color: var(--text-muted); background: var(--bg-tertiary); white-space: nowrap;
}
.mz-ask-chip.is-thread { color: var(--accent); background: var(--accent-soft); }

/* the inline proposal — nothing is written to the document until accept */
.mz-proposal {
  margin: 10px 0 13px; padding: 9px 11px 8px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px solid var(--hairline);
  box-shadow: 0 4px 16px -10px rgba(60, 40, 20, 0.4);
  opacity: 0; transform: translateY(-4px);
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease-out);
}
.mz-proposal.is-on { opacity: 1; transform: none; }
.mz-prop-head {
  font-family: var(--font-code); font-size: 8px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 5px;
}
.mz-prop-was, .mz-prop-now { font-size: 12.5px; line-height: 1.55; margin: 0; }
.mz-prop-was s { color: var(--text-faint); text-decoration-color: rgba(255, 59, 48, 0.5); }
.mz-prop-now { color: var(--text-primary); }
.mz-prop-acts { display: flex; gap: 7px; margin-top: 8px; }
.mz-prop-yes, .mz-prop-no {
  font-family: var(--font-ui); font-size: 10.5px; padding: 3px 10px;
  border-radius: var(--radius-pill); cursor: pointer;
  transition: background 0.15s var(--ease), transform 0.12s var(--ease);
}
.mz-prop-yes { color: var(--accent); background: var(--accent-soft); }
.mz-prop-no { color: var(--text-muted); background: var(--bg-tertiary); }
.mz-prop-yes.is-pressed { transform: scale(0.94); background: rgba(196, 93, 53, 0.22); }

/* route ◇ — the element the agent sketched, landed in the document */
.mz-figwrap { opacity: 0; transform: translateY(5px); transition: opacity 0.3s var(--ease), transform 0.3s var(--ease-out); }
.mz-figwrap.is-on { opacity: 1; transform: none; }
.mz-fig {
  margin: 10px 0 13px; padding: 8px 11px 10px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px solid var(--divider-light);
}
.mz-fig-cap {
  font-family: var(--font-code); font-size: 8px; letter-spacing: 0.07em;
  color: var(--text-faint); margin-bottom: 5px;
}

/* ── under the window: one reserved box holds the hint pill (beats 0–1) and
      the lede + CTA (settle, t+550ms) — they trade places, nothing shifts ── */
/* 60px, not 92: this box exists to hold the hint pill, which is absolutely
   positioned at top:24px and ~34px tall, and which is hidden outright at `mz`
   and `settled`. The 32px it gives back goes to the document — and, because
   it is a flex item the desk is centred against, shrinking it also stops the
   desk being pushed toward the top of the viewport at settle, when this box
   is holding nothing at all. */
.mz-below { position: relative; z-index: 3; width: min(1460px, 90vw); height: 60px; margin-top: clamp(12px, 2.2vh, 26px); }
.mz-hint {
  position: absolute; left: 50%; top: 24px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-family: var(--font-ui); font-size: 12px; color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.5); border: 1px solid var(--hairline);
  border-radius: var(--radius-pill); padding: 7px 15px;
  opacity: 0; pointer-events: none; transition: opacity 0.5s var(--ease);
}
.mz-hero.hint-on .mz-hint { opacity: 1; pointer-events: auto; }
.mz-hero.hint-on .mz-hint:hover { color: var(--text-primary); border-color: var(--hairline-strong); }
.mz-hint kbd {
  padding: 1px 6px; border: 1px solid var(--divider); border-radius: 4px;
  background: var(--bg-secondary); color: var(--text-secondary);
  font-family: var(--font-ui); font-size: 10.5px; font-weight: 500; line-height: 1.5;
}
.mz-hero[data-mz="mz"] .mz-hint, .mz-hero[data-mz="settled"] .mz-hint,
.mz-hero[data-mz="mz"].hint-on .mz-hint, .mz-hero[data-mz="settled"].hint-on .mz-hint {
  opacity: 0; pointer-events: none; transition-duration: calc(0.3s * var(--mzs));
}
/* ── the dock (macOS) / taskbar (Windows): one choreography, two costumes ── */
.mz-dock {
  position: absolute; left: 50%; bottom: 12px; z-index: 3;
  display: flex; gap: 9px; padding: 7px 9px; border-radius: 19px;
  background: rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset, 0 10px 26px -8px rgba(60, 40, 20, 0.28);
  backdrop-filter: blur(16px) saturate(1.4); -webkit-backdrop-filter: blur(16px) saturate(1.4);
  opacity: 0; transform: translate(-50%, 150%);
  transition: opacity calc(0.8s * var(--mzs)) var(--ease-out) calc(0.45s * var(--mzs)),
              transform calc(0.8s * var(--mzs)) var(--ease-out) calc(0.45s * var(--mzs));
}
[data-mz="mz"] .mz-dock, [data-mz="settled"] .mz-dock { opacity: 1; transform: translate(-50%, 0); }
/* each tile is a drawn app icon, not a tinted square: macOS's squircle radius
   (~22% of the side), a vertical gradient, a glyph, and the dock's cast
   shadow. Four are generic desk companions drawn inline as SVG; the live one
   is HudHud itself — hudhud-logo.png, shipped beside the page in both trees
   so the source page and the build render the same pixels. */
.mz-dock i {
  position: relative; display: block; width: 40px; height: 40px; border-radius: 9px;
  background-size: cover; background-position: center;
  box-shadow: 0 1px 1.5px rgba(29, 29, 31, 0.22), 0 4px 8px -3px rgba(60, 40, 20, 0.3);
}
.mz-dock i:nth-child(1) { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%238ED0FF'/%3E%3Cstop offset='1' stop-color='%233E9BEF'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%234FA9F5'/%3E%3Cstop offset='1' stop-color='%231B72D6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='80' height='80' rx='18' fill='url(%23a)'/%3E%3Cpath d='M42 0h20a18 18 0 0 1 18 18v44a18 18 0 0 1-18 18H42c-7-12-10-26-10-40s3-28 10-40z' fill='url(%23b)'/%3E%3Cpath d='M22 30v12M58 30v12' stroke='%23153F66' stroke-width='4' stroke-linecap='round'/%3E%3Cpath d='M18 52q22 14 44 0' stroke='%23153F66' stroke-width='4' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); }
.mz-dock i:nth-child(2) { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cdefs%3E%3ClinearGradient id='n' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23FCE283'/%3E%3Cstop offset='1' stop-color='%23F5C64B'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='80' height='80' rx='18' fill='%23FFFDF6'/%3E%3Cpath d='M0 18A18 18 0 0 1 18 0h44a18 18 0 0 1 18 18v6H0z' fill='url(%23n)'/%3E%3Crect x='16' y='38' width='48' height='4' rx='2' fill='%23C9C2B2'/%3E%3Crect x='16' y='50' width='48' height='4' rx='2' fill='%23D6D0C0'/%3E%3Crect x='16' y='62' width='30' height='4' rx='2' fill='%23D6D0C0'/%3E%3C/svg%3E"); }
.mz-dock i:nth-child(3) { background-image: url("hudhud-logo.png"); }
.mz-dock i:nth-child(4) { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%2359B4F8'/%3E%3Cstop offset='1' stop-color='%231E6FE0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='80' height='80' rx='18' fill='url(%23m)'/%3E%3Crect x='15' y='24' width='50' height='34' rx='5' fill='%23FFFFFF'/%3E%3Cpath d='M17 27l23 17 23-17' stroke='%23A9CBF0' stroke-width='3' fill='none' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.mz-dock i:nth-child(5) { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cdefs%3E%3ClinearGradient id='c' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23FFFFFF'/%3E%3Cstop offset='1' stop-color='%23ECEAE4'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='80' height='80' rx='18' fill='url(%23c)'/%3E%3Cpath d='M0 18A18 18 0 0 1 18 0h44a18 18 0 0 1 18 18v4H0z' fill='%23EC5B49'/%3E%3Ctext x='40' y='63' text-anchor='middle' font-family='-apple-system, Helvetica, Arial, sans-serif' font-size='40' font-weight='300' fill='%23444444'%3E1%3C/text%3E%3C/svg%3E"); }
.mz-dock i.is-live::after {
  content: ""; position: absolute; left: 50%; bottom: -5px; transform: translateX(-50%);
  width: 3px; height: 3px; border-radius: 50%; background: var(--text-muted);
}
.mz-taskbar {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3; height: 42px;
  display: flex; align-items: center; gap: 10px; padding: 0 calc(12px + var(--mz-desk-crop, 0px));
  background: rgba(250, 250, 248, 0.78); border-top: 1px solid var(--hairline);
  backdrop-filter: blur(16px) saturate(1.4); -webkit-backdrop-filter: blur(16px) saturate(1.4);
  opacity: 0; transform: translateY(100%);
  transition: opacity calc(0.8s * var(--mzs)) var(--ease-out) calc(0.45s * var(--mzs)),
              transform calc(0.8s * var(--mzs)) var(--ease-out) calc(0.45s * var(--mzs));
}
[data-mz="mz"] .mz-taskbar, [data-mz="settled"] .mz-taskbar { opacity: 1; transform: none; }
.mz-tb-tiles { display: flex; gap: 8px; }
.mz-tb-tiles i {
  position: relative; display: block; width: 26px; height: 26px; border-radius: 6px;
  background: linear-gradient(165deg, #FFFFFF, #E6E0D4);
  box-shadow: inset 0 0 0 1px rgba(29, 29, 31, 0.07);
}
.mz-tb-tiles i.is-live { box-shadow: inset 0 0 0 1px rgba(29, 29, 31, 0.12), 0 2px 0 var(--text-muted) inset; }
.mz-tb-clock { margin-left: auto; }
[data-platform="mac"] .mz-taskbar, [data-platform="win"] .mz-dock { display: none; }
[data-platform="win"] .mz-menubar { display: none; }
[data-platform="win"] .mz-field { padding: 0 0 56px; }

.page-bar { transition: opacity 0.5s var(--ease); }
/* while the desktop is up, the site's own bar yields to the OS chrome */
.page-bar.is-yielded { opacity: 0; pointer-events: none; }

/* ═══ §2 — the deep dive opens on plain paper ═══ */
.s2-stage {
  position: relative; z-index: 2; width: 100%;
  display: flex; flex-direction: column; align-items: center;
  margin-top: clamp(34px, 5vh, 62px);
}
.s2-end { width: 1px; height: 1px; }
.mz-endmark { position: absolute; left: 0; bottom: 0; width: 1px; height: 1px; pointer-events: none; }

@media (max-width: 900px) {
  .mz-hero { --mz-doc-h: clamp(300px, calc(100vh - 262px), 480px); }
  .mz-window { width: 94vw; }
  .mz-doc-inner { grid-template-columns: 1fr; gap: 16px; justify-content: stretch; }
  .mz-rail { border-top: 1px solid var(--hairline); padding-top: 14px; }
  .mz-note { margin-top: 0 !important; }
  .mz-note::before, .mz-note .mn-connector { display: none; }
  .mz-note-inner { padding-left: 0; }
  .mz-note-act { margin-left: 0; }
}
@media (max-width: 640px) {
  .mz-below { height: 128px; }
  .mz-hint { white-space: normal; text-align: center; max-width: 88vw; }
  .mz-dock i { width: 32px; height: 32px; border-radius: 8px; }
  .mz-menubar { gap: 12px; padding: 0 10px; }
  .mz-mb-menu { display: none; }
}
/* reduced motion: both states are rendered at once, no pin, no seam, no scrub */
@media (prefers-reduced-motion: reduce) {
  .mz-field { height: auto; min-height: 100vh; padding: 40px 0 0; }
  .mz-caret { animation: none; }
}

/* The editor window — grown wide and landscape (D1): the doc and the margin
   rail breathe. Used twice on the page (here and in the build). */
.editor-window {
  position: relative; z-index: 2;
  width: min(1380px, 92vw);
  height: clamp(620px, 78vh, 880px);
  display: flex; flex-direction: column;
  background: var(--bg-primary); border-radius: 14px; overflow: hidden;
  box-shadow: var(--shadow-window), 0 26px 64px -44px rgba(60, 40, 20, 0.26);
  font-family: var(--font-ui);
}
.editor-window { opacity: 0; transform: translateY(18px); }
.editor-window.is-up {
  opacity: 1; transform: none;
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}
.drag-strip {
  height: 34px; flex: none; display: flex; align-items: center; padding: 0 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(247, 247, 244, 0.35));
}
.traffic { display: flex; align-items: center; gap: 8px; }
.traffic span {
  width: 13px; height: 13px; border-radius: 50%; display: block;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.55), inset 0 -1px 1px rgba(0, 0, 0, 0.10),
              0 0.5px 1px rgba(0, 0, 0, 0.08);
}
.window-tabs {
  flex: none; display: flex; align-items: flex-end; gap: 2px;
  padding: 0 12px; background: var(--bg-secondary);
  border-bottom: 1px solid var(--divider-light); font-size: 12px;
}
.wtab {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--text-secondary); padding: 7px 14px 8px;
  border-radius: 8px 8px 0 0; white-space: nowrap;
}
.wtab-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; transition: background 0.3s; }
.wtab-dot--complete  { background: var(--status-green); }
.wtab-diamond { font-size: 10px; }
.wtabs-new { color: var(--text-muted); padding: 7px 10px 8px; }

/* hero document: prose + margin rail, native scroll inside the window */
.doc-scroll { flex: 1; overflow-y: auto; overscroll-behavior: contain; position: relative; }
.doc-inner {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 700px) 244px;
  justify-content: center;
  gap: clamp(30px, 5vw, 72px);
  padding: 30px clamp(18px, 3vw, 34px) 110px clamp(22px, 3.4vw, 44px);
}
.doc-prose { font-family: var(--font-body); font-size: 16px; line-height: 1.72; min-width: 0; }
.doc-prose h3 {
  font-size: 23px; font-weight: 700; line-height: 1.25;
  margin: 28px 0 12px; font-family: var(--font-body);
}
.doc-prose h3:first-child { margin-top: 0; }
.doc-prose p { margin: 0 0 13px; }
.doc-prose ul { margin: 0 0 13px; padding-left: 20px; }
.doc-prose li { margin: 0 0 7px; }
.doc-prose code {
  font-family: var(--font-code); font-size: 0.88em;
  background: var(--bg-secondary); border-radius: 3px; padding: 0 3px;
}
/* anchored phrases — tap one and the margin answers (D5.1) */
.anchor-phrase {
  border-bottom: 1px dashed rgba(196, 93, 53, 0.5); cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.anchor-phrase:hover { border-bottom-color: var(--accent); background: var(--accent-soft); }
/* ghost-text continuation in the hero editor doc (renderFilm emits these for
   any film block with a `ghost:` field — plan-mode/A-B/company films) */
.doc-caret {
  display: inline-block; width: 1px; height: 1em; background: var(--text-primary);
  vertical-align: -2px; margin-left: 1px;
}
.ghost-run { color: var(--text-muted); font-style: italic; opacity: 0.6; }
.ghost-hint { display: inline-flex; margin-left: 8px; vertical-align: 1px; }
.ghost-hint kbd {
  padding: 1px 6px; border: 1px solid var(--divider); border-radius: 4px;
  background: var(--bg-secondary); color: var(--text-secondary);
  font-family: var(--font-ui); font-size: 0.72em; font-weight: 500; line-height: 1.4;
  font-style: normal;
}
/* objective-context widget (as the editor renders it, simplified honestly) */
.oc-widget {
  border: 1px solid var(--hairline-strong); border-radius: 10px;
  padding: 13px 15px; margin: 4px 0 14px; font-family: var(--font-ui);
  background: var(--bg-primary);
}
.oc-prose { font-family: var(--font-body); font-size: 13.5px; color: var(--text-secondary); margin: 0 0 9px; line-height: 1.55; }
.oc-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 4px; }
.oc-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10.5px; color: var(--text-secondary);
  border: 1px solid var(--divider-light); border-radius: 999px; padding: 2px 9px;
}
.oc-chip .k { color: var(--text-muted); font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em; }
.oc-code {
  margin: 9px 0 0; background: var(--bg-secondary); border-radius: 8px;
  padding: 10px 12px; overflow-x: auto;
}
.oc-code pre { margin: 0; font-family: var(--font-code); font-size: 11.5px; line-height: 1.6; color: var(--text-primary); }
.oc-code .cm { color: var(--text-muted); }
.oc-code .kw { color: #8250DF; }
.oc-code .ty { color: #953800; }
.oc-canvas { margin: 9px 0 0; }
.oc-canvas svg { display: block; width: 100%; height: auto; }
.oc-canvas .cnode { fill: var(--bg-elevated); stroke: var(--divider); }
.oc-canvas .cnode--accent { stroke: var(--accent); }
.oc-canvas text { font-family: var(--font-ui); font-size: 10px; fill: var(--text-secondary); }
.oc-canvas .cedge { stroke: var(--divider); fill: none; }
/* capability list (serif card, mirrors capabilityList.ts) */
.cap-list {
  border: 1px solid rgba(174, 174, 178, 0.45); border-radius: 10px;
  padding: 13px 17px; margin: 14px 0 0; font-family: var(--font-body);
}
.cap-item { display: flex; gap: 10px; align-items: center; font-size: 13.5px; padding: 4px 0; }
.cap-check {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center; transition: background 0.3s, border 0.3s;
}
.cap-item.is-done .cap-check { background: var(--accent); border: none; }
.cap-item.is-done .cap-check { animation: check-pop 0.4s var(--ease-out); }

/* ── The margin rail: the AI's home. Collapsed notes are CHROMELESS —
   floating text reached by a hand-drawn wavy connector (ground truth §1).
   No border, no background, no shadow. ── */
.doc-rail { position: relative; min-width: 0; }
.margin-note {
  position: absolute; left: 0; right: 0;
  font-family: var(--font-ui); cursor: pointer;
  opacity: 0; transform: translateX(8px); pointer-events: none;
}
.margin-note.is-on {
  opacity: 1; transform: translateX(0); pointer-events: auto;
  transition: opacity 0.4s var(--ease) var(--d, 0s), transform 0.4s var(--ease) var(--d, 0s);
}
/* anchor dot at the note's left edge */
.margin-note::before {
  content: ""; position: absolute; left: -4px; top: 14px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--ai-dot);
  transition: background 0.2s var(--ease), opacity 0.2s var(--ease);
}
/* the defining visual: a wavy hand-drawn line, seeded per thread */
.mn-connector {
  position: absolute; top: 14px; height: 5px;
  color: var(--ai-connector); overflow: visible; pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s var(--ease) calc(var(--d, 0s) + 0.12s), color 0.2s var(--ease);
}
.margin-note.is-on .mn-connector { opacity: 1; }
.margin-note:hover::before { background: var(--accent); opacity: 0.8; }
.margin-note:hover .mn-connector { color: var(--accent); opacity: 0.35; }
.mn-inner { padding-left: 10px; padding-right: 8px; border-radius: 4px; position: relative; }
.margin-note[data-type="warning"] .mn-inner { border-left: 2px solid rgba(255, 59, 48, 0.35); }
.mn-label { display: flex; align-items: center; margin-bottom: 2px; color: var(--ai-label-color); }
/* type pill — exactly five variants, each its color on an 8% tint (margin.css) */
.mn-type {
  font-family: var(--font-ui); font-size: 9px; font-weight: 500;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 1px 5px; border-radius: 3px; line-height: 1.4;
  color: var(--text-muted); background: var(--bg-tertiary);
}
.mn-type.question     { color: var(--accent);        background: rgba(196, 93, 53, 0.08); }
.mn-type.suggestion   { color: var(--status-green);  background: rgba(52, 199, 89, 0.08); }
.mn-type.architecture { color: var(--status-orange); background: rgba(255, 149, 0, 0.08); }
.mn-type.warning      { color: var(--status-red);    background: rgba(255, 59, 48, 0.08); }
.mn-body {
  font-size: 13px; line-height: 1.55; color: var(--text-secondary);
  overflow-wrap: break-word; min-width: 0;
}
.mn-count { margin-left: 8px; font-size: 9.5px; color: var(--text-muted); letter-spacing: 0.02em; }
/* the artifact lives in the margin too: a micro-preview of the embed rides
   the collapsed note, so the visual work is visible before the tap */
.mn-embed {
  margin: 7px 0 1px; height: 56px; border-radius: 7px; overflow: hidden;
  border: 1px solid var(--divider-light);
  box-shadow: 0 2px 6px rgba(60, 40, 20, 0.08);
  transition: box-shadow 0.15s var(--ease), transform 0.15s var(--ease);
}
.mn-embed svg { display: block; width: 100%; height: 100%; }
.margin-note:hover .mn-embed {
  box-shadow: 0 0 0 1px rgba(196, 93, 53, 0.35), 0 4px 10px rgba(60, 40, 20, 0.12);
  transform: translateY(-1px);
}
.mn-body b { font-weight: 600; color: var(--text-primary); }
.margin-note.collapsed .mn-body {
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
/* footer actions — lowercase text links, quiet until hovered; NO reply here */
.mn-actions { display: flex; gap: 10px; padding: 4px 0 0 10px; }
.mn-act {
  font-family: var(--font-ui); font-size: 10.5px; color: var(--text-secondary);
  opacity: 0.45; transition: opacity 0.15s var(--ease);
}
.mn-act:hover { opacity: 1; }
/* in-flight pulsing dot — "AI is working"; hidden while the bubble is open */
.mn-activity-dot {
  position: absolute; top: 2px; right: 2px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--status-orange);
  animation: mn-activity-pulse 1.6s ease-in-out infinite;
}
@keyframes mn-activity-pulse {
  0%, 100% { opacity: 0.45; transform: scale(1); }
  50%      { opacity: 0.95; transform: scale(1.18); }
}
.margin-note.bubble-open .mn-activity-dot { display: none; }
/* spotlight dimming while a thread bubble is open (thread-bubble.css) */
.margin-note.dimmed { opacity: 0.48; filter: saturate(0.92); }
.margin-note.dimmed, .margin-note.bubble-source { transition: opacity 0.25s var(--ease), filter 0.25s var(--ease); }
.margin-note.bubble-source { opacity: 1; filter: none; }

/* objective picker riding the editor's bottom edge — half in, half out,
   its horizontal centerline on the window's edge for a smooth cut */
.picker {
  position: relative; z-index: 3;
  display: flex; gap: 6px; background: #f5f0e7;
  border: 1px solid var(--hairline); border-radius: 999px; padding: 5px 7px;
  font-family: var(--font-ui); margin-top: -20px;
  box-shadow: 0 14px 30px -14px rgba(60, 40, 20, 0.32);
}
.picker-btn {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 550; color: var(--text-secondary);
  padding: 6px 14px; border-radius: 999px; white-space: nowrap;
  transition: color 0.2s;
}
.picker-btn:hover { color: var(--text-primary); }
.picker-btn[aria-selected="true"] { background: var(--bg-primary); color: var(--text-primary); box-shadow: 0 1px 4px rgba(60, 40, 20, 0.14); }
.picker-btn .p-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--divider); flex: none; }
.picker-btn[aria-selected="true"] .p-dot { background: var(--accent); }
.picker-note {
  position: relative; z-index: 2;
  font-family: var(--font-ui); font-size: 11.5px; color: var(--text-muted);
  margin-top: 12px; text-align: center;
}
/* film switch: outgoing sinks away, incoming rises to meet the reader */
.doc-fade { transition: opacity 0.18s var(--ease), transform 0.18s var(--ease); }
.doc-fade.is-out { opacity: 0; transform: translateY(10px); }
.doc-fade.is-in { opacity: 0; transform: translateY(14px); transition: none; }

/* ── The thread bubble — the real expanded thread (ground truth §2):
   360×436 elevated card, header close + title, turns by alignment only,
   Reply... composer, dashed orange tether. Shared by the hero (live) and
   the threads showcase (staged). ── */
.thread-bubble {
  position: absolute; width: 380px; height: 460px;
  display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--divider); border-radius: var(--radius-xl);
  background: var(--bg-elevated); box-shadow: var(--shadow-lg);
  font-family: var(--font-ui); z-index: 30; isolation: isolate;
}
.thread-bubble::after { /* resize grabber */
  content: ""; position: absolute; right: 10px; bottom: 8px; width: 18px; height: 18px;
  background: linear-gradient(135deg, transparent 0 44%, var(--divider) 44% 52%, transparent 52% 68%, var(--divider) 68% 76%, transparent 76% 100%);
  opacity: 0.9; pointer-events: none;
}
.thread-bubble.is-opening { animation: tb-bloom 0.28s var(--ease-out); }
@keyframes tb-bloom {
  from { opacity: 0; transform: scale(0.92) translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.tb-header {
  display: flex; align-items: center; gap: 8px; padding: 10px 14px;
  border-bottom: 1px solid var(--divider); flex: none; cursor: grab; user-select: none;
}
.tb-close {
  width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); color: var(--text-muted); font-size: 16px; line-height: 1; flex: none;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.tb-close::after { content: "\00d7"; }
.tb-close:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.tb-title {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13.5px; font-weight: 600; line-height: 1.2; color: var(--text-secondary);
}
.tb-messages {
  flex: 1; overflow-y: auto; padding: 14px;
  display: flex; flex-direction: column; gap: 12px; min-height: 120px;
}
.tb-msg { display: flex; flex-direction: column; gap: 6px; max-width: 100%; }
.tb-msg.ai { align-self: flex-start; }
.tb-msg.user { align-self: flex-end; align-items: flex-end; }
.tb-msg-body {
  padding: 10px 12px; border-radius: 16px; width: fit-content; max-width: 100%;
  font-size: 13px; line-height: 1.58; word-break: break-word;
}
.tb-msg.ai .tb-msg-body { background: var(--bg-secondary); color: var(--text-primary); }
.tb-msg.user .tb-msg-body { background: var(--accent); color: #fff; max-width: min(100%, 296px); }
.tb-msg-body b { font-weight: 700; }
.tb-msg.ai .tb-msg-body code {
  font-family: var(--font-code); font-size: 0.92em; padding: 0 4px; border-radius: 4px;
  background: var(--bg-tertiary); color: var(--text-secondary); display: inline-block;
}
.tb-typing {
  display: inline-flex; align-items: center; gap: 4px; padding: 10px 12px;
  border-radius: 16px; background: var(--bg-tertiary); align-self: flex-start;
}
.tb-typing span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--text-muted);
  animation: tb-typing-bounce 1.2s infinite;
}
.tb-typing span:nth-child(2) { animation-delay: 0.2s; }
.tb-typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes tb-typing-bounce {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
/* agent activity timeline — divider rule with status, mono verb, count, chevron */
.tb-activity { margin: 2px 0; }
.tb-activity-header {
  display: flex; align-items: center; gap: 8px; width: 100%;
  color: var(--text-muted); cursor: pointer;
}
.tb-activity-line { flex: 1; height: 1px; background: var(--divider); }
.tb-activity-icon { font-size: 11px; font-weight: 700; line-height: 1; flex: none; }
.tb-activity-icon.done { color: var(--status-green); }
.tb-activity-label {
  font-family: var(--font-code); font-size: 11px; line-height: 1; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 160px;
}
.tb-activity-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-pill);
  background: var(--bg-tertiary); font-family: var(--font-code); font-size: 10px; font-weight: 600; flex: none;
}
.tb-activity-chevron { font-size: 10px; flex: none; transition: transform 0.15s var(--ease); }
.tb-activity.is-open .tb-activity-chevron { transform: rotate(90deg); }
.tb-activity-log { display: none; padding: 6px 0 4px 26px; flex-direction: column; gap: 4px; }
.tb-activity.is-open .tb-activity-log { display: flex; }
.tb-activity-entry {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; line-height: 1.3; color: var(--text-secondary);
}
.tb-activity-entry .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--status-green); flex: none; }
.tb-activity-entry .verb { font-family: var(--font-code); font-weight: 600; white-space: nowrap; }
.tb-activity-entry .target { font-family: var(--font-code); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tb-activity-entry .time { margin-left: auto; font-family: var(--font-code); font-size: 10px; color: var(--text-muted); flex: none; }
/* composer — Reply... pill + ↑ */
.tb-input-area {
  display: flex; align-items: flex-end; gap: 10px;
  padding: 8px 12px 10px; border-top: 1px solid var(--divider); flex: none;
}
.tb-input {
  flex: 1; min-width: 0; min-height: 32px; max-height: 112px; resize: none;
  padding: 6px 12px; border: 1px solid var(--divider); border-radius: var(--radius-pill);
  background: var(--bg-secondary); color: var(--text-primary);
  font-family: var(--font-ui); font-size: 12px; line-height: 1.45; outline: none;
}
.tb-input:focus { border-color: var(--text-muted); background: var(--bg-tertiary); }
.tb-input::placeholder { color: var(--text-muted); }
.tb-send {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-pill); background: var(--accent); color: #fff;
  font-size: 12px; font-weight: 700; flex: none;
  transition: background 0.15s var(--ease);
}
.tb-send:hover { background: var(--accent-hover); }

/* hero tether overlay — dashed orange line + 12px accent dot at the anchor */
.tb-overlay {
  position: absolute; left: 0; right: 0; top: 69px; bottom: 0;
  overflow: hidden; pointer-events: none; z-index: 29;
}
.tb-tether-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.tb-tether-svg path {
  fill: none; stroke: var(--status-orange); stroke-opacity: 0.6;
  stroke-width: 1.5; stroke-dasharray: 4 4;
}
.tb-anchor-dot {
  position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border-radius: var(--radius-pill); background: var(--accent);
  box-shadow: 0 0 0 4px var(--bg-elevated), 0 0 0 6px var(--accent-soft);
}

/* ── The embed pair (ground truth §3): flat pill header (label + lowercase
   muted tier badge) over a framed host with a hover CTA. No icon, no menu,
   no bottom action bar — those were fabrications. ── */
.embed-pair { margin-top: 8px; width: 100%; }
.embed-pill {
  display: flex; align-items: center; gap: 6px; padding: 5px 8px;
  border-radius: var(--radius-md); border: 1px solid var(--divider-light);
  background: var(--bg-secondary); color: var(--text-muted);
  font-family: var(--font-ui); font-size: 11px; margin-bottom: 6px;
}
.embed-pill-label {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-primary); font-size: 10px; font-weight: 600;
}
.tier-badge {
  font-family: var(--font-ui); font-size: 9.5px; font-weight: 500; letter-spacing: 0.02em;
  padding: 1px 5px; border-radius: 8px; white-space: nowrap;
  background: var(--bg-tertiary); color: var(--text-muted);
}
.embed-host {
  display: block; position: relative; width: 100%; height: 198px;
  border-radius: var(--radius-md); overflow: hidden; cursor: pointer;
  background: var(--bg-primary); padding: 0; text-align: left;
  box-shadow: inset 0 0 0 1px rgba(29, 29, 31, 0.06), 0 10px 22px rgba(0, 0, 0, 0.10);
  transition: transform 0.12s var(--ease), box-shadow 0.12s var(--ease);
}
.embed-host:hover, .embed-host:focus-visible {
  transform: translateY(-1px);
  box-shadow: inset 0 0 0 1px rgba(196, 93, 53, 0.65), 0 0 0 1px rgba(196, 93, 53, 0.30), 0 14px 28px rgba(0, 0, 0, 0.16);
}
.embed-host .embed-art { display: block; width: 100%; height: 100%; }
.embed-cta {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.10), rgba(0, 0, 0, 0.45));
  color: #fff; font-family: var(--font-ui); font-size: 11px; font-weight: 500; letter-spacing: 0.03em;
  opacity: 0; transition: opacity 0.12s var(--ease); pointer-events: none;
}
.embed-host:hover .embed-cta, .embed-host:focus-visible .embed-cta { opacity: 1; }
/* the gold veil — "the AI is working on this object" (build/patch) */
.embed-veil {
  position: absolute; inset: 0; z-index: 3; border-radius: var(--radius-md);
  opacity: 0; pointer-events: none;
  background: rgba(255, 214, 10, 0.16);
  box-shadow: inset 0 0 0 1px rgba(255, 214, 10, 0.55);
  transition: opacity 0.2s var(--ease);
}
.embed-veil.is-active { opacity: 1; pointer-events: auto; animation: veil-pulse 1.8s ease-in-out infinite; }
@keyframes veil-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }

/* ═══ §2 — CAPABILITIES: three merged cards, one project ═══════════════════
   Ported from thoughts/artifacts/2026-07-13-onboarding-editor-section-merged.html (removed in 588154713826785ab)
   and re-based onto this page's own token world. ONE ARTIFACT SIZE: --art sets
   the width of all three objects (thread card, awareness room, editor frame);
   --stage-h reserves the same height in every stage, so the three read as
   siblings. Two sanctioned second worlds live inside, by design: the Awareness
   room keeps its OWN authored cool palette (--paper/--ink-r/--accent-r/--surface),
   and the editor frame embeds the real app's editor tokens (--e-*). Every other
   surface — cards, stages, kindlist, captions, dots, replay chip — speaks the
   page's tokens. ═══════════════════════════════════════════════════════════ */
.cap-grid {
  position: relative; z-index: 2; display: grid; grid-template-columns: 1fr 1fr;
  gap: 22px; width: min(1080px, 100%); margin-top: 56px;
  /* one artifact size, shared by all three stages */
  --art: 420px; --stage-h: 470px;
}
.cap-card {
  position: relative; overflow: hidden; display: flex; flex-direction: column;
  background: var(--bg-primary); border: 1px solid var(--hairline);
  border-radius: 22px; box-shadow: var(--shadow-md); padding: 30px 30px 26px;
}
.cap-card.wide { grid-column: 1 / -1; }
.cap-card h3 {
  font-family: var(--font-body); font-size: clamp(20px, 2.2vw, 25px); font-weight: 700;
  margin: 0 0 10px; letter-spacing: -0.01em; line-height: 1.2;
}
.cap-card .para {
  font-family: var(--font-body); color: var(--text-secondary); font-size: 15px;
  line-height: 1.6; margin: 0 0 16px; max-width: 46ch;
}
.cap-card .para strong { color: var(--text-primary); font-weight: 700; }

/* the replay chip — the room's "perform again" affordance */
.replay {
  position: absolute; bottom: 12px; right: 14px; z-index: 6; cursor: pointer;
  font-family: var(--font-code); font-size: 10.5px; color: var(--accent);
  background: var(--bg-primary); border: 1px solid var(--divider-light);
  border-radius: var(--radius-pill); padding: 4px 12px;
  transition: border-color 0.15s var(--ease), transform 0.12s var(--ease);
}
.replay:hover { border-color: var(--accent); }
.replay:active { transform: scale(0.95); }

/* wide card interior: copy (with the kind list) | stage */
.wide-inner { display: grid; grid-template-columns: minmax(300px, 0.95fr) 1.05fr; gap: 34px; align-items: stretch; }
.wide-copy { display: flex; flex-direction: column; align-items: stretch; padding-top: 4px; }

/* the kind list — a legend you read, that also switches the artifact. It fills
   the column the old floating capsule left empty, and teaches the three kinds. */
.kindlist { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
.kind {
  display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; align-items: center;
  text-align: left; cursor: pointer; width: 100%;
  background: transparent; border: 1px solid transparent; border-left: 3px solid transparent;
  border-radius: var(--radius-lg); padding: 9px 12px; font: inherit;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.kind:hover { background: var(--bg-secondary); }
.kind.on { background: var(--bg-secondary); border-color: var(--hairline); border-left-color: var(--accent); }
.kind .kt { font-family: var(--font-ui); font-size: 14px; font-weight: 600; color: var(--text-primary); }
.kind .kd { grid-column: 1 / -1; font-family: var(--font-ui); font-size: 12.5px; color: var(--text-secondary); line-height: 1.45; }
.kind.on .kd { color: var(--text-primary); opacity: 0.75; }

/* every stage: same reserved height, same object width, same chrome */
.stage {
  position: relative; background: var(--bg-secondary);
  border: 1px solid var(--hairline); border-radius: var(--radius-xl);
  padding: 26px 22px 22px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; overflow: hidden;
  flex: 1; min-height: var(--stage-h);
}
/* the object rises in on the page's one-beat settle (data-played), replacing the
   donor's .riser/.cargo timing — every §2 card enters under one system */
.stage .settle { width: 100%; display: flex; flex-direction: column; align-items: center; }

/* ════════ CARD 1 · thread margin with embedded artifact ════════ */
.tcard {
  width: var(--art); max-width: 100%; background: var(--bg-elevated); border-radius: var(--radius-xl);
  border: 1px solid var(--divider); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10); padding: 18px 20px 20px;
}
.thead { display: flex; align-items: center; gap: 8px; margin-bottom: 11px; }
/* kind chips = the app's real .mn-type pill recipe, sourced from page tokens */
.tchip {
  font-family: var(--font-ui); font-size: 9px; font-weight: 500;
  letter-spacing: 0.04em; text-transform: uppercase; padding: 1px 5px; border-radius: var(--radius-sm);
  color: var(--text-muted); background: var(--bg-tertiary); white-space: nowrap;
}
.tchip.arch { color: var(--status-orange); background: rgba(255, 149, 0, 0.10); }
.tchip.sug { color: var(--status-green); background: rgba(52, 199, 89, 0.12); }
.tcrumb { font-family: var(--font-code); font-size: 9.5px; color: var(--text-secondary); letter-spacing: 0.04em; }
.tprose { font-family: var(--font-body); font-size: 13.5px; line-height: 1.6; margin-bottom: 13px; }
.tprose b { font-weight: 650; }

.embed { border: 1px solid var(--divider-light); border-radius: 11px; overflow: hidden; background: var(--bg-primary); }
.embed-head {
  display: flex; align-items: center; gap: 8px; padding: 8px 11px;
  border-bottom: 1px solid var(--divider-light); background: var(--bg-secondary);
}
.embed-head .eicon { width: 15px; height: 15px; border: 1.4px solid var(--text-primary); border-radius: var(--radius-sm); display: inline-flex; align-items: center; justify-content: center; font-size: 8px; flex-shrink: 0; }
.embed-head .etitle { font-family: var(--font-ui); font-size: 11.5px; font-weight: 650; }
.embed-head .etag {
  margin-left: auto; font-family: var(--font-code); font-size: 7.5px;
  letter-spacing: 0.12em; padding: 2px 7px; border-radius: var(--radius-sm); border: 1px solid var(--divider-light);
  color: var(--text-secondary); background: var(--bg-elevated); white-space: nowrap;
}
.embed-body { padding: 11px; }

/* stack embed — Atlas departure alerts. The interior data-viz colours (blue
   route glyph, status reds) are artifact content, like the hero's embeds. */
.nrow {
  background: var(--bg-elevated); border: 1px solid var(--divider-light); border-radius: var(--radius-lg);
  padding: 9px 11px; display: flex; gap: 10px; align-items: flex-start;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); margin-bottom: 7px;
}
.nrow:last-child { margin-bottom: 0; }
.nicon { width: 25px; height: 25px; border-radius: 7px; background: #2f6fe4; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 11px; flex-shrink: 0; }
.nrow.dim .nicon { background: #a9a091; }
.nkind { font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.12em; color: var(--text-secondary); }
.nmain { font-family: var(--font-ui); font-size: 11.5px; font-weight: 650; }
.nquote { font-family: var(--font-ui); font-size: 10.5px; color: var(--text-secondary); font-style: italic; }
.nwhen { margin-left: auto; font-family: var(--font-ui); font-size: 9px; color: var(--text-secondary); white-space: nowrap; padding-left: 8px; }
.nrow.peek { margin-bottom: -16px; opacity: 0.5; }

/* chart embed — ETA-promise A/B */
.chart-head { display: flex; align-items: baseline; gap: 10px; padding: 2px 2px 7px; }
.chart-head .ct { font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.1em; color: var(--text-secondary); }
.chart-head .n { margin-left: auto; font-family: var(--font-code); font-size: 8.5px; color: var(--text-secondary); }
.legend { display: flex; gap: 8px; align-items: center; padding-bottom: 6px; flex-wrap: nowrap; }
.legend .win { font-family: var(--font-code); font-size: 7.5px; font-weight: 700; color: #fff; background: #2f9e57; padding: 2px 6px; border-radius: var(--radius-sm); white-space: nowrap; }
.legend .li { font-family: var(--font-code); font-size: 8px; color: var(--text-secondary); white-space: nowrap; }
.legend .li b.b { color: #2f9e57; } .legend .li b.a { color: var(--text-muted); }
.chart-note { font-family: var(--font-code); font-size: 8px; color: var(--text-secondary); padding: 6px 2px 0; }

/* one unified footprint — JS locks this to the tallest variant so switching never resizes */
.tbody-swap { min-height: 300px; }
.tvariant { display: none; }
.tvariant.cur { display: block; animation: swapin 0.4s var(--ease-out); }
@keyframes swapin { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ════════ CARD 3 · awareness — component-native room ════════
   Decision 3: the room keeps its OWN authored cool world untouched — this is the
   one sanctioned second palette on the page, sold by framing (the ◆ glyph, the
   "derived from route-preview.md" tag, and the caption), never re-warmed to the
   page. The route IS the module map; answers land in a reserved evidence lane. */
.room {
  --paper: #fdfcf8; --ink-r: #232b38; --accent-r: #2b62c9; --surface: #eef1f6;
  --ok: #2f9e57; --warn: #c07d2a; --bad: #c8402d; --rgrid: #dfe3ea; --dim: #8a8f9b;
  position: relative; width: var(--art); max-width: 100%;
  background: var(--paper); color: var(--ink-r);
  border: 1.5px solid #cdd4e0; border-radius: 15px;
  box-shadow: 0 12px 30px rgba(35,43,56,.13), 0 2px 8px rgba(35,43,56,.08);
  font-family: -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
}
.room .rh {
  display: flex; align-items: center; gap: 8px; padding: 9px 14px;
  font-family: ui-monospace, Menlo, monospace; font-size: 9px; letter-spacing: .14em;
  color: var(--dim); text-transform: uppercase; border-bottom: 1px solid var(--rgrid);
}
.room .rh .rd { color: var(--accent-r); }
.room .rh .rtag {
  margin-left: auto; font-size: 8px; letter-spacing: .04em; text-transform: none;
  color: var(--dim); border: 1px solid var(--rgrid); border-radius: 999px;
  padding: 2px 9px; background: var(--surface); white-space: nowrap;
}
.rbody { padding: 12px 14px 14px; }
.orient { position: relative; margin-bottom: 9px; }
.orient svg { display: block; width: 100%; }

/* the three askable marks — dashed rings make the affordance visible BEFORE hover */
.stop-hit {
  position: absolute; border-radius: 10px; cursor: pointer;
  border: 1px dashed transparent; transition: border-color .3s ease, background .3s ease;
}
.room.yourturn .stop-hit { border-color: rgba(43,98,201,.28); }
.room.yourturn .stop-hit:hover { border-color: var(--accent-r); background: rgba(43,98,201,.06); }
.stop-hit.plan { left: 4%;  top: 57%; width: 38%; height: 43%; }
.stop-hit.eta  { left: 32%; top: 1%;  width: 36%; height: 51%; }
.stop-hit.onb  { left: 78%; top: 52%; width: 22%; height: 48%; }
.armed { border-style: solid !important; border-color: var(--accent-r) !important; background: rgba(43,98,201,.08) !important; }
/* the waypoint cools once the window promise is picked */
.room .wp-hot { transition: opacity .45s ease; }
.room .wp-cool { opacity: 0; transition: opacity .45s ease; }
.room.win .wp-hot { opacity: 0; }
.room.win .wp-cool { opacity: 1; }
.rbadge {
  position: absolute; top: -7px; right: -5px; z-index: 3; font-size: 7.5px; font-family: ui-monospace, Menlo, monospace;
  background: var(--accent-r); color: #fff; border-radius: 999px; padding: 2px 7px; font-weight: 700;
  opacity: 0; transform: scale(.7); transition: opacity .35s ease, transform .35s cubic-bezier(.22,1,.36,1);
}
.answered > .rbadge { opacity: 1; transform: none; }
/* the eta mark's top-right is occupied by the DISAGREE badge — drop its receipt below */
.stop-hit.eta .rbadge { top: auto; bottom: -6px; right: 4px; }

/* ── the evidence lane: ask and answer both land here, in reserved space ── */
.lane {
  position: relative; min-height: 66px; margin-bottom: 10px;
  background: var(--surface); border: 1px solid var(--rgrid); border-radius: 10px;
  padding: 10px 12px; display: flex; align-items: center;
}
.lane.asking, .lane.answered { background: #fff; border-color: rgba(43,98,201,.45); box-shadow: 0 4px 14px rgba(35,43,56,.10); }
/* the caret slides horizontally to sit under whichever mark was asked */
.lcaret {
  position: absolute; top: -6px; left: 50%; width: 10px; height: 10px; margin-left: -5px;
  background: inherit; border-left: 1px solid var(--rgrid); border-top: 1px solid var(--rgrid);
  transform: rotate(45deg); opacity: 0;
  transition: left .45s cubic-bezier(.22,1,.36,1), opacity .3s ease, border-color .3s ease;
}
.lane.asking .lcaret, .lane.answered .lcaret { opacity: 1; background: #fff; border-color: rgba(43,98,201,.45); }
/* the three lane states stack in the same reserved box — visibility (not just opacity)
   so a faded-out state can never bleed through the one on top */
.lstate {
  position: absolute; left: 12px; right: 12px; pointer-events: none;
  opacity: 0; visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
}
.lstate.show { opacity: 1; visibility: visible; transition: opacity .3s ease, visibility 0s; }
.lidle { font-size: 11px; color: var(--dim); display: flex; align-items: center; gap: 7px; }
.lidle .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent-r); opacity: .55; flex-shrink: 0; }
.lai { font-family: ui-monospace, Menlo, monospace; font-size: 7.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--dim); display: block; margin-bottom: 3px; }
.lfield { font-size: 12.5px; color: var(--ink-r); }
.lfield .ph { color: #a3adbd; }
.tcaret { display: inline-block; width: 1.5px; height: 12px; background: var(--accent-r); vertical-align: -2px; animation: cblink 1s steps(1) infinite; }
@keyframes cblink { 50% { opacity: 0; } }
.lans-t { font-size: 12px; line-height: 1.45; display: block; }
.lans-t b { color: var(--accent-r); }
.lans-s { display: block; font-family: ui-monospace, Menlo, monospace; font-size: 8px; color: var(--dim); margin-top: 4px; letter-spacing: .04em; }

/* Atlas departure banner — the component that reacts to your stance */
.abanner {
  display: flex; gap: 10px; align-items: center;
  background: #fff; border: 1px solid var(--rgrid); border-radius: 12px;
  box-shadow: 0 3px 10px rgba(35,43,56,.08); padding: 9px 12px; margin-bottom: 9px;
}
.ab-icon { width: 28px; height: 28px; border-radius: 8px; background: var(--accent-r); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 13px; flex-shrink: 0; }
.ab-kind { font-family: ui-monospace, Menlo, monospace; font-size: 8px; letter-spacing: .1em; color: var(--dim); }
.ab-line { font-size: 12px; }
.ab-line b { font-weight: 650; }
.ab-eta {
  margin-left: auto; font-family: ui-monospace, Menlo, monospace; font-size: 11px; font-weight: 700;
  color: var(--accent-r); background: rgba(43,98,201,.08); border: 1px solid rgba(43,98,201,.35);
  border-radius: 8px; padding: 5px 10px; white-space: nowrap;
}
.ab-eta.flash { animation: etaflash .6s ease; }
@keyframes etaflash { 0% { box-shadow: 0 0 0 0 rgba(43,98,201,.4); } 100% { box-shadow: 0 0 0 8px rgba(43,98,201,0); } }

/* the promise — an Atlas segmented control; picking previews the stance in the banner */
.segrow { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.seglab { font-family: ui-monospace, Menlo, monospace; font-size: 8px; letter-spacing: .13em; text-transform: uppercase; color: var(--dim); flex-shrink: 0; }
.segctl { flex: 1; display: flex; background: var(--surface); border: 1px solid var(--rgrid); border-radius: 9px; padding: 2px; position: relative; }
.room.yourturn .segctl { box-shadow: 0 0 0 2px rgba(43,98,201,.16); }
.seg {
  flex: 1; cursor: pointer; border: none; background: transparent; border-radius: 7px;
  font-family: -apple-system, "Segoe UI", sans-serif; font-size: 10.5px; font-weight: 500;
  color: var(--dim); padding: 5px 8px; transition: all .2s ease; white-space: nowrap;
}
.seg:hover { color: var(--ink-r); }
.seg.on { background: #fff; color: var(--accent-r); font-weight: 650; box-shadow: 0 1px 4px rgba(35,43,56,.16); }

/* one doorway */
.door {
  border: 1px solid var(--rgrid); border-left: 3px solid var(--accent-r); border-radius: 9px;
  background: linear-gradient(90deg, rgba(43,98,201,.10), var(--surface)); padding: 9px 12px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  transition: box-shadow .3s;
}
.door .dt { font-size: 12.5px; font-weight: 700; display: flex; gap: 6px; }
.door .dt .st { color: var(--accent-r); }
/* evidence gets its own row — at 420px it has no business competing with the title */
.door .de { order: 3; flex-basis: 100%; font-family: ui-monospace, Menlo, monospace; font-size: 8.5px; color: var(--dim); letter-spacing: .04em; }
.door .nf { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; font-family: ui-monospace, Menlo, monospace; font-size: 8px; letter-spacing: .13em; text-transform: uppercase; color: var(--accent-r); white-space: nowrap; }
.door.lit { box-shadow: 0 0 0 2px rgba(43,98,201,.35); }

.ccursor {
  position: absolute; z-index: 10; width: 15px; height: 15px; pointer-events: none;
  opacity: 0; transition: top 1s cubic-bezier(.45,0,.25,1), left 1s cubic-bezier(.45,0,.25,1), opacity .4s ease;
}
/* stage-level caption + dots for the room — page tokens (not the room's world) */
.ccap { text-align: center; font-family: var(--font-code); font-size: 10px; letter-spacing: .08em; color: var(--text-secondary); margin-top: 14px; min-height: 26px; max-width: var(--art); line-height: 1.4; }
.rmdots { display: flex; gap: 6px; justify-content: center; margin-top: 8px; }
.rmdots i { width: 5px; height: 5px; border-radius: 50%; background: var(--divider-light); transition: background .3s, transform .3s; }
.rmdots i.on { background: var(--accent); transform: scale(1.3); }

/* ════════ CARD 2 · the editor recording — the SHIPPING app's tokens ════════
   The docframe embeds the real editor tokens (--e-*, electron-app/src/styles/
   tokens.css, light) verbatim, by design. This is the page's ONLY perpetual
   loop; it pauses off-screen and renders its final frame under reduced motion. */
.docframe {
  --e-bg:#FAFAF8; --e-panel:#FFFFFF; --e-ink:#1D1D1F; --e-sec:#6E6E73; --e-mut:#AEAEB2;
  --e-acc:#C45D35; --e-div:#D1D1D6; --e-divl:#E5E5EA; --e-bg2:#F5F5F2;
  --e-sel:rgba(196,93,53,.10); --e-dot:rgba(196,93,53,.45);
  width: var(--art); max-width: 100%; border: 1px solid var(--e-divl); border-radius: 10px;
  background: var(--e-bg); box-shadow: 0 8px 24px rgba(0,0,0,.10); overflow: hidden;
  font-family: Charter, "Bitstream Charter", "Iowan Old Style", Georgia, serif;
}
.docframe .dtab {
  display: flex; align-items: center; gap: 6px; background: var(--e-bg2);
  border-bottom: 1px solid var(--e-divl); padding: 7px 11px;
  font-family: "SF Mono", Menlo, ui-monospace, monospace; font-size: 9px; color: var(--e-sec);
}
.docframe .dtab .d { width: 6px; height: 6px; border-radius: 50%; background: var(--e-acc); opacity: .7; flex-shrink: 0; }
.docframe .rchap { margin-left: auto; font-size: 8px; letter-spacing: .1em; color: var(--e-acc); display: flex; align-items: center; gap: 5px; }
.docframe .rchap::before { content: "●"; font-size: 6px; animation: recblink 1.6s ease infinite; }
@keyframes recblink { 50% { opacity: .35; } }
/* min-height tuned so the frame stands the same height as the room next to it */
.docframe .dbody { padding: 18px 20px 20px; font-size: 14px; line-height: 1.72; min-height: 372px; color: var(--e-ink); }
.ln { margin-bottom: 11px; }
/* the toolbar hangs below the selected line — reserve the gap it lands in */
.ln.selline { position: relative; margin-bottom: 44px; }

/* ── chapter 1 · LIVE PREVIEW — Decoration.replace({}) removes the syntax from
   the DOM the moment the caret leaves the line: markers collapse to zero width. */
.syn {
  color: var(--e-mut); opacity: .9; display: inline-block; max-width: 40px;
  overflow: hidden; vertical-align: bottom; white-space: nowrap;
  transition: opacity .45s ease, max-width .45s cubic-bezier(.4,0,.2,1);
}
.rec.fold .syn { opacity: 0; max-width: 0; }
.dh {
  font-size: 14px; font-weight: 400; margin-bottom: 10px;
  transition: font-size .5s cubic-bezier(.22,1,.36,1), font-weight .3s ease;
}
.rec.fold .dh { font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
.bt { font-weight: 400; transition: font-weight .35s ease; }
.rec.fold .bt { font-weight: 700; }
/* the blink keyframe animates opacity, so show/hide the carets with visibility */
.caret { display: inline-block; width: 1.5px; height: 13px; background: var(--e-acc); vertical-align: -2px; animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.c1 { visibility: visible; }
.rec.fold .c1 { visibility: hidden; }

/* ── chapter 2 · SELECTION — the verbs are AGENT-COINED per selection
   (shared/selectionActions.ts): the toolbar reads the passage first, then
   writes its verbs. That "reading the selection…" beat is the whole point. ── */
.rec .sug-target { position: relative; border-radius: 4px; transition: background .3s ease; }
.rec.sel .sug-target, .rec.read .sug-target, .rec.tb .sug-target, .rec.hov .sug-target { background: var(--e-sel); }
.rec.anchor .sug-target { background: transparent; }
/* hand-inked anchor underline — the real app's wavy anchor, drawn on */
.inkline { position: absolute; left: -4px; right: -4px; bottom: -6px; height: 9px; overflow: visible; pointer-events: none; }
.inkline path { fill: none; stroke: rgba(196,93,53,.62); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 100; stroke-dashoffset: 100; }
.inkline path.under { stroke: rgba(196,93,53,.22); stroke-width: 2.6; }
.rec.anchor .inkline path { animation: inkdraw .52s cubic-bezier(.55,0,.3,1) forwards; }
.rec.anchor .inkline path.under { animation-duration: .6s; }
@keyframes inkdraw { to { stroke-dashoffset: 0; } }

.seltb {
  position: absolute; left: 4px; top: 100%; margin-top: 7px; z-index: 6;
  display: flex; gap: 2px; align-items: center;
  background: var(--e-panel); border: 1px solid var(--e-divl); border-radius: 999px;
  box-shadow: 0 2px 8px rgba(0,0,0,.10); padding: 4px 7px;
  font-family: -apple-system, "Segoe UI", Helvetica, sans-serif;
  opacity: 0; transform: translateY(4px); pointer-events: none;
  transition: opacity .3s ease, transform .3s cubic-bezier(.4,0,.2,1);
}
.rec.read .seltb, .rec.tb .seltb, .rec.hov .seltb { opacity: 1; transform: none; }
.rec.anchor .seltb { opacity: 0; transform: translateY(-4px); }
/* reading beat — the classify agent is looking at the passage */
.seltb .reading {
  display: none; align-items: center; gap: 6px; white-space: nowrap;
  font-size: 9px; color: var(--e-sec); padding: 2px 6px;
}
.rec.read .seltb .reading { display: inline-flex; }
.seltb .reading i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--e-acc);
  animation: rpulse 1s ease-in-out infinite;
}
@keyframes rpulse { 0%,100% { opacity: .3; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.1); } }
.seltb .verb {
  display: none; gap: 4px; align-items: center; white-space: nowrap;
  font-size: 9.5px; font-weight: 500; color: var(--e-sec);
  padding: 3px 8px; border-radius: 999px;
  opacity: 0; transform: translateY(3px);
  transition: opacity .28s ease, transform .28s ease, color .25s, background .25s;
}
.rec.tb .seltb .verb, .rec.hov .seltb .verb { display: inline-flex; opacity: 1; transform: none; }
.rec.tb .seltb .verb:nth-of-type(2), .rec.hov .seltb .verb:nth-of-type(2) { transition-delay: .10s; }
.rec.tb .seltb .verb:nth-of-type(3), .rec.hov .seltb .verb:nth-of-type(3) { transition-delay: .20s; }
.seltb .verb .g { opacity: .7; font-size: 9px; }
.rec.hov .verb.challenge { color: var(--e-acc); background: var(--e-sel); }
.rec.hov .verb:not(.challenge) { opacity: .35; }

/* thread outcome — a pulsing ai-dot above the anchored phrase, no note card */
.aidot {
  position: absolute; top: -9px; left: 50%; width: 6px; height: 6px; border-radius: 50%;
  background: var(--e-dot); opacity: 0; transform: scale(.6);
  transition: opacity .4s ease, transform .4s cubic-bezier(.4,0,.2,1);
}
.rec.anchor .aidot { opacity: 1; transform: none; animation: aidotpulse 2s ease-in-out infinite .4s; }
@keyframes aidotpulse { 50% { box-shadow: 0 0 0 4px rgba(196,93,53,.12); } }

/* ── chapter 3 · AUTOCOMPLETE ── */
.ghost { color: var(--e-mut); opacity: .6; font-style: italic; }
.tabk {
  font-family: -apple-system, "Segoe UI", Helvetica, sans-serif; font-size: .72em; font-weight: 500;
  border: 1px solid var(--e-div); border-radius: 4px; padding: 1px 6px;
  color: var(--e-sec); background: var(--e-bg2); margin-left: 8px;
}
.rec .g3 { opacity: 0; transition: opacity .6s ease, color .4s ease; }
.rec.ghostin .g3 { opacity: .6; }
.rec .t3 { opacity: 0; transition: opacity .4s ease, background .25s, color .25s, border-color .25s; }
.rec.ghostin .t3 { opacity: 1; }
.rec.tabhit .t3 { background: var(--e-acc); color: #fff; border-color: var(--e-acc); }
.rec.commit .g3 { opacity: 1; color: var(--e-ink); font-style: normal; }
.rec.commit .t3 { opacity: 0; }
.rec .c3 { visibility: hidden; }
.rec.ghostin .c3, .rec.commit .c3 { visibility: visible; }

/* stage-level caption + dots for the recording — page tokens */
.rdots { display: flex; gap: 6px; justify-content: center; margin-top: 14px; }
.rdots i { width: 5px; height: 5px; border-radius: 50%; background: var(--divider-light); transition: background .3s, transform .3s; }
.rdots i.on { background: var(--accent); transform: scale(1.3); }
.rcap { text-align: center; font-family: var(--font-code); font-size: 10px; letter-spacing: .08em; color: var(--text-secondary); margin-top: 14px; min-height: 26px; max-width: var(--art); line-height: 1.4; }

/* single-column collapse ≤900px, matching the merged section's breakpoint */
@media (max-width: 900px) {
  .cap-grid { grid-template-columns: 1fr; }
  .wide-inner { grid-template-columns: 1fr; }
  .kfoot { display: none; }
}

/* ═══ §3+§4 — THE BUILD: approve, and it builds beside you (D5.2) ════════
   No auto-start. The plan waits — calm, intentional — until the visitor's
   Approve releases the engine to claim its half of the window. */
.build-stage-wrap { position: relative; z-index: 2; width: min(1120px, 100%); margin-top: 56px; }
.build-stage {
  background: linear-gradient(180deg, #F2EBDD, #EFE6D4);
  border-radius: 18px; padding: clamp(28px, 4.5vw, 54px) clamp(18px, 4vw, 46px);
}
.build-window {
  background: var(--bg-primary); border-radius: 14px; box-shadow: var(--shadow-window);
  max-width: 940px; margin: 0 auto; overflow: hidden; font-family: var(--font-ui);
}
.build-split {
  display: grid; grid-template-columns: 1fr 0fr; min-height: 440px;
  transition: grid-template-columns 0.95s var(--ease-out);
}
#build.is-claimed .build-split { grid-template-columns: 1fr 1fr; }
.build-doc { padding: 28px 34px 26px; font-family: var(--font-body); font-size: 15px; line-height: 1.66; min-width: 0; }
.build-doc-inner { max-width: 640px; margin: 0 auto; }
.build-doc h3 { font-size: 18px; font-weight: 700; margin: 0 0 12px; }
.build-doc p { margin: 0 0 13px; }
.build-doc .thin { color: var(--text-secondary); }
.build-doc .anchor-phrase { cursor: default; }
.build-doc .anchor-phrase:hover { background: none; border-bottom-color: rgba(196, 93, 53, 0.5); }
.build-caret {
  display: inline-block; width: 1px; height: 1em; background: var(--text-primary);
  vertical-align: -2px; margin-left: 1px; animation: cursor-blink 1.15s steps(1) infinite;
}
/* the plan card — the capability list at rest, with the one affordance */
.plan-card {
  border: 1px solid rgba(174, 174, 178, 0.45); border-radius: 10px;
  padding: 13px 17px 13px; margin: 14px 0 0; font-family: var(--font-body);
  background: var(--bg-primary);
}
.plan-title {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted);
}
.plan-count { margin-left: auto; font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.plan-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--divider-light);
  font-family: var(--font-ui);
}
.approve-btn {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--accent); color: #fff;
  font-family: var(--font-ui); font-size: 12.5px; font-weight: 600;
  border-radius: 8px; padding: 7px 16px;
  transition: background 0.15s var(--ease), transform 0.15s var(--ease);
}
.approve-btn .arr { font-size: 11px; }
.approved-chip {
  display: none; align-items: center; gap: 6px;
  font-family: var(--font-ui); font-size: 11.5px; font-weight: 600; color: var(--status-green);
}
#build.is-claimed .approve-btn { display: none; }
#build.is-claimed .approved-chip { display: inline-flex; }
.approve-note { font-size: 11px; color: var(--text-muted); }
#build.is-claimed .approve-note { display: none; }
/* execution panel — mirrors .ep-* specs; SQUARE corners, deliberate divergence.
   Arrives only as a consequence of Approve: the engine claims its half. */
#build.is-claimed .ep-panel { opacity: 1; transform: none; }
.ep-inner {
  min-width: 320px; height: 100%; padding: 15px 16px 17px;
  display: flex; flex-direction: column; font-family: var(--font-ui);
}
.ep-head {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); margin: 0 0 8px; display: flex; justify-content: space-between;
}
.ep-status { text-transform: none; letter-spacing: 0; transition: color 0.4s; }
.ep-summary { display: flex; gap: 6px; align-items: baseline; margin: 0 0 10px; }
.ep-summary-label { font-size: 11px; color: var(--text-muted); }
.ep-stage { position: relative; flex: 1; min-height: 240px; }
.ep-view {
  position: absolute; inset: 0; opacity: 0; transform: translateY(10px);
  pointer-events: none; transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
}
.ep-view.is-on { opacity: 1; transform: none; pointer-events: auto; }
.ep-view.is-on .dp-card { animation: card-land 0.6s var(--ease-out); }
@keyframes card-land {
  0% { transform: translateY(10px) scale(0.97); opacity: 0; }
  70% { transform: translateY(-2px) scale(1.004); opacity: 1; }
  100% { transform: none; opacity: 1; }
}
.ep-row {
  display: flex; gap: 9px; align-items: center; padding: 6px;
  border-radius: 6px; font-size: 12px; line-height: 1.3;
}  /* static per the covenant */
.ep-activity { font-size: 11px; color: var(--text-muted); padding: 6px 6px 0; }
.dp-card {
  background: var(--bg-elevated); border: 1px solid var(--divider-light);
  border-radius: 8px; padding: 12px 14px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.dp-card-header { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.dp-card-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dp-card-dot--waiting { background: var(--status-orange); }
.dp-card-dot--done    { background: var(--status-green); }
.dp-card-title { font-size: 12px; font-weight: 600; }
.dp-card-name { font-size: 11px; color: var(--text-muted); margin-left: auto; }
.dp-card-summary { font-size: 12px; color: var(--text-secondary); margin: 4px 0 10px; line-height: 1.5; }
.dp-pr-link {
  display: inline-block; font-size: 12px; font-weight: 500;
  background: var(--accent); color: #fff; padding: 5px 10px; border-radius: 6px;
  text-decoration: none;
}
.dp-pr-link:hover { background: var(--accent-hover); }
.mono-chip { font-family: var(--font-code); font-size: 11px; }
.build-caption {
  display: flex; gap: 10px; align-items: baseline; margin: 30px auto 0;
  font-family: var(--font-ui); max-width: 940px;
}
.build-caption .tag {
  flex: none; font-size: 10px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--accent); min-width: 74px;
}
.build-caption p { margin: 0; font-size: 13px; color: var(--text-secondary); max-width: 74ch; transition: opacity 0.4s; }

/* ═══ §5 — DUSK CLOSE ════════════════════════════════════════════════════ */
/* the horizon: paper dissolves into sky — the transition IS the section break. */
.horizon { height: 44vh; min-height: 260px;
  background: linear-gradient(180deg, var(--bg-canvas) 0%, #EADCCF 30%, #C9ACA4 64%, var(--sky-dusk-high) 100%);
}
.dusk {
  position: relative; min-height: 96vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 12vh clamp(20px, 4vw, 48px) 0; overflow: hidden;
  /* the dusk skyscape rides on top; the gradients beneath are its fallback */
  background:
    url("assets/hero-image.jpg") center / cover no-repeat,
    radial-gradient(130% 60% at 50% 108%, rgba(232, 177, 131, 0.85) 0%, rgba(232, 177, 131, 0) 60%),
    linear-gradient(0deg, var(--sky-dusk-amber) 0%, var(--sky-dusk-rose) 46%, var(--sky-dusk-high) 100%);
}
.dusk::before { /* seam blend: the horizon lands on --sky-dusk-high; this feathers the painting's top edge into it */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, var(--sky-dusk-high) 0%, rgba(110, 97, 120, 0) 16%);
}
.dusk-content {
  position: relative; z-index: 2; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 0;
  /* palette-tinted scrim so text always clears the sky */
  padding: 44px clamp(24px, 6vw, 72px) 40px; border-radius: 26px;
  background: radial-gradient(88% 78% at 50% 46%, rgba(74, 56, 66, 0.34) 0%, rgba(74, 56, 66, 0.20) 58%, rgba(74, 56, 66, 0) 100%);
}
.hoopoe { width: 44px; height: auto; display: block; margin: 0 auto 22px; opacity: 0.92; }
.hoopoe path { fill: #3A2E30; }
/* dusk settle: the bird glides in first, then the copy lands line by line */
.dusk-content .hoopoe { opacity: 0; transform: translate(-30px, 12px) rotate(-4deg); }
.dusk-tagline, .dusk-sub, .waitlist-form, .wl-note { opacity: 0; transform: translateY(16px); }
.dusk-content.is-on .hoopoe {
  opacity: 0.92; transform: none;
  transition: opacity 1.2s var(--ease-out) 0.1s, transform 1.2s var(--ease-out) 0.1s;
}
.dusk-content.is-on .dusk-tagline {
  opacity: 1; transform: none;
  transition: opacity 0.8s var(--ease-out) 0.45s, transform 0.8s var(--ease-out) 0.45s;
}
.dusk-content.is-on .dusk-sub {
  opacity: 1; transform: none;
  transition: opacity 0.8s var(--ease-out) 0.62s, transform 0.8s var(--ease-out) 0.62s;
}
.dusk-content.is-on .waitlist-form {
  opacity: 1; transform: none;
  transition: opacity 0.8s var(--ease-out) 0.8s, transform 0.8s var(--ease-out) 0.8s;
}
.dusk-content.is-on .wl-note {
  opacity: 1; transform: none;
  transition: opacity 0.8s var(--ease-out) 0.95s, transform 0.8s var(--ease-out) 0.95s;
}
.dusk-tagline {
  font-family: var(--font-body); font-weight: 700; letter-spacing: -0.01em;
  font-size: clamp(32px, 5vw, 46px); line-height: 1.15; margin: 0 0 10px;
  color: #FBFAF7; text-wrap: balance; text-shadow: 0 1px 22px rgba(58, 42, 48, 0.35);
}
.dusk-sub {
  font-family: var(--font-body); font-size: 17px; color: rgba(251, 250, 247, 0.85);
  margin: 0 0 34px; max-width: 46ch;
}
.waitlist-form { display: flex; gap: 10px; width: min(440px, 88vw); }
.wl-input {
  flex: 1; min-width: 0; font-family: var(--font-ui); font-size: 14px;
  background: rgba(251, 250, 247, 0.96); color: var(--text-primary);
  border: 1px solid rgba(255, 255, 255, 0.5); border-radius: 10px; padding: 11px 14px;
}
.wl-input::placeholder { color: var(--text-muted); }
.wl-btn {
  font-family: var(--font-ui); font-size: 14px; font-weight: 600;
  background: var(--accent); color: #fff; border-radius: 10px; padding: 11px 18px;
  white-space: nowrap; transition: background 0.2s;
}
.wl-btn:hover { background: var(--accent-hover); }
.wl-note {
  font-family: var(--font-ui); font-size: 12.5px; margin: 14px 0 0; min-height: 1.4em;
  color: rgba(251, 250, 247, 0.75);
}
.wl-note.is-ok      { color: #FBFAF7; font-weight: 550; }
.wl-note.is-already { color: #FBFAF7; }
.wl-note.is-invalid { color: #FFE1C9; }
.wl-note.is-fail    { color: #FFD6C9; }
.dusk-footer {
  position: relative; z-index: 2; width: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: auto; padding: 12vh clamp(20px, 4vw, 44px) 26px;
  font-family: var(--font-ui); font-size: 11.5px; color: rgba(251, 250, 247, 0.6);
}
.dusk-footer a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(251,250,247,0.25); }
.state-preview { display: inline-flex; gap: 10px; opacity: 0.55; }
.state-preview button { font-size: 11px; color: inherit; border-bottom: 1px dotted rgba(251,250,247,0.4); }

/* ── lightbox (ground truth §3): title + TIER (uppercase only here) +
   status bar + interaction hint + the Commit composer. The gold veil
   covers the artifact while the commit applies. ── */
.lightbox {
  position: fixed; inset: 0; z-index: 200; display: none;
  align-items: center; justify-content: center;
  background: rgba(40, 32, 28, 0.42); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  padding: 24px;
}
.lightbox.is-open { display: flex; }
.lb-card {
  width: min(640px, 94vw); background: var(--bg-elevated); border-radius: 16px;
  box-shadow: 0 30px 80px rgba(40, 30, 24, 0.35); font-family: var(--font-ui); overflow: hidden;
}
.lb-head { display: flex; align-items: center; gap: 10px; padding: 13px 16px; border-bottom: 1px solid var(--divider-light); }
.lb-title { font-size: 13px; font-weight: 600; }
.lb-tier {
  font-size: 9px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted); background: var(--bg-tertiary); border-radius: 999px; padding: 2px 8px;
}
.lb-meta { font-size: 11px; color: var(--text-muted); font-family: var(--font-code); }
.lb-close { margin-left: auto; color: var(--text-muted); font-size: 16px; line-height: 1; }
.lb-art { position: relative; background: var(--bg-secondary); }
.lb-art svg { display: block; width: 100%; height: auto; }
.lb-art .embed-veil { border-radius: 0; }
.lb-status {
  display: flex; align-items: center; gap: 8px; padding: 10px 16px;
  border-top: 1px solid var(--divider-light); font-size: 11.5px; color: var(--text-secondary);
}
.lb-status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--status-green); flex: none; transition: background 0.2s; }
.lb-status.is-applying .lb-status-dot { background: var(--status-gold); animation: mn-activity-pulse 1.6s ease-in-out infinite; }
.lb-hint { margin-left: auto; color: var(--text-muted); font-size: 11px; font-style: italic; }
.lb-commit { display: flex; align-items: center; gap: 10px; padding: 4px 16px 14px; }
.lb-commit-input {
  flex: 1; min-width: 0; border: 1px solid var(--divider); border-radius: 999px;
  padding: 7px 14px; font-family: var(--font-ui); font-size: 12px;
  background: var(--bg-secondary); outline: none;
}
.lb-commit-input:focus { border-color: var(--text-muted); background: var(--bg-tertiary); }
.lb-commit-input::placeholder { color: var(--text-muted); }
.lb-commit-btn {
  background: var(--accent); color: #fff; border-radius: 8px; padding: 7px 16px;
  font-size: 12px; font-weight: 600; flex: none;
  transition: background 0.15s var(--ease), opacity 0.2s var(--ease);
}
.lb-commit-btn:hover { background: var(--accent-hover); }
.lb-commit-btn:disabled { opacity: 0.4; cursor: default; }

/* ═══ §3 — THE CLOSE ═════════════════════════════════════════════════════
   The coda. No sky, no tint, no window, no card, no section number, no
   footer: the close adds no surface of its own, and the paper ground of §2
   runs straight through it. It is the only centred block on the page — that
   break from the left-aligned document grid is the signal that the document
   is over. The signup is the document's last line, in the document's voice.

   The DUSK CLOSE rules above are the ending that was cut. They, --sky-dusk-*
   and .dusk-hoopoe-far stay in the file, deliberately unused. Don't wire
   them up here.

   No entrance: the close is the one block that must be readable the moment
   it is reached, so it carries no settle beat and no JS dependency.
   One interaction, like every scene: a caret in the field. On submit the row
   resolves into a confirmation in place. Six states, one attribute:
   idle · invalid · submitting · done · already · error ═════════════════ */
.close {
  padding: clamp(48px, 9vh, 104px) clamp(20px, 4vw, 48px) clamp(120px, 20vh, 200px);
  background: transparent;
}
.close-inner {
  width: 100%; max-width: 560px; margin: 0 auto;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.close-claim {
  font-family: var(--font-body); font-size: clamp(30px, 3.6vw, 42px);
  font-weight: 700; line-height: 1.15; letter-spacing: -0.015em;
  margin: 0; max-width: 24ch; text-wrap: balance;
}
.close-line {
  font-family: var(--font-body); font-size: 18px; color: var(--text-secondary);
  margin: 15px 0 0; max-width: 46ch; text-wrap: pretty;
}
.close-rule { display: block; width: 34px; height: 1px; margin: 32px 0 0; background: var(--hairline-strong); }

.close-form { width: 100%; margin: 30px 0 0; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.close-row {
  display: flex; align-items: stretch; gap: 10px; width: min(400px, 88vw);
  transition: opacity 0.2s var(--ease);
}
/* the label is for screen readers; the placeholder carries it visually */
.close-label {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.close-field {
  flex: 1; min-width: 0; height: 42px; padding: 0 13px; -webkit-appearance: none;
  font-family: var(--font-body); font-size: 15px; line-height: 1; color: var(--text-primary);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--divider); border-radius: var(--radius-md); outline: none;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease), background 0.16s var(--ease);
}
.close-field::placeholder { color: var(--text-muted); }
.close-field:hover { border-color: var(--hairline-strong); }
.close-field:focus {
  background: rgba(255, 255, 255, 0.94);
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.close-submit {
  height: 42px; padding: 0 18px; border: none; cursor: pointer;
  border-radius: var(--radius-md); background: var(--accent); color: #fff;
  font-family: var(--font-ui); font-size: 13px; font-weight: 600; white-space: nowrap;
  transition: background 0.16s var(--ease), transform 0.12s var(--ease);
}
.close-submit:hover { background: var(--accent-hover); }
.close-submit:active { transform: scale(0.97); }
.close-submit:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* the confirmation stands exactly where the row stood, at the row's height,
   so resolving does not move the page */
.close-resolve {
  display: none; width: min(400px, 88vw); min-height: 42px; margin: 0;
  align-items: center; justify-content: center; gap: 9px;
  font-family: var(--font-body); font-size: 16px; color: var(--text-primary);
}
.close-resolve-dot {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--status-green); box-shadow: 0 0 0 3px rgba(52, 199, 89, 0.14);
}
/* one slot, two jobs: the standing reassurance, and — while the address is
   unfinished — the correction, in the same quiet type. Nothing turns red. */
.close-note {
  width: min(400px, 88vw); margin: 0; min-height: 1.5em;
  font-family: var(--font-code); font-size: 11px; letter-spacing: 0.04em;
  line-height: 1.5; color: var(--text-secondary);
  transition: color 0.16s var(--ease);
}

.close-form[data-state='invalid'] .close-field {
  border-color: color-mix(in srgb, var(--accent) 48%, var(--divider));
  box-shadow: 0 0 0 3px var(--accent-soft);
  background: rgba(255, 255, 255, 0.94);
}
.close-form[data-state='invalid'] .close-note,
.close-form[data-state='error'] .close-note { color: var(--text-primary); }
/* in flight: the row goes quiet and stops taking input. No spinner. */
.close-form[data-state='submitting'] .close-row { opacity: 0.5; cursor: wait; pointer-events: none; }
.close-form[data-state='done'] .close-row,
.close-form[data-state='already'] .close-row { display: none; }
.close-form[data-state='done'] .close-resolve,
.close-form[data-state='already'] .close-resolve { display: flex; }

@media (max-width: 480px) {
  .close-row { flex-direction: column; }
  .close-submit { width: 100%; }
}

/* ── responsive (legacy file — mostly retired) ─────────────────────────────
   The real breakpoints for the current page live with their sections:
   hero-wallpaper.css (max-width: 900px), editor-motion.css (max-width: 900px
   collapses .pin-grid), close.css (max-width: 480px). The page-wide
   reduced-motion kill-switch lives in editor-motion.css. Only the rules below
   still match markup that exists (hero's .doc-inner / .thread-bubble and the
   page bar); the rest of the pre-reframe rules were deleted — their selectors
   (.editor-window, .doc-rail, .ep-panel, .s2-stage, .picker, .waitlist-form,
   .dusk-footer, .lb-hint, .hero-cursor, .build-caret, .caret, .tcaret,
   .docframe, .seltb, .rec.anchor) left the page with the stage reframe. ── */
@media (max-width: 880px) {
  .doc-inner { grid-template-columns: 1fr; padding-right: 28px; justify-content: stretch; }
  .thread-bubble { width: min(380px, calc(100vw - 48px)); }
}
@media (max-width: 640px) {
  body { font-size: 16px; }
  .page-bar { padding: 14px 18px; font-size: 11px; }
}

/* ═══ HudHud onboarding §2 v12 — "Think it through on the page."
   v13 — THE AWARENESS ARTIFACT (2026-08-06). Nothing structural changed here;
   the section gained ONE token, --evidence, for the measured quantity scene
   ①'s rebuilt OBSERVATION card reports. Scene ② became the awareness room and
   its stylesheet took back the editor-scene-awareness.css name — see the
   turnover note below, and the file's own header for the room.

   v12 — THE STAGE REFRAME (2026-08-05, hi-fi design round 2). Every scene now
   happens inside the same cropped app window; the shared Frame C idiom and the
   dot-grid mat that carries it moved to editor-frame.css, which is why the
   `.stage--am / --gold / --pm` day-arc mats that used to live in this file are
   gone (they were the only consumers of the dot-grid declaration, and the mat
   is now the scaled block itself — `.fc` — so the tint modifiers had nothing
   left to tint). Scene ②'s whole `.aw-*` world went with the retired example
   product; the first editor-scene-awareness.css was removed here (af0a5bc2b)
   and editor-scene-artifact.css took its slot. That file has since retired
   too, with the conflict component it drew, and the name came back at v13 for
   a different room. What changed HERE is only the copy column and the
   two shared stage controls: the scene index takes the accent, h3 loses its
   bold, the kfoot becomes the mono hint the design draws, and .stage-replay
   shrinks to a hairline disc — it is the one thing allowed into the mat's
   protected air, so it is as small as it can be and still be found.
   The v10 record follows.
   v10 — SCENE ② rebuilt (2026-07-25, Omar's feedback round). Scenes ① and ③
   untouched; the margin's pinned a→b→c→fan choreography is unchanged.
   ㉙ THE DOC-SNIPPET STRIP IS CUT. `.tdoc` (the 11.5px "…the reveal lands flat
     — Vern already knows…" line) and `.tlink` (the v7 ⑯ ink-stroke connector,
     the only consumer of --ai-dot / --ai-connector on this page) are gone,
     along with the 128px + 40px columns they held. That strip was v6 ⑨'s
     "signature anchor gesture", but it spent 27% of the 620px row on text too
     small to read and left the card itself narrow. The card is now the whole
     row; `.trow` is a plain block. Where the note landed survives as the
     header crumb (`night-shift.md · sc. 14 · p. 38`) — a reference, not a
     whisper of the prose.
   ㉚ THE NOTE GETS ROOM. `.tprose` goes 13.5px → 14px and one clipped beat →
     two or three sentences (v7 ⑰ had cut it to one on the narrow card; the
     width is back, so the reasoning comes back). Capped at 64ch so it stays a
     margin note and not an essay. The header gains a `.tmeta` timestamp.
   ㉛ THE EMBED LOSES ITS CHROME BARS. v6–v9 sandwiched every artifact between
     two filled grey strips (`.embed-head` on --bg-secondary, `.efoot` the
     same), which read greyer than the worlds inside them and made each embed
     look like a widget. Now: an unfilled title line, the artifact edge-to-
     edge, one hairline action row. The frame is felt, not seen.
   ㉜ THE THREE WORLDS ARE REDRAWN at the width the cut bought them —
     screenplay (writing), espresso order card (app UI), figure (research) —
     Apple-quiet: hairlines and inset rings over borders, pill badges, tabular
     numerals on the promise, the chart re-authored at 540×190 so it renders
     ~1:1 instead of scaling its 8px labels up 1.4×.
   The v9 record follows.
   v9 — the awareness scene becomes a DECK, and the scrub returns to scroll
   (2026-07-25, Omar's feedback round):
   ㉔ THE THREE ARTIFACTS ARE ONE FANNED DECK. v8's separate coda grid — two
     small settled sibling cards below the room — is retired. Night Shift
     (writing) and the recall study (research) are now full-size room cards
     stacked behind Cortado (code), fanned so exactly one band of each stays
     exposed: the screenplay shows its header, the study its footer. That band
     is the whole job — it has to say "screenplay" and "research" at a 30px
     crop, so each carries its own paper, its own type, and one unmistakable
     texture (a Courier scene gutter; a teal figure legend on graph paper).
   ㉕ THE TRIGGER IS SCROLL AGAIN — the primer's original ask, which v8 traded
     for a drag handle to avoid two pinned beats back to back. The deck now
     wants a held frame the way the margin does, so #s1 pins (320vh) and one
     timeline drives both beats: deck settles 0 → .20, the room comes apart
     .16 → .78, then a dwell where it is settled, armed and still pinned.
     The primer's named cost — interactions waiting on the scrub — is paid
     down by arming at .72 of the explode (the last piece lands at .70)
     rather than at .97, and by freezing the scrub while an ask popover or the
     depth page is open, so a stray nudge can't re-collapse the room.
   ㉘ THE DECK IS OPERABLE. A card behind is not art — tap its exposed band and
     it comes to the front, the other two fanning behind it; any of the three
     can lead. Feedback: "I cannot tap on the other artifact… it always will be
     overlapped by the cortado artifact." So the two other rooms are now drawn
     in full — each with its own material, its own typed pieces and its own
     card grammar (Courier on sepia stock; lab cards on the grid). The
     pull-apart still lives on Cortado alone, so there is exactly one scrubbing
     gesture on the page. Cortado's card therefore DOES carry a transform when
     it is tucked, which measure() neutralises along with the scaler and the
     phone — that is what keeps the docking geometry real.
   ㉖ SIZE: the room is authored at 580px, not 660 — the stage now holds the
     same box as the margin's cards (620) and the build window (640), and the
     scene no longer needs its own 1280px stacking rule.
   ㉗ SIMPLIFIED: kind tags moved off their floating pills and into the piece
     cards as a first line; the mark's prose note, the socket's italic caption
     and the separate ✦ footer strip are cut — provenance and the ✦ gesture
     share one bottom bar. Four pieces, one phone, one bar.
   The v8 record follows.
   v8 — the awareness scene is rebuilt as the coda cut (2026-07-25).
   Sources: thoughts/primers/2026-07-22-awareness-room-onboarding.md (the
   explode itself), thoughts/artifacts/2026-07-23-awareness-explode-
   directions.html (the three decisions), thoughts/artifacts/2026-07-23-
   awareness-scene-coda.html (the reference build ported here).
   ⑲ SCENE ① is now ONE room that comes apart. Cortado arrives WHOLE — the
     promise pill genuinely inside the order card, the tab bar inside the
     phone, docked by runtime measurement onto their real slots with card
     chrome at zero opacity. Scrubbing pulls them out while the phone scales
     1.14 → 1.0, receding to give them room; extracted pieces leave dashed
     sockets behind, derived pieces fade in en route and leave none; wires,
     then kind tags, then the ✦ footer land last. Reversibility is the
     argument — an on-load reveal can't make it, because nobody watches the
     components leave their sockets.
   ⑳ the trigger is a DRAG HANDLE, not a scroll pin — a deliberate deviation
     from the primer, which asks for scroll-scrub. #s2 (the margin, 420vh)
     owns this section's only pinned beat, and two sticky beats back to back
     read as a hijacked page. Dragging satisfies the primer's own stated
     reason for scrubbing (reversible, user-driven) and drops its one named
     cost: the room arms immediately instead of waiting for p > 0.97.
   ㉑ VERBS ONLY. Tags name what a piece does — mark·ask, control·set,
     doorway·open, silence·wake, ✦ next focus·commit. Momentum, tension and
     silence survive as colour alone (the red dot, the green ring, the
     dashed pill); v6's labelled momentum/tension/quiet legend is cut. Two
     taxonomies stacked as visible tags is how a teaching surface becomes a
     wall.
   ㉒ breadth keeps its bet without a second act: Night Shift (writing) and
     the recall study (research) sit under the room as SETTLED sibling
     artifacts, drawn post-explode in their own worlds with their own
     sockets and typed pieces. Three artifacts, three project domains, one
     interaction model. v6's tap-to-promote three-room stack is retired,
     along with its .zone stagger, .rthreads redraw wires and the shared
     #askpop element (the room now carries its own, stage-scoped).
   ㉓ the room is authored at 660px and scaled to fit its column — measure()
     neutralises that scale, so the docking stays real geometry — and below
     1280px the scene stacks so the column can give the room its width back.
   Kept live from v6, not regressed: the dark ask popover with its
   "redrawing this part of the room…" beat and an answer that changes the
   element itself; the doorway → depth → ✦ commit one level down, whose
   objective carries both the call and the control's stance.
   The v7 record follows.
   v7 — Omar's feedback round (2026-07-20), edited in place:
   ⑭ scene order is now margin → awareness → build — the margin leads the
     section; the day-arc stage tints move with the swap (margin = am,
     awareness = gold, build = pm). Copy renumbered to match. Sides swap
     too: the margin unflips (copy left, cards right), awareness flips
     (room stack left, copy right) — alternation restored.
   ⑮ the gold build veil is cut from the margin cards entirely — the
     once-per-card flash read as a stray cream background, not a signal
     (it was the margin.css .mn-embed-veil homage from v6 ⑨).
   ⑯ the doc-anchor connector is redrawn as an authentic ink stroke — a
     rested-pen blot plus a doubled freehand line with round caps —
     replacing the mechanical cut-wave S-curve.
   ⑰ margin cards lightened: card prose is down to one beat each, and
     card A's embed is rebuilt as a screenplay-editor component (file bar,
     highlighted line with its pin, tethered annotation card) instead of
     a flat block of typescript text.
   ⑱ awareness slimmed: mark rows drop their middle sentence, section
     labels tightened, door subtitles cut short, the study's paper text
     trimmed; the copy column narrows to 360px / 34ch. The scroll-
     triggered auto-ask demo is gone — the dark popover now opens only
     when a mark is tapped.
   The v6 record follows.
   ═══ v6 rebuilds SCENE ① to match the room-redesign artifact
   (thoughts/artifacts/2026-07-20-awareness-room-redesign.html, removed in 588154713826785ab
   2026-07-22; this record is its surviving spec):
   ⑩ rooms draw the PROJECT'S OWN SURFACE, not a blueprint of it — Cortado is
     its order screen on a phone, Night Shift its typescript page, the study
     its paper + fig-2; marks pin to the real elements (ring cues by kind).
   ⑪ the ask flow is the redesign's grammar: a dark popover with the question
     prefilled → "redrawing this part of the room…" → the answer lands AND
     the element itself changes (a flag on the promise, a thread to the lone
     source, the d8 line running hot).
   ⑫ provenance is visible: WHERE-IT-STANDS lines and DRAWN-FROM file chips
     cross-light the exact elements they reference.
   ⑬ sizing: the room stack widens to the redesign's proportions (660px);
     scenes ② and ③ untouched. The v5 record follows.
   ═══ v5 — "Think it through on the page."
   Rebuilt from v4 on two review findings:
   ⑤ scene ① is now a STACK of three rooms — iOS app / screenplay / research —
     tilted behind one another; hover straightens a back card, tap promotes it
     to the front (400ms, app ease-out) and its zones redraw. One room can't
     show that the agent *chooses* the shape; three visibly different shapes
     can. Each room is visual-first: the map is the card, zone status is drawn
     (green glow = momentum, red ring = tension, dashed = quiet) instead of
     mono micro-tags, and answers land as callouts anchored on the map itself —
     file-path evidence is progressive disclosure inside the callout. The
     ✦ next-focus flow lives on the anchor room (Cortado) only; it is the one
     that hands off to scenes ② and ③.
   ⑥ the copy column now top-aligns with its stage and owns the card's full
     height — kfoot pinned to the bottom edge, paras 15→16px, h3 up a step,
     a small scene index over each h3. (v4's centered copy floated as a compact
     block in dead space beside a 470px card.)
   ⑦ the rooms are no longer one blueprint skin ×3 — each is a DERIVED WORLD.
     Source: the awareness authoring contract (agents/awareness/prompt.md:
     "the visual world … is derived from the project's own identity sources …
     no two unrelated projects share a world by default"; author-interactive-
     html SKILL.md bans the cream-serif-terracotta convergence look and calls
     sub-3-color schemes "a wireframe" — the v5 blueprint tripped both).
     Cortado = the café's chalkboard (espresso paper, chalk ink, caramel
     accent); Night Shift = the typescript's corkboard (Courier, sepia paper,
     red-string character threads); the study = a graph-paper evidence wall
     (teal highlighter, mono citations — modeled on the repo's own "Cold-Start"
     example room). Every room keeps the real four-token contract
     (--paper/--ink/--accent/--surface), litters file:line evidence in muted
     mono, and signs itself with the required "world derived from: …" note.
     The header strip above each room stays HudHud chrome — the app frame
     around the artifact iframe (iframes never receive the token cascade).
   ⑧ interactions mirror the shipping iframe runtime (preview-srcdoc.ts):
     ask affordances are invisible at rest and use the real hover cue — 1px
     inset accent hairline @38% + 6% tint ("quiet, not a badge"), arming to
     62% on click; the answer lands in an ask-styled callout drawn in the
     room's own palette and pulses the real 0.9s commit shimmer. ✦ next focus
     moved OFF the entry room: doorway cards (accent left edge + tension
     subtitle, per the authoring guidance) open a depth strip, and the ✦
     commit lives only there — "✦ next focus … lives on a depth page — never
     on the entry room" (prompt.md).
   ⑨ scene ② is the same system, not a second exhibit: the margin cards carry
     the SAME three projects, each embed body rendered in its room's world
     while the card chrome stays app-warm (the layer split the real editor
     enforces). Real margin values throughout: lowercase tier badges
     annotatable / manipulable / view-only + CTAs "Annotate UI" / "Edit
     Diagram" / "View Full" (threadCodec.ts, threadEmbed*), true pill kinds
     (OBSERVATION muted / QUESTION accent / SUGGESTION green — margin.css), a
     wavy-underlined document snippet + --ai-dot + wavy connector (the
     margin's signature anchor gesture), and the wordless gold build veil
     (--status-gold @16% fill, inset 55% ring, 1.8s pulse — margin.css
     .mn-embed-veil) playing once per card on arrival. Card B is drawn as its
     opened lightbox (uppercase badge + status line) because manipulable
     embeds are static thumbnails on the card — editing happens in the
     lightbox. "Commit a stance" wording follows the product briefing
     (README §3a). Scene ③ gains one quiet line — the objective is "✦ seeded
     from Awareness" — closing the loop the room's confirm chip opens.
   Carried from v4: ① beat order is the product loop — awareness → margin →
   build; ② scenes ① and ③ sit in plain scroll flow, one gentle rise each;
   ③ the margin beat keeps the ONE piece of pinned scroll choreography;
   ④ one hero interaction per beat — promote a room / open a doorway to the
   ✦ commit, drag the pickup window, press Approve.
   Content model: anchor + cast. The anchor project is "Cortado", a coffee-shop
   ordering iOS app — its room opens the section, its plan closes it. The
   page's whole cast is three projects — Cortado (iOS app), Night Shift
   (screenplay), the recall study (research) — and the same three appear in
   the room stack and again in the margin cards, one system end to end.
   Tokens mirror electron-app/src/styles/tokens.css.
   Choreography lives behind (min-width:901px) and (prefers-reduced-motion:
   no-preference); the base document is the static, fully-readable fallback. ═══ */
#editor {  /* merged: tokens scoped so hero keeps its own --paper/--surface */
  --bg-primary: #FAFAF8;
  --bg-secondary: #F5F5F2;
  --bg-tertiary: #EDEDEA;
  --bg-elevated: #FFFFFF;
  --bg-canvas: #F5F5F2;   /* = the app's workspace field; see base.css */

  --text-primary: #1D1D1F;
  --text-secondary: #6E6E73;
  --text-muted: #AEAEB2;
  --text-faint: rgba(29, 29, 31, 0.36);

  --accent: #C45D35;
  --accent-hover: #A84E2D;
  --accent-soft: rgba(196, 93, 53, 0.10);
  --accent-soft-2: rgba(196, 93, 53, 0.18);

  /* the one colour outside the app's palette, carried in from the approved
     margin-card wireframe (2d): the measured quantity a margin OBSERVATION is
     reporting. Deliberately not the accent — the accent means "act here", and
     an observation is the one card in §2 with nothing to press. It is spent in
     exactly one place, scene ①'s evidence bar; anything else that wants a
     second colour should be asking why. */
  --evidence: #3F6B5C;

  --divider: #D1D1D6;
  --divider-light: #E5E5EA;
  --hairline: rgba(29, 29, 31, 0.08);

  --status-green: #34C759;
  --status-orange: #FF9500;
  --status-red: #FF3B30;

  --ai-label-color: rgba(0, 0, 0, 0.30);
  --ai-connector: rgba(0, 0, 0, 0.18);
  --ai-dot: rgba(196, 93, 53, 0.45);

  --font-body: Charter, 'Bitstream Charter', 'Iowan Old Style', 'Hoefler Text', Georgia, serif;
  --font-ui: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-code: 'SF Mono', ui-monospace, 'JetBrains Mono', Menlo, Consolas, monospace;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-xl: 14px;
  --radius-pill: 999px;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);

  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.08);
  --shadow-window: 0 1px 0 rgba(255, 255, 255, 0.85) inset,
                   0 0 0 1px rgba(29, 29, 31, 0.05),
                   0 2px 6px rgba(60, 40, 20, 0.06),
                   0 24px 48px -16px rgba(60, 40, 20, 0.16),
                   0 64px 120px -40px rgba(60, 40, 20, 0.30);

  /* one shared axis for the header and every scene — the v3 misalignment fix */
  /* widened 1200 → 1320 (2026-08-07, Omar): at 1200 the fixed-width 780×470
     mat rendered at ~0.85 scale — the reframe's window read small. 1320 with
     the 7.8fr stage column below lands makeFit at ~0.99, i.e. the frame is
     finally seen at the size it was authored.
     94vw → 100vw - 40px (2026-08-08, responsive polish): the frame is the
     fixed point and the page's own margins are the first thing to collapse —
     at 1280 the old 94vw kept 38px-a-side dead margin while the mat scaled
     to 0.90. A hard 20px a side hands that margin to the stage column
     instead; #capabilities' side padding is pinned to the same 20px below so
     the section box never re-narrows what the token grants. */
  --container: min(1320px, 100vw - 40px);
  /* one shared vertical gap between the three scenes */
  --scene-gap: clamp(149px, 21.6vh, 259px); /* +20% (Omar, 2026-08-06) */
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* overflow-x: clip (not hidden) — hidden creates a scroll container and kills
   position: sticky in Firefox; clip only clips */
html { -webkit-text-size-adjust: 100%; scroll-behavior: auto; overflow-x: clip; }
body {
  background: var(--bg-canvas);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}
button, input, kbd, textarea { font: inherit; color: inherit; }
button { background: none; border: none; padding: 0; cursor: pointer; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }
::selection { background: var(--accent-soft-2); color: var(--text-primary); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* ── page bar: brand + the day clock ── */
.page-bar {
  position: fixed; inset: 0 0 auto 0; z-index: 80;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 18px clamp(20px, 4vw, 44px);
  font-family: var(--font-ui); font-size: 12px; letter-spacing: 0.02em;
  color: var(--text-secondary); pointer-events: none;
  background: linear-gradient(to bottom, rgba(250, 250, 248, 0.5) 0%, rgba(250, 250, 248, 0) 100%);
}
.page-bar > * { pointer-events: auto; }
.brand {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-family: var(--font-body); font-weight: 700; font-size: 16px;
  letter-spacing: -0.01em; color: var(--text-primary); text-decoration: none;
}
.brand-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); transform: translateY(-3px);
  box-shadow: 0 0 0 4px rgba(196, 93, 53, 0.10);
}
.day-clock {
  font-feature-settings: "tnum" 1; font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--text-secondary);
}
.day-clock .dc-day { color: var(--text-faint); margin-right: 6px; }

/* ── section header — shares --container with the scenes below ── */
.sect-head {
  width: var(--container); margin: 0 auto; text-align: center;
  padding: clamp(110px, 16vh, 180px) 0 clamp(40px, 6vh, 72px);
}
.eyebrow {
  font-family: var(--font-ui); font-size: 11px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0;
}
.sect-head h2 {
  font-family: var(--font-body); font-size: clamp(32px, 4.6vw, 46px);
  line-height: 1.15; font-weight: 700; letter-spacing: -0.01em;
  margin: 14px auto 12px; text-wrap: balance; max-width: 22ch;
}
.sect-head .sub {
  font-family: var(--font-body); font-size: 19px; color: var(--text-secondary);
  max-width: 52ch; margin: 0 auto; text-wrap: balance;
}

/* #capabilities is the .section box around everything below; its side padding
   (section-scaffold.css, clamp to 48px) predates the frame-holds policy. The
   pin-grid is width: var(--container) with auto margins, and a block wider
   than its padded containing block zeroes those margins and overflows to the
   RIGHT only — so at moderate widths the section padding both re-narrowed the
   axis and skewed it. Pinned to the 20px the --container arm already
   reserves, the two agree at every width and centring stays symmetric. */
#capabilities { padding-inline: 20px; }

/* ── scene scaffolding — base is static & fully readable; pinning is layered
     on for wide screens + motion-tolerant visitors ── */
.scene { position: relative; }
.scene-pin { position: relative; }
/* The grid's one job since the responsive polish (2026-08-08): THE FRAME
   HOLDS, THE COPY COLUMN FLEXES. The stage track is capped at 780px — the
   mat's authored width, so makeFit sits at scale 1 whenever the track is
   full — and the copy column is the elastic one, absorbing surplus on wide
   pages and giving way first as the page narrows. Only once copy hits its
   250px floor (~1080px viewport, with the collapsed margins and gap) does
   the stage track start shrinking and makeFit begin to scale the mat at
   all — under the old 4.2fr/7.8fr split the mat was already at 0.90 by
   1280. Track floors: copy 250px ≈ 28ch of the 17px para, held readable;
   stage minmax(0,…) so sub-scope widths still resolve. */
.pin-grid {
  width: var(--container); margin: 0 auto;
  display: grid; grid-template-columns: minmax(250px, 1fr) minmax(0, 780px);
  gap: clamp(24px, 3vw, 60px); align-items: stretch;
  padding: var(--scene-gap) 0;
}
.scene--flip .pin-grid > .beat-copy { order: 2; }
.scene--flip .pin-grid > .stage-cam { order: 1; }
/* the flipped scene leads with its stage — the mirrored split of the shared one,
   so every scene's stage square is the same width */
.scene--flip .pin-grid { grid-template-columns: minmax(0, 780px) minmax(250px, 1fr); }

/* beat copy voice — a full-height column: index + h3 + paras at the top,
   the try-it kfoot pinned to the card's bottom edge (v5 fix: v4 centered a
   compact block against a 470px+ card) */
.beat-copy {
  max-width: 490px; min-width: 0;
  display: flex; flex-direction: column; padding-top: 6px;
}
.scene-ix {
  font-family: var(--font-code); font-size: 10px; font-weight: 400;
  letter-spacing: 0.09em;
  color: var(--accent-hover); margin: 0 0 18px;
}
.scene-ix b { font-weight: 400; margin-right: 3px; }
.beat-copy h3 {
  font-family: var(--font-body); font-size: clamp(25px, 2.3vw, 30px); font-weight: 400;
  margin: 0 0 18px; letter-spacing: -0.012em; line-height: 1.25; text-wrap: pretty;
}
.beat-copy .para {
  font-family: var(--font-body); color: var(--text-secondary); font-size: 17px;
  line-height: 1.66; margin: 0 0 14px; max-width: 44ch; text-wrap: pretty;
}
.beat-copy .para strong { color: var(--text-primary); font-weight: 600; }
/* the hairline-topped footer hint — mono, not the italic serif it was through
   v11: the copy column's three voices are now index, prose and hint, and the
   hint belongs with the stage captions it rhymes with, not with the prose */
.kfoot {
  margin: auto 0 0; padding-top: 16px; border-top: 1px solid var(--hairline);
  font-family: var(--font-code); font-size: 9.5px; letter-spacing: 0.07em;
  line-height: 1.7; color: var(--text-muted);
}

/* the stage: the creamy square card each artifact sits on */
/* no will-change here: it pins the layer's raster scale for the whole pinned
   scene, so every glyph inside the scaled room stays soft */
.stage-cam { min-width: 0; }
/* `border: none` is doing work, not stating a default: orphan-capabilities.css
   declares its own `.stage` with `border: 1px solid var(--hairline)` and loads
   EARLIER in STYLE_ORDER, so simply deleting the declaration here hands the
   stroke back to the orphan rule instead of removing it. The stroke went
   because the dot grid below already defines the surface and the line boxed it
   in. */
.stage {
  position: relative; background: var(--bg-secondary);
  border: none; border-radius: var(--radius-xl);
  /* horizontal padding trimmed 26 → 20 with the container widening above:
     both changes serve the same goal — hand the fixed-width mat enough column
     that makeFit stops shrinking it */
  padding: 28px 20px 22px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; overflow: hidden;
  min-height: 470px;
}
/* the mono caption under each stage. Since the reframe it sits OUTSIDE .stage
   as a sibling — the mat is now the composition itself, edge to edge, and the
   caption is the page talking about it rather than part of it. */
.stage-note {
  margin: 14px 0 0; font-family: var(--font-code); font-size: 9.5px;
  letter-spacing: 0.08em; color: var(--text-muted); text-align: center;
  min-height: 14px; transition: opacity 0.25s var(--ease);
}
/* ↺ replay — the scenes autoplay their timeline once on arrival, so this is
   the only way back to the start, and it is the ONE thing the reframe allows
   into the mat's protected air (top / far right). Drawn as a hairline disc so
   it can be found without competing with the window below it; the accent
   arrives on hover only, where it means "act here". The driver builds it, so
   it is absent from the frames that never animate. */
.stage-replay {
  position: absolute; top: 14px; right: 16px; z-index: 4;
  width: 24px; height: 24px; padding: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-code); font-size: 11px; line-height: 1;
  color: #8E8E93;
  background: rgba(255, 255, 255, 0.66); border: 1px solid rgba(29, 29, 31, 0.10);
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.stage-replay:hover, .stage-replay:focus-visible {
  color: var(--accent-hover); border-color: rgba(196, 93, 53, 0.45); background: #FFFFFF;
}

/* ═══ FRAME C — the shared window every scene now happens inside (v12) ═══
   The reframe's one structural idea: the three scenes used to float their UI
   as bare cards on the dot-grid mat, which read as *illustrations of* the
   product. The hero earns its credibility by materialising the app around the
   text; this extends that promise down the page. Every scene is the same
   cropped HudHud window on the same paper.

   The crop is the composition, not an accident:
     · the window is ~90% of the mat wide (736 of 780) and bleeds off the mat's
       BOTTOM and LEFT edges (left:-34, bottom:-30) — so its bottom-left radius
       is knowingly sacrificed. The camera has leaned closer, like the hero's.
     · the breathing room that leaves gathers at the TOP and FAR RIGHT and
       stays empty. That air is design. The only thing allowed to sit in it is
       .stage-replay.
     · the chrome is one slim row — traffic lights and the document tab
       together, no separate title strip above the tabs — which is what the
       real app draws (renderer window chrome) and what the hero already
       mirrors. padding-left:48px is what clears the cropped edge.

   Sizing: the mat is authored at a fixed 780×470 and scaled to whatever the
   column gives it by makeFit() in editor-scenes.js — the same fixed-width
   authoring the scenes have always used, moved up to the mat so the crop
   itself stays proportional. transform-origin is top-left here (the old
   blocks were centred), so with no JS at all the mat simply overflows to the
   right and .stage clips it — losing empty air and nothing else. ═══ */

/* the mat: .stage becomes a transparent, shrink-to-fit holder and the dot grid
   moves onto the scaled block, so the paper is exactly the composition */
.stage--frame {
  padding: 0;
  min-height: 0;
  background: none;
  align-items: flex-start;
  justify-content: flex-start;
  /* the base .stage rounds all four corners and clips — soften the bottom-left
     to a whisper (3px ≈ 20% of --radius-xl) so the cropped corner reads nearly
     square; all three clip layers (.stage--frame, .fc, .fc-win) must agree or
     the largest radius wins visually (Omar, 2026-08-06) */
  border-radius: var(--radius-xl) var(--radius-xl) var(--radius-xl) 3px;
}

.fc {
  position: relative; flex: none;
  width: 780px; height: 470px;
  /* bottom-left at 3px, matching .stage--frame's softened crop corner */
  border-radius: var(--radius-xl) var(--radius-xl) var(--radius-xl) 3px; overflow: hidden;
  background:
    radial-gradient(circle, rgba(29, 29, 31, 0.18) 1px, transparent 1.4px) 0 0 / 20px 20px,
    var(--bg-canvas);
}

/* ── the window ── */
.fc-win {
  position: absolute; left: -34px; bottom: -30px;
  width: 736px; height: 414px;
  border-radius: var(--radius-xl) var(--radius-xl) var(--radius-xl) 0;
  background: var(--bg-elevated);
  border: 1px solid rgba(29, 29, 31, 0.08);
  box-shadow: 0 20px 48px rgba(29, 29, 31, 0.10), 0 2px 6px rgba(29, 29, 31, 0.05);
  overflow: hidden;
}

/* ── chrome: one row, lights and tabs together ── */
.fc-chrome {
  height: 36px; display: flex; align-items: center; gap: 10px;
  padding-left: 48px;
  border-bottom: 1px solid rgba(29, 29, 31, 0.06);
}
.fc-traffic { display: flex; gap: 6px; flex: none; margin-right: 4px; }
.fc-traffic i { display: block; width: 9px; height: 9px; border-radius: 50%; background: #E5E4E0; }
.fc-tab {
  display: flex; align-items: center; gap: 7px; flex: none;
  padding: 4px 11px; border-radius: var(--radius-md);
  background: var(--bg-secondary);
  font-family: var(--font-code); font-size: 10px; color: var(--text-primary);
}
.fc-tab i { display: block; width: 4px; height: 4px; border-radius: 50%; background: var(--ai-dot); }
/* inactive tabs ride the strip without a card fill — the app's own idiom */
.fc-tab--quiet { background: none; color: #C9C9CC; }
.fc-tab--quiet i {
  width: auto; height: auto; border-radius: 0; background: none;
  font-style: normal; color: #D8D8DA;
}

.fc-body { position: relative; height: 378px; }

/* v13 note: .fc--dark, the modifier that turned the whole window over to the
   old scene ②'s material, was removed with that scene. The awareness room is
   light paper — the drawing wants paper — so §2 no longer has a dark beat and
   nothing in the section uses the modifier. */

/* ═══ SCENE ① · THE MARGIN — a comfortable sentence, questioned in place ═══
   (v12, the stage reframe. The Wayfare route-card embed died with the invented
   product; the card's hero is now the split itself.)

   Inside Frame C: a document that is skeleton bars except for ONE line of real
   type — the sentence the hero literally typed — and the margin card sitting
   in the margin column at truthful editor proportions, never blown up. What
   proves the card belongs to that line is the connector: measured live from
   the sentence's last line box out to the card's left edge, ending in the
   round --ai-dot the real margin system draws (marginCompanion/
   threadCardRenderer.ts).

   The card's body is the approved wireframe 2d, brought down to the margin's
   own scale: an OBSERVATION that answers with evidence rather than a chart,
   and then says out loud that it is not asking for a decision. The split
   micro-diagram and its two dashed options went with it — they argued a claim
   in pictures, where 2d states one and shows the measurement behind it.

   Beats arrive as classes on .m1 — bk1 the anchored sentence + its connector,
   bk2 the card, bkn the claim, bk3 the evidence, bk4 the delta bracket,
   bk5/bk6 the stance foot — so the fully-classed markup IS the no-JS frame.
   ═══ */

.m1-body { display: flex; gap: 24px; padding: 28px 24px 0 62px; }

/* ── the document ── */
.m1-doc { width: 340px; flex: none; display: flex; flex-direction: column; gap: 12px; }
.m1-doc i { display: block; height: 7px; border-radius: 3px; background: rgba(29, 29, 31, 0.09); }
/* the skeleton is a composition, not filler: a heading bar, a paragraph, the
   real sentence, a paragraph, a sub-heading, and the paragraph the second note
   hangs off. Widths live here so the markup stays free of style attributes
   (the CSP drops 'unsafe-inline' for style-src). */
.m1-doc i:nth-of-type(1) { width: 62%; height: 11px; background: rgba(29, 29, 31, 0.13); }
.m1-doc i:nth-of-type(2) { width: 100%; }
.m1-doc i:nth-of-type(3) { width: 93%; }
.m1-doc i:nth-of-type(4) { width: 71%; }
.m1-doc i:nth-of-type(5) { width: 88%; }
.m1-doc i:nth-of-type(6) { width: 96%; }
.m1-doc i:nth-of-type(7) { width: 44%; }
.m1-doc i:nth-of-type(8) { width: 38%; height: 9px; margin-top: 10px; background: rgba(29, 29, 31, 0.12); }
.m1-doc i:nth-of-type(9) { width: 91%; }
.m1-doc i:nth-of-type(10) { width: 84%; }
.m1-doc i:nth-of-type(11) { width: 97%; }
.m1-doc i:nth-of-type(12) { width: 58%; }

.m1-line { margin: 6px 0 0; }
/* the anchored sentence — a hairline accent rule under the type, not a wash.
   The margin voice never shouts; the connector is what carries the anchorage. */
.m1-anchor {
  font-family: var(--font-body); font-size: 14px; line-height: 22px;
  color: var(--text-primary);
  border-radius: 2px;
  box-shadow: none;
  transition: box-shadow 0.4s var(--ease);
}
.m1.bk1 .m1-anchor { box-shadow: inset 0 -1px 0 rgba(196, 93, 53, 0.28); }

/* ── the drawn connector (path measured by editor-scenes.js) ── */
.m1-conn {
  position: absolute; left: 0; top: 0; width: 736px; height: 378px;
  pointer-events: none; overflow: visible;
}
.m1-c1 {
  fill: none; stroke-linecap: round;
  stroke-dasharray: 100; stroke-dashoffset: 100;
  transition: stroke-dashoffset 0.5s var(--ease), opacity 0.3s var(--ease);
  opacity: 0;
  stroke: var(--ai-connector); stroke-width: 1.1;
}
.m1-cdot { transition: opacity 0.3s var(--ease); opacity: 0; fill: var(--ai-dot); }
.m1.bk1 .m1-c1 { opacity: 1; stroke-dashoffset: 0; }
.m1.bk2 .m1-cdot { opacity: 1; }

/* ── the margin card — editor proportions, and no card at all ──
   286px, not the 216px the column carried through v12. The evidence body needs
   to read as a measurement, and at 216px it stacked into a tall ticket: three
   or four lines of claim over two short bars over a footer. Widening the
   margin column (and narrowing the document to 340px, which still holds the
   anchored sentence on one line) buys the claim a three-line paragraph and the
   bars a 200px track — the block now sits wider than it is tall, which is what
   something reporting a number should look like.

   The white fill, the hairline and the drop shadow are gone. A raised card on
   a white page was chrome arguing that the margin is a separate surface; it
   isn't — it is the same paper, one column over. What holds the block together
   now is the connector landing on its left edge and its own internal rules,
   which is what the real margin does. */
.m1-card {
  width: 286px; flex: none; align-self: flex-start; margin-top: -6px;
  padding: 10px 12px;
  opacity: 0; transform: translateY(10px);
  transition: opacity 0.56s var(--ease-out), transform 0.56s var(--ease-out);
}
.m1.bk2 .m1-card { opacity: 1; transform: none; }

/* header: kind pill and the time it was written, nothing else. The ◆ hudhud
   author line that rode here through v12 is gone: an OBSERVATION does not need
   signing — the pill already says what kind of thinking this is — and 192px of
   content has no width to spend on chrome that repeats itself. */
.m1-chead { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; }
.m1-chip {
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.06em;
  color: var(--accent-hover); background: var(--accent-soft);
  border-radius: var(--radius-pill); padding: 2px 7px;
}
.m1-when { margin-left: auto; font-family: var(--font-code); font-size: 8.5px; color: var(--text-muted); }

/* the claim, in one line of the document's own voice: the finding bolded, and
   a second sentence that refuses the decision the first one looks like it is
   angling for. line-height drops from 1.55 to 1.5 — at 12px over 192px this
   paragraph is the card's tallest element and the four lines it takes are the
   difference between the stance foot clearing .m1-note2 and colliding with it. */
.m1-note {
  margin: 0 0 8px; font-family: var(--font-body); font-size: 12px; line-height: 1.5;
  color: var(--text-primary); text-wrap: pretty;
  transition: opacity 0.4s var(--ease); opacity: 0;
}
.m1.bkn .m1-note { opacity: 1; }
.m1-note strong { font-weight: 700; }
.m1-note em { font-style: italic; color: var(--text-secondary); }

/* ── the evidence ──
   The card answers with the measurement, not a chart of it: the population it
   was taken on, two labelled bars, and the gap between them called out by
   hand. The bars keep a FIXED 62px lane clear on the right for the bracket, so
   both fills are percentages of the same track and the eye can still trust
   their ratio. Only the spaced bar takes --evidence; the massed bar stays
   neutral, which is what makes the colour mean "the number this card is about"
   rather than "bar". */
.m1-ev {
  padding-top: 9px; border-top: 1px solid rgba(29, 29, 31, 0.09);
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
  opacity: 0; transform: translateY(8px);
}
.m1.bk3 .m1-ev { opacity: 1; transform: none; }
.m1-evhead {
  display: flex; justify-content: space-between; gap: 8px; margin-bottom: 7px;
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.07em;
  line-height: 1; color: var(--text-muted);
}

/* the 58px the bars occupy is load-bearing arithmetic, not a happy number:
   12px label + 4px + 8px track, twice, with a 10px gap. .m1-delta is placed
   against it by hand below. */
.m1-bars { position: relative; display: flex; flex-direction: column; gap: 10px; padding-right: 62px; }
.m1-blab { display: flex; align-items: baseline; gap: 6px; margin-bottom: 4px; line-height: 1; }
.m1-bname { font-family: var(--font-code); font-size: 8.5px; color: var(--text-secondary); }
.m1-bval {
  font-family: var(--font-body); font-size: 12px; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.m1-btrack { height: 8px; border-radius: 2px; background: rgba(29, 29, 31, 0.05); }
.m1-bfill { display: block; height: 8px; border-radius: 2px; }
.m1-bar--spaced .m1-bfill { width: 64%; background: var(--evidence); }
.m1-bar--quiet .m1-bname { color: var(--text-muted); }
.m1-bar--quiet .m1-bval { color: var(--text-secondary); }
.m1-bar--quiet .m1-bfill { width: 53%; background: rgba(29, 29, 31, 0.20); }

/* the delta bracket — drawn, never computed. top:19px + height:36px is exactly
   bar-centre to bar-centre inside the 58px block, so the brace is visibly
   measuring the two numbers above it and not just decorating the margin. It is
   the one place the accent appears inside this card, and at 55% it stays a
   hand annotation rather than a control. */
.m1-delta {
  position: absolute; right: 0; top: 19px; width: 56px; height: 36px;
  display: flex; align-items: center; gap: 3px;
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
  opacity: 0; transform: translateY(6px);
}
.m1.bk4 .m1-delta { opacity: 1; transform: none; }
.m1-brace { flex: none; overflow: visible; }
.m1-brace path {
  fill: none; stroke: var(--accent); stroke-width: 1;
  stroke-linecap: round; stroke-linejoin: round; opacity: 0.55;
}
.m1-dtext { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.m1-dnum {
  font-family: var(--font-body); font-size: 14px; line-height: 1;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
/* 14px breaks the card's 8.5–12px ladder by one step, on purpose and once: the
   whole card exists to deliver this number, and at 12px it sat under its own
   POINTS label instead of over it. */
.m1-dunit {
  font-family: var(--font-code); font-size: 8px; letter-spacing: 0.06em;
  line-height: 1; color: var(--accent); opacity: 0.7;
}

/* ── the stance foot ──
   §2's other cards end on an invitation with a reply count beside it. This one
   ends on one quiet way out and nothing else: the card is read-only, and the
   most honest way to say so is to give it a single link instead of a row of
   affordances. */
.m1-stance {
  margin-top: 7px; padding-top: 8px; border-top: 1px solid rgba(29, 29, 31, 0.07);
  display: flex; align-items: center; justify-content: flex-end;
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
  opacity: 0; transform: translateY(6px);
}
.m1.bk5 .m1-stance { opacity: 1; transform: none; }
.m1-full {
  flex: none; font-family: var(--font-body); font-size: 9.5px; letter-spacing: 0.01em;
  color: var(--accent);
  transition: opacity 0.2s var(--ease); opacity: 0;
}
.m1.bk6 .m1-full { opacity: 1; }

/* ═══ SCENE ② · THE AWARENESS ARTIFACT — the room the agent draws (v13) ═══
   Replaces editor-scene-artifact.css and the whole .ar-* world (the anonymous
   conflict component, its two version cards and the seam between them). What
   survives from it is the idiom, not the material: the hairline call-out —
   leader plus one mono phrase, nothing boxed — and the click-vs-clock rule,
   whichever is further along wins.

   The room is the picture the agent draws after it looks at the project:
   AREA IS WHERE THE WORK WENT, and what fills that area is the work itself.
   The project is Counter, an order-ahead coffee app, and the room's whole
   argument is one sentence long — one component carries the pickup promise,
   and two other surfaces copy its number by hand.

   Ink discipline is the design, and it is the only rule this file really has:
     · OUTLINE MEANS TENSION. Exactly one block is drawn — Pickup & promise.
       Everything settled drops to flat tone with no stroke at all, so the eye
       finds the argument before it finds the inventory.
     · TONE MEANS SETTLED. --bg-tertiary, no border, no shadow, no label chrome.
     · --accent APPEARS THREE TIMES in the drawing and means one thing, "this
       is the contested part": the block's hairline, the promise component
       inside it, and the word `hard-coded` on the surface that copies it.
       Nothing decorative takes it. --evidence is scene ①'s and never appears
       here. The agent's pin is the one thing outside the drawing that carries
       the accent — it is the agent's own voice, not a mark on the territory,
       and it is drawn as a bubble so it can never be mistaken for one.
     · SILENCE IS TYPE, NOT BOXES. Untouched areas were boxes in the earlier
       cut, which gave dead work the same visual weight as live work. One line
       of mono says it instead — and still tells GONE QUIET (it has a duration)
       from NEVER STARTED (it does not) by tone.

   Geometry is Frame C's, unchanged and non-negotiable: 736×414 window bled to
   left:-34 / bottom:-30, one 36px chrome row, body content starting at the
   62px that clears the crop, and only the first 348px of the body ever on
   paper. .aw-room is therefore given a HARD 314px height (20px body padding +
   314 = 334, fourteen clear of the crop) and the pin row is pushed to its
   bottom with margin-top:auto — so nothing important can ever drift below the
   fold, at any scale the fit governor produces.

   Beats arrive as classes on .fc.aw — ab1 the room's shape (blocks and tone),
   ab2 the material filling the outlined block, ab3 the line of silences, ab4
   the pin and its claim — so the fully-classed markup IS the no-JS frame. The
   five interactions (hover evidence · tap to note · the pin · weigh · next
   focus) are live in every frame that runs JS, choreographed or not. ═══ */

/* Caveat carries the agent's handwritten pin — self-hosted, latin subset
   (public/fonts/caveat.woff2), so the page stays free of external hosts and
   the CSP keeps `font-src 'self' data:` with no Google Fonts exception. The
   asset has been in the tree since db977f5b9 and went unreferenced when the
   first .aw-* world retired (af0a5bc2b); this is what claims it again. */
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/caveat.woff2') format('woff2');
}

/* ── the room ── */
.aw-body { padding: 20px 26px 0 62px; }
.aw-room {
  position: relative;
  height: 314px;              /* the on-paper budget, spent deliberately */
  display: flex; flex-direction: column; gap: 10px;
  --aw-w: 0%;                 /* where the weigh thumb sits */
  /* Counter's own palette — the SAMPLE PROJECT's, not §2's. Deliberately
     low-chroma warm neutral (espresso, crema, oat): the two thumbnails have to
     look like a real coffee app, because "you recognise the project rather
     than reading a legend" is the whole reason the block is filled with
     material. Kept desaturated on purpose so it can never be mistaken for
     --accent, which in this room means one thing and appears three times. */
  --counter-ink: #4A3B2E;
  --counter-mid: #8A7461;
  --counter-tint: #EFE7DC;
  --counter-line: rgba(74, 59, 46, 0.16);
  /* the agent's hand — the one face in §2 that is not the app's */
  --font-hand: 'Caveat', 'Bradley Hand', 'Segoe Script', ui-rounded, cursive;
  /* the two quantities the weigh control moves. Defaults ARE the recency
     drawing, so the no-JS room is the one the wireframe was drawn as. */
  --aw-fh: 64px;              /* Ordering flow's height */
  --aw-rg: 1;                 /* Receipts' share of the row beside Payments */
}

/* ── the header line, and the control that re-asks the question behind the
     drawing. The weigh control is hairline and sits in the header's own row,
     so asking the question costs the room no height. ── */
.aw-head { display: flex; align-items: center; gap: 16px; }
.aw-hline {
  font-family: var(--font-code); font-size: 9px; letter-spacing: 0.07em;
  line-height: 1.5; color: var(--text-muted);
}
.aw-weigh { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none; }
.aw-wlab {
  font-family: var(--font-code); font-size: 8px; letter-spacing: 0.08em;
  color: var(--text-muted); flex: none;
}
/* A real <input type="range"> carries the drag, the arrow keys and the
   accessible name; it is laid over the drawn control at zero opacity so the
   hairline the room actually shows is CSS we own, identical in every engine
   rather than whatever the platform draws for a slider. --aw-w is the only
   thing JS moves. The thumb is neutral at rest and takes the accent on hover,
   focus and drag only, where it means "act here" — the same contract
   .stage-replay has. */
.aw-wctl { position: relative; flex: none; width: 96px; height: 12px; display: flex; align-items: center; }
.aw-wtrack { display: block; position: relative; width: 100%; height: 2px; border-radius: 1px; background: rgba(29, 29, 31, 0.16); }
.aw-wthumb {
  position: absolute; top: -4px; left: var(--aw-w); margin-left: -5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--bg-elevated); border: 1px solid rgba(29, 29, 31, 0.42);
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.aw-wctl:hover .aw-wthumb, .aw-wctl:focus-within .aw-wthumb {
  background: var(--accent); border-color: var(--accent);
}
.aw-wctl:focus-within .aw-wtrack { background: rgba(196, 93, 53, 0.30); }
.aw-wrange {
  position: absolute; inset: -3px -6px; width: auto; height: auto;
  margin: 0; padding: 0; opacity: 0; cursor: ew-resize;
}

/* ── the territory ── */
.aw-main { display: flex; gap: 16px; align-items: flex-start; }

/* THE ONE DRAWN BLOCK. 384px is authored, not fitted: it is the width at which
   two 92px screen thumbnails, their gutter and a 158px call-out lane all fit
   without the leader ever reaching the window's right padding. */
.aw-block {
  width: 384px; flex: none;
  display: flex; flex-direction: column; gap: 9px;
  padding: 11px; border-radius: 11px;
  background: var(--bg-elevated);
  border: 1px solid var(--accent);
  transition: box-shadow 0.3s var(--ease), background 0.3s var(--ease);
}
.aw-bhead { display: flex; align-items: baseline; gap: 8px; height: 17px; }
.aw-bname { font-family: var(--font-ui); font-size: 13px; font-weight: 500; color: var(--text-primary); }
.aw-bmeta { font-family: var(--font-code); font-size: 9px; letter-spacing: 0.07em; color: var(--text-muted); }
/* the badge the room grows when a note becomes an objective */
.aw-obj {
  margin-left: auto; display: none; flex: none;
  padding: 2px 7px; border-radius: var(--radius-pill);
  font-family: var(--font-code); font-size: 8px; letter-spacing: 0.08em;
  color: var(--accent-hover); background: var(--accent-soft);
}

/* the material: the project's own screens and its real component, at true
   relative scale — you recognise the project instead of reading a legend */
.aw-mat { display: flex; gap: 10px; align-items: flex-start; }
/* the two thumbnails are Counter's real screens, drawn at true relative scale
   rather than sketched. At the sizes the fit governor produces, what carries
   recognition is composition and palette, not copy — so the screens are built
   from the app's own furniture (header, category chips, menu rows with product
   tiles, a filled order bar; on TRACK, a status line, the promise, a progress
   rail with its three stops) and the ONE thing meant to be read at this size is
   the promise component itself. */
.aw-screen {
  width: 92px; height: 124px; flex: none;
  display: flex; flex-direction: column; gap: 5px;
  padding: 7px; border-radius: 10px; overflow: hidden;
  background: var(--bg-elevated); border: 1px solid var(--counter-line);
}
/* the app's own header row, carrying the room's name for the screen — one row
   doing both jobs, because 110px of interior has no height to spend twice */
.aw-shead {
  display: flex; align-items: center; gap: 4px; flex: none;
  padding-bottom: 4px; border-bottom: 1px solid var(--counter-line);
}
.aw-sdot { flex: none; width: 5px; height: 5px; border-radius: 50%; background: var(--counter-ink); }
.aw-slab { font-family: var(--font-code); font-size: 7.5px; letter-spacing: 0.09em; color: var(--counter-mid); }
.aw-smenu { flex: none; margin-left: auto; width: 9px; height: 3px; border-radius: 2px; background: var(--counter-line); }

/* ORDER — category chips over two menu rows, and the order bar at the foot */
.aw-chips { display: flex; gap: 3px; flex: none; }
.aw-chips i { display: block; height: 6px; border-radius: 3px; background: var(--counter-tint); }
.aw-chips i:nth-child(1) { width: 21px; background: var(--counter-ink); }
.aw-chips i:nth-child(2) { width: 15px; }
.aw-chips i:nth-child(3) { width: 12px; }
.aw-item { display: flex; align-items: center; gap: 5px; flex: none; }
.aw-ithumb {
  flex: none; width: 22px; height: 22px; border-radius: 6px;
  background: var(--counter-tint); border: 1px solid var(--counter-line);
}
.aw-ilines { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.aw-ilines i { display: block; height: 4px; border-radius: 2px; background: rgba(74, 59, 46, 0.24); }
.aw-ilines i:nth-child(2) { width: 42%; background: rgba(74, 59, 46, 0.13); }
.aw-cta {
  margin-top: auto; flex: none; height: 14px; border-radius: 7px;
  background: var(--counter-ink);
  display: flex; align-items: center; justify-content: center;
}
.aw-cta i { display: block; width: 32px; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.55); }

/* TRACK — the status line, the promise, and the rail it is a promise about */
.aw-tstat { display: flex; align-items: center; gap: 4px; flex: none; }
.aw-tstat i:nth-child(1) { flex: none; width: 5px; height: 5px; border-radius: 50%; background: var(--counter-mid); }
.aw-tstat i:nth-child(2) { flex: 1; height: 4px; border-radius: 2px; background: rgba(74, 59, 46, 0.20); }
.aw-prog { position: relative; display: block; flex: none; height: 5px; }
.aw-prail { position: absolute; left: 0; top: 1px; width: 100%; height: 3px; border-radius: 2px; background: var(--counter-tint); }
.aw-pfill { position: absolute; left: 0; top: 1px; width: 56%; height: 3px; border-radius: 2px; background: var(--counter-ink); }
.aw-pstop {
  position: absolute; top: 0; width: 5px; height: 5px; border-radius: 50%;
  background: var(--bg-elevated); border: 1px solid var(--counter-mid);
}
.aw-pstop--1 { left: 0; background: var(--counter-ink); border-color: var(--counter-ink); }
.aw-pstop--2 { left: 54%; background: var(--counter-ink); border-color: var(--counter-ink); }
.aw-pstop--3 { right: 0; }
.aw-item--sm { margin-top: auto; }
.aw-item--sm .aw-ithumb { width: 16px; height: 16px; border-radius: 5px; }

/* the promise component, lit inside TRACK — accent #2, and the one element in
   either screen that is meant to be legible at the room's scale */
.aw-comp {
  display: block; flex: none; padding: 5px; border-radius: 6px;
  border: 1px solid var(--accent); background: var(--accent-soft);
  font-family: var(--font-ui); font-size: 11px; font-weight: 600;
  color: var(--text-primary); text-align: left;
}
/* the call-out: leader plus label, nothing boxed. 34px of padding lands it on
   the component it names rather than on the top of the thumbnail. */
.aw-call {
  flex: 1; min-width: 0; margin: 0; padding-top: 34px;
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.06em;
  line-height: 1.5; color: var(--text-muted); pointer-events: none;
}
.aw-call::before {
  content: ''; flex: none; display: block;
  width: 20px; height: 1px; background: rgba(29, 29, 31, 0.22);
}

/* the settled areas: flat tone, no outline. Their height and their share of
   the row are what the weigh control moves — the block never budges, so the
   argument stays exactly where the eye left it. */
.aw-tone { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.aw-area {
  border-radius: 10px; background: var(--bg-tertiary); padding: 9px 11px;
  display: flex; flex-direction: column; gap: 3px; overflow: hidden;
  transition: height 0.18s linear, flex-grow 0.18s linear, opacity 0.3s var(--ease);
}
.aw-aname { font-family: var(--font-ui); font-size: 11.5px; font-weight: 500; color: var(--text-primary); }
.aw-ameta { font-family: var(--font-code); font-size: 9px; letter-spacing: 0.06em; color: var(--text-muted); }
/* accent #3, and the last one: the surface that copies the promise by hand */
.aw-ameta--hot { color: var(--accent); }
.aw-area--flow { height: var(--aw-fh); }
.aw-area--flow .aw-aname { font-size: 12px; }
.aw-arow { display: flex; gap: 8px; height: calc(120px - var(--aw-fh)); }
.aw-area--pay { flex: 1 1 0; min-width: 0; height: 100%; }
.aw-area--rec { flex: var(--aw-rg) 1 0; min-width: 0; height: 100%; }

/* ── the silences, as one line of type — the room's floor.
     It moved BELOW the pin in the hand-written pass: the pin now points at the
     block with a drawn arrow, and the arrow needs clear paper between the two.
     The pin is still the last thing that argues; this line is inventory. ── */
.aw-quiet {
  margin: auto 0 0; padding-top: 8px; border-top: 1px solid rgba(29, 29, 31, 0.14);
  font-family: var(--font-code); font-size: 9px; letter-spacing: 0.07em; line-height: 1.5;
}
/* gone quiet carries a duration and therefore weight; never started does not.
   The drop is one step of tone — both halves stay at or above the section's
   muted floor — and the rest of the distinction is carried on letterform, not
   luminance: the durations are underscored, the never-started phrase is not. */
.aw-qlab { color: var(--text-muted); }
.aw-qgone { color: var(--text-secondary); border-bottom: 1px dotted rgba(29, 29, 31, 0.22); }
.aw-qnever { color: var(--text-muted); }

/* ── the agent's pin — marginalia, not a component.
     Everything that made it look like a UI object is gone: no fill, no border,
     no radius, no pill row. What is left is what a person would actually leave
     on a drawing — a numbered pin head, one line of handwriting, and an arrow
     drawn at the thing it is about. The claim runs 440px, two thirds of the
     room, so it reads as a note ON the picture rather than a bar UNDER it. ── */
.aw-pinrow { position: relative; margin-top: 12px; display: flex; gap: 14px; align-items: flex-start; }
.aw-pin {
  position: relative; flex: none; width: 462px; padding-left: 22px;
  display: flex; flex-direction: column; gap: 2px;
  transition: opacity 0.35s var(--ease);
}
/* the arrow: hand-drawn, crossing up off the note into the block's bottom edge
   under TRACK — ink laid over the drawing, which is exactly what an annotation
   is. Accent, at the same 0.55 the margin card's delta brace uses, so it stays
   a hand mark and never reads as a control. */
.aw-plead { position: absolute; left: 38px; top: -32px; width: 124px; height: 42px; pointer-events: none; overflow: visible; }
.aw-pl-line, .aw-pl-head {
  fill: none; stroke: var(--accent); stroke-width: 1.2;
  stroke-linecap: round; stroke-linejoin: round; opacity: 0.55;
}
/* the pin head sits INSIDE the 62px that clears the crop, in a 22px gutter the
   note reserves for it — nothing in the room may hang into the cut edge */
.aw-pnum {
  position: absolute; top: 1px; left: 0;
  width: 15px; height: 15px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #FFFFFF;
  font-family: var(--font-code); font-size: 9px; line-height: 1;
}
.aw-pclaim {
  margin: 0; font-family: var(--font-hand); font-size: 16px; font-weight: 500;
  line-height: 1.3; color: var(--text-primary); text-wrap: pretty;
}
/* one fixed-height slot holds the pin's three states in turn — actions, the
   reply line, the thread it becomes — so answering the agent can never grow
   the bubble past the crop */
.aw-pfoot { position: relative; height: 18px; }
.aw-pacts, .aw-preply, .aw-pthread {
  position: absolute; inset: 0; display: none; align-items: center; gap: 12px; margin: 0;
}
.aw-pin[data-pf="rest"] .aw-pacts { display: flex; opacity: 0; transition: opacity 0.18s var(--ease); }
.aw-pin[data-pf="rest"]:hover .aw-pacts,
.aw-pin[data-pf="rest"]:focus-within .aw-pacts { opacity: 1; }
.aw-pin[data-pf="reply"] .aw-preply { display: flex; }
.aw-pin[data-pf="thread"] .aw-pthread { display: flex; }
.aw-plab { flex: none; font-family: var(--font-code); font-size: 8px; letter-spacing: 0.08em; color: var(--text-muted); }
.aw-pinput {
  flex: 1; min-width: 0; outline: none;
  font-family: var(--font-hand); font-size: 15px; line-height: 18px; color: var(--text-primary);
  border-bottom: 1px dashed rgba(29, 29, 31, 0.28);
  white-space: nowrap; overflow: hidden;
}
.aw-pinput:empty::before { content: attr(data-ph); color: var(--text-muted); }
.aw-pthread {
  font-family: var(--font-hand); font-size: 14px; letter-spacing: 0;
  color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aw-pthread b { font-weight: 500; color: var(--accent-hover); }

/* the pin's own three answers are marginalia too — quiet text links, not
   pills. `write a note` stays a pill: that one is the room's control. */
.aw-plink {
  flex: none; padding: 0; background: none; border: none; cursor: pointer;
  font-family: var(--font-ui); font-size: 10px; line-height: 1.4; white-space: nowrap;
  color: var(--accent); border-bottom: 1px solid rgba(196, 93, 53, 0.30);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.aw-plink:hover { color: var(--accent-hover); border-bottom-color: var(--accent-hover); }

/* ── the shared pill affordance ── */
.aw-btn {
  flex: none; padding: 3px 9px; border-radius: var(--radius-pill); white-space: nowrap;
  font-family: var(--font-ui); font-size: 10px; line-height: 1.4; cursor: pointer;
  color: var(--text-secondary); background: var(--bg-elevated);
  border: 1px solid rgba(29, 29, 31, 0.18);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.aw-btn:hover { color: var(--accent); border-color: rgba(196, 93, 53, 0.45); }
.aw-btn--p { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.aw-btn--p:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #FFFFFF; }
.aw-write { margin-top: 1px; }

/* ── every mark can be opened: the parts ── */
.aw-part { position: relative; cursor: pointer; }
.aw-part:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* a stored note leaves its mark on the element it was written on */
.aw-part.has-note::after {
  content: ''; position: absolute; top: -3px; right: -3px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--bg-elevated);
}

/* ── hover evidence: a small dark tip, anchored to the part it is about and
     clamped inside the room, so it never reaches the mat's protected air ── */
.aw-tip {
  position: absolute; z-index: 6; max-width: 236px; pointer-events: none;
  padding: 7px 9px; border-radius: 8px;
  background: #1E1D1A; color: #EDEBE7;
  font-family: var(--font-code); font-size: 8.5px; line-height: 1.6; letter-spacing: 0.03em;
  box-shadow: 0 8px 20px rgba(29, 29, 31, 0.22);
  opacity: 0; transition: opacity 0.16s var(--ease);
}
.aw-tip.is-on { opacity: 1; }
.aw-tip b { display: block; font-weight: 400; color: #FFFFFF; letter-spacing: 0.06em; }
.aw-tip i { font-style: normal; color: rgba(255, 255, 255, 0.52); }

/* ── the note field: it opens ON the part, never in a panel beside it ── */
.aw-note {
  position: absolute; z-index: 7; width: 238px;
  padding: 9px 10px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px solid rgba(29, 29, 31, 0.16);
  box-shadow: 0 10px 26px rgba(29, 29, 31, 0.14);
}
.aw-nhead {
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.07em;
  color: var(--text-muted); margin-bottom: 5px;
}
/* the note field's own writable line is the same hand */
.aw-nline {
  font-family: var(--font-hand); font-size: 15px; line-height: 1.3;
  color: var(--text-primary); outline: none;
  border-bottom: 1px dashed rgba(29, 29, 31, 0.30);
  padding-bottom: 5px; margin-bottom: 8px; min-height: 20px;
}
.aw-nline:empty::before { content: attr(data-ph); color: var(--text-muted); }
.aw-nacts { display: flex; flex-wrap: wrap; gap: 6px; }

/* ── show me why: the three accented marks, and nothing else ── */
.aw.is-why .aw-head,
.aw.is-why .aw-quiet,
.aw.is-why .aw-area--flow,
.aw.is-why .aw-area--pay,
.aw.is-why .aw-screen--order { opacity: 0.28; }
.aw.is-why .aw-block { box-shadow: 0 0 0 3px var(--accent-soft); }
.aw.is-why .aw-comp { box-shadow: 0 0 0 3px var(--accent-soft-2); }
.aw.is-why .aw-area--rec { background: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ── next focus: the room settles into "this became an objective". The only
     gesture out, and it is the visitor's — the agent never takes it. ── */
.aw.is-focus .aw-block { background: var(--accent-soft); }
.aw.is-focus .aw-obj { display: block; }
.aw.is-focus .aw-tone { opacity: 0.45; }
.aw.is-focus .aw-write { display: none; }
.aw.is-dismissed .aw-pin { opacity: 0; pointer-events: none; }

/* ── the choreographed beats. Everything below is a fade or a 8px rise on an
     element whose box never changes size, so the room's geometry is identical
     in the first frame and the last — the outlined block cannot jump. ── */
.aw-head, .aw-block, .aw-tone {
  opacity: 0; transform: translateY(8px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.aw.ab1 .aw-head, .aw.ab1 .aw-block, .aw.ab1 .aw-tone { opacity: 1; transform: none; }
.aw-mat, .aw-bmeta { opacity: 0; transition: opacity 0.45s var(--ease-out); }
.aw.ab2 .aw-mat, .aw.ab2 .aw-bmeta { opacity: 1; }
.aw-quiet { opacity: 0; transition: opacity 0.45s var(--ease-out); }
.aw.ab3 .aw-quiet { opacity: 1; }
.aw-pinrow {
  opacity: 0; transform: translateY(6px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.aw.ab4 .aw-pinrow { opacity: 1; transform: none; }
/* the arrow draws itself in after the note it belongs to */
.aw-pl-line, .aw-pl-head { stroke-dasharray: 140; stroke-dashoffset: 140; }
.aw.ab4 .aw-pl-line { stroke-dashoffset: 0; transition: stroke-dashoffset 0.7s var(--ease-out) 0.25s; }
.aw.ab4 .aw-pl-head { stroke-dashoffset: 0; transition: stroke-dashoffset 0.3s var(--ease-out) 0.85s; }
.aw.is-dismissed .aw-plead { opacity: 0; transition: opacity 0.35s var(--ease); }
/* is-focus dims the tone column; the beat rule above must not win it back */
.aw.is-focus.ab1 .aw-tone { opacity: 0.45; }

/* ═══ SCENE ③ · THE BUILD — nothing runs until you do (v12) ═══
   The scene that already had window chrome is now inside the *shared* one, at
   the same Frame C crop as ① — by the third scene the frame is a rhythm: one
   app, three things. The Execution Engine moved with it: it is docked INSIDE
   this window, in its own column against a hairline, rather than floating
   beside the document in separate chrome as it did through v11. It is always
   present — "Ready · 0 of 4" before the run, "Executing · 2 of 4" during it —
   because a panel that appears only once something starts is a picture of
   execution, not a part of the app.

   Fidelity-correct against the app (widgets/capabilityList.ts,
   capabilityArmedState.ts, renderer/executionPanel/): the capability card is
   serif, like the document it lives in; rows carry an 18px status button that
   fills with the accent when complete; the footer EXISTS only once the model
   arms the request, and Build stays dead until the writer has checked every
   box. Dot colours are the panel's own — green complete, pulsing orange in
   progress, quiet --ai-dot pending — and only the current row carries an
   activity word.

   State classes on .bd, set by editor-scenes.js and baked into the markup for
   the no-JS frame: tail-in · caps-in · is-armed · all-done · is-building. ═══ */

@keyframes bd-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.45; transform: scale(0.82); } }

.bd-body { display: flex; }

/* ── the document column ── */
.bd-doc { width: 404px; flex: none; padding: 18px 20px 0 62px; display: flex; flex-direction: column; }

/* the document's own prose tail — the sentence the four rows came out of.
   The four .bd-seed phrases are the four capabilities before they were rows;
   the accent marks them at its quietest weight so a reader can point at the
   words behind each checkbox without the page underlining its own homework. */
.bd-tail {
  margin: 0 0 9px; font-family: var(--font-body); font-size: 12.5px; line-height: 1.6;
  color: var(--text-secondary); text-wrap: pretty;
  opacity: 0; transform: translateY(7px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.bd.tail-in .bd-tail { opacity: 1; transform: none; }
.bd-seed { color: var(--text-primary); box-shadow: inset 0 -1px 0 0 var(--accent-soft-2); }

/* ── the capabilities card, in the document ──
   It arrives after the tail has settled: the translation from prose to plan is
   the scene's whole claim, and it only reads as a translation if the prose is
   visibly there first. */
.bd-caps {
  border: 1px solid rgba(29, 29, 31, 0.10); border-radius: var(--radius-lg);
  background: var(--bg-primary); padding: 10px 12px;
  box-shadow: 0 2px 8px rgba(29, 29, 31, 0.04);
  opacity: 0; transform: translateY(9px);
  transition: opacity 0.52s var(--ease-out), transform 0.52s var(--ease-out);
}
.bd.caps-in .bd-caps { opacity: 1; transform: none; }
.bd-caps-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 9px; }
.bd-caps-title { font-family: var(--font-body); font-size: 13px; color: var(--text-primary); }
/* the app shows a bare total here; the fraction is an onboarding flourish —
   it is the count the reader is being asked to close */
.bd-count {
  margin-left: auto; font-family: var(--font-code); font-size: 9px; letter-spacing: 0.06em;
  color: var(--text-muted); transition: color 0.2s var(--ease);
}
.bd.all-done .bd-count { color: var(--accent-hover); }

.bd-rows { display: flex; flex-direction: column; gap: 6px; }
.bd-cap { position: relative; display: flex; align-items: flex-start; gap: 9px; }
.bd-check {
  flex: none; width: 16px; height: 16px; margin-top: 1px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-ui); font-size: 9px; line-height: 1; cursor: pointer;
  background: transparent; border: 1.5px solid rgba(29, 29, 31, 0.22); color: transparent;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.bd-check.is-done { background: var(--accent); border-color: var(--accent); color: #FFFFFF; }
.bd-name {
  flex: 1; min-width: 0; font-family: var(--font-body); font-size: 12.5px; line-height: 1.45;
  color: var(--text-secondary); outline: none; transition: color 0.2s var(--ease);
}
.bd-name.is-done { color: var(--text-primary); }
/* reorder / remove reveal on hover, as they do in the app — and they OVERLAY
   the row's right edge rather than reserving a lane in it. Reserved, the three
   16px buttons take 50px off a 273px name column and every capability wraps to
   two lines, which is 72px the document column does not have: the card would
   run past the crop and take the Build gate with it. */
.bd-rowctl {
  position: absolute; right: 0; top: 0; z-index: 1;
  display: flex; gap: 1px; padding-left: 6px; background: var(--bg-primary);
  opacity: 0; transition: opacity 0.1s var(--ease);
}
.bd-cap:hover .bd-rowctl, .bd-cap:focus-within .bd-rowctl { opacity: 1; }
.bd-rowctl button {
  width: 16px; height: 16px; padding: 0; border: none; background: none;
  color: var(--text-muted); font-size: 10px; cursor: pointer;
}
.bd-rowctl button:hover { color: var(--accent); }

.bd-addcap {
  margin-top: 9px; padding: 0; background: none; border: none; cursor: pointer;
  font-family: var(--font-ui); font-size: 11px; color: var(--text-muted);
  transition: color 0.1s var(--ease);
}
.bd-addcap:hover { color: var(--accent); }

/* ── the gate: it exists only once the agent arms the request ── */
.bd-gate { overflow: hidden; max-height: 0; opacity: 0; transition: max-height 0.3s var(--ease), opacity 0.3s var(--ease); }
.bd.is-armed .bd-gate { max-height: 90px; opacity: 1; }
.bd-gate-inner {
  margin-top: 10px; padding-top: 9px; border-top: 1px solid rgba(29, 29, 31, 0.08);
  display: flex; align-items: center; gap: 10px;
}
.bd-armed-line {
  font-family: var(--font-code); font-size: 9px; letter-spacing: 0.05em;
  color: var(--ai-label-color);
}
.bd-build {
  margin-left: auto; padding: 6px 15px; border-radius: var(--radius-md);
  font-family: var(--font-ui); font-size: 11.5px; cursor: pointer;
  background: var(--accent); border: 1px solid var(--accent); color: #FFFFFF;
  transition: background 0.2s linear, border-color 0.2s linear, color 0.2s linear;
}
.bd-build:disabled {
  background: rgba(29, 29, 31, 0.04); border-color: rgba(29, 29, 31, 0.10);
  color: #C9C9CC; cursor: not-allowed;
}

/* ── the Execution Engine, docked inside the same window ── */
.bd-ep {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  padding: 20px 24px 0 20px;
  border-left: 1px solid rgba(29, 29, 31, 0.07); background: #FCFCFA;
}
.bd-ep-title {
  font-family: var(--font-ui); font-size: 11.5px; font-weight: 500; letter-spacing: 0.01em;
  color: var(--text-primary); margin-bottom: 4px;
}
/* the panel's exact state vocabulary — "Ready · N of M", "Executing · N of M" */
.bd-ep-state {
  font-family: var(--font-code); font-size: 9.5px; letter-spacing: 0.07em;
  color: var(--text-muted); margin-bottom: 18px; transition: color 0.3s var(--ease);
}
.bd.is-building .bd-ep-state { color: var(--accent-hover); }

.bd-ep-group {
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.09em;
  color: #C9C9CC; margin: 16px 0 8px;
}
.bd-ep-group:first-child { margin-top: 0; }
.bd-ep-row { display: flex; align-items: flex-start; gap: 8px; }
.bd-ep-row + .bd-ep-row { margin-top: 8px; }
.bd-ep-rdot { flex: none; width: 6px; height: 6px; border-radius: 50%; margin-top: 5px; background: rgba(196, 93, 53, 0.28); }
.bd-ep-rname { display: block; font-family: var(--font-ui); font-size: 11px; line-height: 1.45; color: var(--text-muted); }
.bd-ep-rbody { min-width: 0; }
/* orange means "actively building"; gold belongs to artifact work in the
   margin system and never to this panel */
.bd-ep-row.r-done .bd-ep-rdot { background: #5A9E6F; }
.bd-ep-row.r-done .bd-ep-rname { color: var(--text-secondary); }
.bd-ep-row.r-now .bd-ep-rdot { background: var(--accent); animation: bd-pulse 1.6s var(--ease) infinite; }
.bd-ep-row.r-now .bd-ep-rname { color: var(--text-primary); }
.bd-ep-row.r-idle .bd-ep-rdot { background: rgba(196, 93, 53, 0.22); }
.bd-ep-row.r-idle + .bd-ep-row.r-idle { margin-top: 9px; }
/* only the current row carries an activity word */
.bd-ep-word {
  display: block; margin-top: 3px;
  font-family: var(--font-code); font-size: 8.5px; letter-spacing: 0.07em;
  color: var(--accent-hover);
}

/* ═══ MOTION LAYER (v11) — sections sit in plain scroll flow; each element
   gets ONE gentle rise, played once. Under the choreographed gate each scene
   also plays its own beat timeline — the margin's anchor → card → thread, the
   awareness room's shape → material → silences → pin, and the build's tail →
   check → Build → docked engine — on a clock, once, when it reaches the
   viewport. The scenes' settled states are baked into the markup; the driver
   strips them on boot, so outside this gate (narrow viewports, reduced motion,
   no JS) the page renders the finished frames and nothing moves.

   The three scenes used to be 360–380vh tall and pinned, because scroll
   position WAS the clock: `#s2/#s1/#s3 { height: 360vh }` plus a sticky
   `.scene-pin` gave the scrub its room. Timed autoplay (2026-08-05) needs
   none of it — the scenes are normal height and the page is ~9 viewports
   shorter for it. ═══ */
@media (min-width: 901px) and (min-height: 820px) and (prefers-reduced-motion: no-preference) {
  .beat-copy, .stage-cam { opacity: 0; transform: translateY(18px); }
  .beat-copy[data-played], .stage-cam[data-played] {
    opacity: 1; transform: none;
    transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out);
  }
  .stage-cam[data-played] { transition-delay: 0.14s; }

  /* neighbouring scenes are separated by exactly one --scene-gap — each
     contributes half of it, which is the shared-gap contract the token was
     declared for (editor-tokens.css). Unpinned, the authored full gap on both
     edges would double at every boundary. */
  .pin-grid { padding: calc(var(--scene-gap) / 2) 0; }
}

/* ── responsive: below 901px the base static document simply flows ── */
@media (max-width: 900px) {
  .pin-grid { display: block; }
  .beat-copy { max-width: 560px; margin-bottom: 20px; padding-top: 0; }
  .stage { min-height: 0; padding: 24px 16px 20px; }
}

/* ── reduced motion: every moving thing renders at its final frame (the
     markup's baked settled state); the ambient loops stop.
     The named loop is the Execution Engine's live-row pulse — the only
     animation left in the section. Scene ② has never had one: the room it
     draws now (editor-scene-awareness.css, v13) is fades and one 8px rise,
     and the conflict component it replaced (editor-scene-artifact.css,
     retired with it) was transitions only. ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
  }
  .bd-ep-row.r-now .bd-ep-rdot { animation: none; }
}

/* ═══ Post-merge fixes ═══════════════════════════════════════════════════
   Loaded LAST. Everything else under src/styles/ is a byte-faithful slice of
   the merged design file; this is the one place that deliberately departs from
   it, so the departure stays enumerable — build.mjs lists it in NON_SLICES,
   and `--baseline` omits it so a design-faithful build stays producible. (The
   staging-era provenance gate that enforced this retired with the staging
   tree in b47fe941a.)

   Fixes here are defects the MERGE created — where a rule from one source page
   landed on markup from the other. They are not redesigns. Anything that
   changes the design belongs in the source artifacts, not here.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── ① The pinned scenes never pinned. ──────────────────────────────────
   `.section { overflow: hidden }` (section-scaffold.css, from the hero page —
   "nature lives at the edges; it never spills between sections") is written
   for the standalone hero's decorative edge art. The merge wrapped the whole
   editor in <section class="section" id="capabilities">, and an ancestor with
   `overflow: hidden` becomes the scroll container for any `position: sticky`
   descendant. So `#s2 .scene-pin` and `#s1 .scene-pin` were sticking to a box
   that scrolls away with the page — i.e. not sticking at all.

   Measured at 1840×1076 before this rule: the two pins scrolled 1:1 with the
   page, 8,000px of a 14,086px document rendered blank, and scene 01's
   a → b → c → all card swap fired between y=2600 and y=4600 — entirely inside
   the blank stretch, so only card A was ever visible. After: 600px blank (the
   hero, which has no pin), and every step is on screen while it is current.

   Scoped to #capabilities rather than removing the rule, because `.section` is
   the hero page's vocabulary and more of it may come back when the orphan
   styles are cleaned up. Horizontal spill stays contained: base.css already
   sets `overflow-x: clip` on html and body, and `clip` does not create a
   scroll container, so it cannot break sticky the way `hidden` does.

   2026-08-05: the sticky this unblocked is gone — timed autoplay replaced the
   scroll-scrub and the pins came out of editor-motion.css with it. The rule
   stays because `overflow: hidden` would still clip the section, and because
   restoring the hero's default here is a render change, not a fix. */
#capabilities { overflow: visible; }