/* ============================================================ */
/* agent-video-editor — public landing (`/`) stylesheet          */
/* ============================================================ */
/* Standalone: landing.html does NOT load viewer.css (that file  */
/* carries the /ui chrome header styles, meaningless to an        */
/* anonymous visitor). The design-token :root block below is      */
/* DUPLICATED from viewer.css on purpose — same values, kept in   */
/* sync BY HAND. viewer.css is itself mirrored from               */
/* frontend/src/styles/tokens.css, which is the ultimate source   */
/* of truth; if a token changes there, update viewer.css AND this */
/* file. Landing-only additions (type scale, motion tokens) are   */
/* namespaced with clear comments and live nowhere else.          */
/* ============================================================ */

:root {
  color-scheme: dark;

  /* --- Design tokens: mirror of viewer.css :root (keep in sync) --- */
  --bg-app: #0d0f13;
  --bg-panel: #14171c;
  --bg-elevated: #1b1f26;
  --border: #262b33;
  --fg: #e6e8eb;
  --fg-muted: #8b93a1;
  --fg-faint: #5c6470;
  /* AA-safe stand-in for --fg-faint: #5c6470 is only 3.0-3.2:1 on our dark
     backgrounds (fails WCAG AA's 4.5:1 for normal text). --fg-faint itself is
     kept unchanged (mirrors viewer.css, see file header), so real text that
     was using it (eyebrows, step numbers, footer tagline, timeline labels)
     is repointed at this landing-only token instead; ~4.8-5.5:1 on all three
     surface tones. Purely decorative uses (the auth-mark border) keep
     --fg-faint. */
  --lp-faint-text: #838a97;
  --accent: #4f8ff7;
  --accent-fg: #ffffff;
  --danger: #e5484d;
  --warn: #f0a13b;
  --ok: #46a758;
  /* element-kind colors (fill + border), same semantics as the real timeline */
  --el-clip: #2f5db3;
  --el-clip-border: #4f8ff7;
  --el-text: #8a6d1f;
  --el-text-border: #d4a72c;
  --el-audio: #1f7a55;
  --el-audio-border: #34d399;
  --el-overlay: #6b4fa0;
  --el-overlay-border: #a78bfa;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs-md: 13px;
  --radius: 6px;
  --radius-sm: 4px;
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;

  /* --- Landing-only type scale (design-brief §3) --- */
  --fs-display: clamp(2.4rem, 5vw, 3.75rem);
  --fs-h2: clamp(1.6rem, 3vw, 2.25rem);
  --fs-h3: 1.125rem;
  --fs-lead: clamp(1.05rem, 1.6vw, 1.25rem);
  --fs-body: 0.95rem;
  --fs-mono-label: 0.75rem;

  /* --- Motion tokens (motion-spec §1) --- */
  --dur-instant: 0.08s;
  --dur-fast: 0.18s;
  --dur-normal: 0.35s;
  --dur-slow: 0.6s;
  --dur-crawl: 1s;
  --ease-smooth: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-sharp: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-linear: linear;
  --dist-xs: 4px;
  --dist-sm: 8px;
  --dist-md: 16px;
  --dist-lg: 24px;
  --dist-xl: 48px;
  --scale-subtle: 0.98;
  --scale-press: 0.95;
  --scale-pop: 1.04;

  /* landing layout */
  --lp-maxw: 1080px;
  --lp-gutter: clamp(1rem, 4vw, 2.5rem);
  --lp-rail: 40px; /* left gutter reserved for the playhead rail on desktop */
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: 1.55;
  background: var(--bg-app);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

.lp-mono { font-family: var(--font-mono); }

/* Visually-hidden but screen-reader available (the hero timeline alt text). */
.lp-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================ */
/* Buttons + links (micro-interactions, motion-spec §4)          */
/* ============================================================ */
.lp-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.6rem 1.1rem;
  border-radius: var(--radius);
  font-size: var(--fs-body);
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-sharp),
    background-color var(--dur-fast) var(--ease-sharp),
    border-color var(--dur-fast) var(--ease-sharp),
    box-shadow var(--dur-fast) var(--ease-sharp);
}
.lp-btn:hover { transform: translateY(-1px); }
.lp-btn:active {
  transform: translateY(0) scale(var(--scale-press));
  transition-duration: var(--dur-instant);
}
.lp-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(79, 143, 247, 0.2);
}

.lp-btn--solid {
  /* --accent (#4f8ff7) under --accent-fg white text is only 3.18:1 — fails
     WCAG AA's 4.5:1 for normal text. --el-clip is the same blue family
     (already in the palette, used for the CLIP track) at a shade dark
     enough to clear 6.29:1 with white, so the button borrows it instead of
     a bespoke color. --accent stays on the border/hover glow for the brand
     tint, since those aren't held to the text-contrast ratio. */
  background: var(--el-clip);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.lp-btn--solid:hover { box-shadow: 0 4px 16px rgba(79, 143, 247, 0.25); }

.lp-btn--ghost {
  background: transparent;
  color: var(--fg);
  border-color: var(--border);
}
.lp-btn--ghost:hover { border-color: rgba(79, 143, 247, 0.5); }

/* Tertiary mono text link with an animated underline. */
.lp-link {
  position: relative;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  color: var(--accent);
}
.lp-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-sharp);
}
.lp-link:hover::after,
.lp-link:focus-visible::after { transform: scaleX(1); }

/* ============================================================ */
/* Header (sticky, minimal)                                      */
/* ============================================================ */
.lp-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: 0.7rem var(--lp-gutter);
  background: rgba(20, 23, 28, 0.9);
  border-bottom: 1px solid var(--border);
  backdrop-filter: blur(8px);
}
.lp-header__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--fg-muted);
}
.lp-header__nav {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.lp-header__nav a.lp-nav-link {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--fg-muted);
  transition: color var(--dur-fast) var(--ease-sharp);
}
.lp-header__nav a.lp-nav-link:hover { color: var(--fg); }

/* Explicit focus ring for the plain-text nav/brand links (matches the
   box-shadow treatment already used on .lp-btn/.lp-copy/.lp-link, instead of
   relying solely on the browser's default outline). */
.lp-header__brand:focus-visible,
.lp-header__nav a.lp-nav-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(79, 143, 247, 0.35);
  border-radius: var(--radius-sm);
}

/* The auth-mark: a mono frame with an accent playhead notch. */
.lp-mark {
  display: inline-block;
  width: 18px;
  height: 14px;
  border: 1px solid var(--fg-faint);
  border-radius: 2px;
  position: relative;
  flex: none;
}
.lp-mark::before {
  content: "";
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: 50%;
  width: 2px;
  background: var(--accent);
  transform: translateX(-50%);
}

/* ============================================================ */
/* Page shell + the vertical playhead rail                       */
/* ============================================================ */
.lp-main {
  max-width: var(--lp-maxw);
  margin: 0 auto;
  padding: 0 var(--lp-gutter);
  position: relative;
}

/* The rail: a thin vertical line pinned to the left gutter with an accent
   playhead triangle that inline JS advances down the page on scroll. Purely
   decorative — collapses on mobile. */
.lp-rail {
  position: fixed;
  top: 0;
  bottom: 0;
  left: max(calc((100vw - var(--lp-maxw)) / 2 - var(--sp-3)), var(--sp-2));
  width: 2px;
  background: var(--border);
  z-index: 5;
  pointer-events: none;
}
.lp-rail__head {
  position: absolute;
  top: 0;
  left: -4px;
  width: 0;
  height: 0;
  border-left: 5px solid var(--accent);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  /* JS sets --lp-progress (0..1); translate keeps it compositor-only. */
  transform: translateY(calc(var(--lp-progress, 0) * (100vh - 8px)));
  transition: transform var(--dur-fast) var(--ease-linear);
  will-change: transform;
}

/* ============================================================ */
/* Sections + eyebrow labels                                     */
/* ============================================================ */
.lp-section {
  padding: clamp(3rem, 8vw, 5.5rem) 0;
  border-top: 1px solid var(--border);
}
.lp-section:first-of-type { border-top: none; }

.lp-eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--lp-faint-text);
  margin-bottom: var(--sp-3);
}

.lp-section__title {
  font-size: var(--fs-h2);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-3);
}
.lp-section__lead {
  color: var(--fg-muted);
  max-width: 62ch;
  margin: 0 0 var(--sp-4);
}

/* The 4-color brand strip (reused atop the hero card and the CTA band). */
.lp-strip {
  display: flex;
  height: 4px;
  border-radius: 2px;
  overflow: hidden;
}
.lp-strip > span { flex: 1; }
.lp-strip > span:nth-child(1) { background: var(--el-clip-border); }
.lp-strip > span:nth-child(2) { background: var(--el-text-border); }
.lp-strip > span:nth-child(3) { background: var(--el-audio-border); }
.lp-strip > span:nth-child(4) { background: var(--el-overlay-border); }

/* ============================================================ */
/* Hero                                                          */
/* ============================================================ */
.lp-hero {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  padding-top: clamp(2.5rem, 7vw, 4.5rem);
}
/* A grid item defaults to `min-width: auto`, i.e. it refuses to shrink below
   its min-content width. .lp-prompt is one nowrap mono line whose min-content
   is ~378px, so on a 390px phone the column grew past the gutter and pushed
   the whole page into a horizontal scroll. `min-width: 0` lets the column
   take the track's width and hands the overflow to .lp-prompt's own
   `overflow-x: auto`, where it belongs. */
.lp-hero__copy,
.lp-hero__stage { min-width: 0; }
.lp-hero__title {
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin: var(--sp-2) 0 var(--sp-4);
}
.lp-hero__sub {
  font-size: var(--fs-lead);
  color: var(--fg-muted);
  max-width: 54ch;
  margin: 0 0 var(--sp-4);
}
.lp-hero__sub code {
  font-family: var(--font-mono);
  color: var(--fg);
  font-size: 0.9em;
}
.lp-cta-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.lp-prompt {
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  color: var(--fg-muted);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 0.75rem;
  overflow-x: auto;
  white-space: nowrap;
}
.lp-prompt .lp-prompt__sigil { color: var(--accent); }

/* --- The self-playing hero timeline (design-brief §5, motion-spec §2) --- */
.lp-hero__stage {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.lp-stage__chrome {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--fg-muted);
}
.lp-stage__badge { color: var(--ok); }
.lp-stage__tag {
  margin-left: auto;
  color: var(--lp-faint-text);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
}

.hero-timeline {
  position: relative;
  container-type: inline-size;
  padding: var(--sp-3);
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: var(--sp-2) var(--sp-2);
  overflow: hidden;
}
.hero-timeline__label {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--lp-faint-text);
  align-self: center;
}
.hero-timeline__track {
  position: relative;
  height: 30px;
  border-radius: var(--radius-sm);
  background: rgba(230, 232, 235, 0.04);
}
.hero-timeline__clip {
  position: absolute;
  inset-block: 4px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  transform-origin: left center;
  opacity: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  padding: 0 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  color: rgba(13, 15, 19, 0.85);
  white-space: nowrap;
  will-change: transform, opacity;
  animation: lp-clip-enter var(--dur-slow) var(--ease-smooth) both;
  animation-delay: calc(var(--i, 0) * 0.5s + 0.3s);
  transition: transform var(--dur-fast) var(--ease-sharp);
}
.hero-timeline__clip:hover { transform: translateY(-1px); }

.hero-timeline__track--clip .hero-timeline__clip {
  background: var(--el-clip-border);
  border-color: var(--el-clip-border);
}
.hero-timeline__track--text .hero-timeline__clip {
  background: var(--el-text-border);
  border-color: var(--el-text-border);
}
.hero-timeline__track--audio .hero-timeline__clip {
  background: var(--el-audio-border);
  border-color: var(--el-audio-border);
}
.hero-timeline__track--overlay .hero-timeline__clip {
  background: var(--el-overlay-border);
  border-color: var(--el-overlay-border);
}

@keyframes lp-clip-enter {
  from { opacity: 0; transform: scaleX(var(--scale-subtle)); }
  to { opacity: 0.9; transform: scaleX(1); }
}

/* Playhead: full-width invisible wrapper, a 2px line as ::before swept with a
   container-relative translateX (cqw) — CSS-only, no JS (motion-spec §2). */
.hero-timeline__playhead {
  position: absolute;
  inset: var(--sp-3) var(--sp-3) var(--sp-3) calc(56px + var(--sp-3) + var(--sp-2));
  pointer-events: none;
}
.hero-timeline__playhead::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--accent);
  box-shadow: 0 0 8px rgba(79, 143, 247, 0.6);
  will-change: transform;
  animation: lp-playhead-sweep 8s var(--ease-linear) infinite;
}
/* NOTE: @keyframes cannot be nested inside @container (only @media/@supports
   may contain @keyframes per spec) — every engine silently drops that block
   and falls through to whichever @keyframes of the same name is declared
   next, unconditionally. That previously left the 60vw fallback active on
   every browser, every viewport, which visibly overshoots the timeline
   card's actual (much narrower) width. cqw is a plain length unit once an
   ancestor establishes container-type (.hero-timeline already does), so it
   works directly in @keyframes with no @container wrapper needed at all. */
@keyframes lp-playhead-sweep {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 1; }
  95% { opacity: 1; }
  100% { transform: translateX(calc(100cqw - 72px)); opacity: 0; }
}
/* Fallback for the (rare) engine without container-query unit support —
   @supports CAN legally contain @keyframes, unlike @container. */
@supports not (width: 1cqw) {
  @keyframes lp-playhead-sweep {
    0% { transform: translateX(0); opacity: 0; }
    5% { opacity: 1; }
    95% { opacity: 1; }
    100% { transform: translateX(60vw); opacity: 0; }
  }
}

/* Pause the loop when the hero is scrolled off-screen (perf, motion-spec §6). */
.hero-timeline.is-offscreen .hero-timeline__clip,
.hero-timeline.is-offscreen .hero-timeline__playhead::before {
  animation-play-state: paused;
}

/* ============================================================ */
/* 01 · The loop — a conversation beside its op journal          */
/* ============================================================ */
/* The product's whole claim in one figure: plain sentences on the left, the
   named, versioned operations they produced on the right. Two columns on
   desktop, stacked below 860px (see the responsive block). */
.lp-loop {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: var(--sp-4);
  align-items: start;
}

/* min-width: 0 for the same reason as .lp-hero__copy — these carry mono op
   names that would otherwise set a floor under the column's width. */
.lp-chat, .lp-journal {
  min-width: 0;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.lp-chat__bar, .lp-journal__bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--lp-faint-text);
}
.lp-journal__ver { color: var(--accent); }

.lp-turn {
  display: grid;
  grid-template-columns: 3.4rem 1fr;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border);
}
.lp-turn:last-child { border-bottom: none; }
.lp-turn__who {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  color: var(--lp-faint-text);
  padding-top: 2px;
}
.lp-turn--agent { background: rgba(79, 143, 247, 0.04); }
.lp-turn--agent .lp-turn__who { color: var(--accent); }
.lp-turn__body { margin: 0; font-size: var(--fs-body); line-height: 1.6; }
.lp-turn__body code { font-family: var(--font-mono); color: var(--fg); }

.lp-journal__list { margin: 0; padding: var(--sp-2) 0; list-style: none; }
.lp-journal__op {
  display: grid;
  grid-template-columns: 2.4rem 1fr auto;
  gap: var(--sp-2);
  align-items: baseline;
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-md);
}
.lp-journal__num { color: var(--accent); }
/* Hugs its text so the animated strike-through below crosses the op name and
   not the empty width of the column. */
.lp-journal__name { color: var(--fg); justify-self: start; }
.lp-journal__arg { color: var(--lp-faint-text); }
/* Undone, not deleted — the strike-through IS the point of the section. */
.lp-journal__op--undone .lp-journal__name { color: var(--lp-faint-text); text-decoration: line-through; }
.lp-journal__op--undone .lp-journal__num { color: var(--lp-faint-text); }
.lp-journal__note {
  margin: 0;
  padding: var(--sp-3);
  border-top: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: var(--fs-body);
  line-height: 1.6;
}
.lp-journal__note strong { color: var(--fg); font-weight: 600; }

/* The agent turn's reply and its "working" dots occupy the same box, so the
   dots can stand in for a reply that has not been written yet without the
   panel changing height when it arrives. */
.lp-turn__slot { display: grid; }
.lp-turn__slot > * { grid-area: 1 / 1; }
.lp-turn__working { display: flex; align-items: center; gap: 5px; height: 1.6em; opacity: 0; }
.lp-turn__working i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* A replica of a client's prompt box. Nothing here is a real control. */
.lp-compose {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
}
.lp-compose__field {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  /* flex-end + the caret's auto margin below: the line sits at the left while
     it fits, and once it is longer than the box the start slides off and the
     caret stays in view — exactly how a real single-line input behaves. */
  justify-content: flex-end;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-app);
  padding: 4px 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  color: var(--fg-muted);
}
.lp-compose__text {
  flex: none;
  width: 0;
  overflow: hidden;
  white-space: nowrap;
}
.lp-compose__caret {
  flex: none;
  width: 1px;
  height: 1.1em;
  margin-left: 1px;
  /* Absorbs the free space while the line still fits (see the field above);
     collapses to zero once it does not, handing the box to flex-end. */
  margin-right: auto;
  background: var(--accent);
  visibility: hidden;
}
.lp-compose__send {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--lp-faint-text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px 8px;
}

/* The version chip cycles through fixed values, so they stack in one cell on
   an opaque background: each new one simply covers the last. */
.lp-journal__ver { display: grid; justify-items: end; }
.lp-journal__ver > span { grid-area: 1 / 1; background: var(--bg-elevated); }
.lp-journal__args { display: grid; justify-items: end; color: var(--lp-faint-text); }
.lp-journal__args > span { grid-area: 1 / 1; }
/* Base state is the end of the loop: the op reads "undone". */
.lp-journal__args > span:nth-child(1) { opacity: 0; }
/* The strike is drawn, not text-decoration, so it can be animated across. */
.lp-journal__op--undone .lp-journal__name { text-decoration: none; position: relative; }
.lp-journal__op--undone .lp-journal__name::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--lp-faint-text);
  transform-origin: left center;
}

/* The project those ops built, spanning both columns under them. */
.lp-result {
  grid-column: 1 / -1;
  min-width: 0;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.lp-result__bar {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--lp-faint-text);
}
.lp-result__rows { padding: var(--sp-2) var(--sp-3) var(--sp-3); }
.lp-result__row { display: grid; grid-template-columns: 2.2rem 1fr; align-items: center; margin-top: 5px; }
.lp-result__name { font-family: var(--font-mono); font-size: 9px; color: var(--lp-faint-text); }
.lp-result__track { position: relative; height: 24px; background: var(--bg-app); border-radius: 3px; }
.lp-result__el {
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: 1%;
  border: 1px solid;
  border-radius: 3px;
  padding: 0 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 18px;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  transform-origin: left center;
}
.lp-result__el--clip { width: 80%; background: var(--el-clip); border-color: var(--el-clip-border); }
.lp-result__el--text { width: 14%; background: var(--el-text); border-color: var(--el-text-border); }

/* ------------------------------------------------------------ */
/* The 20s prompt → work → result loop                           */
/* ------------------------------------------------------------ */
/* Beat sheet, as a share of --lp-loop-01:
     1.5–24  the prompt types itself into the composer, caret blinking
     26      send: the composer clears and the sentence becomes a message
     28–46   the agent is working — it is calling ops the whole time
     35      editor_import_url  → v2 · the clip appears on V1
     40      editor_trim_clip   → v3 · that same clip gets shorter
     45      editor_add_text    → v4 · a title appears on T1
     48      the agent answers
     54      you push back: "too long, make it 2s"
     57–69   working again
     63      undo: v4 is struck through, the head goes back to v3, the title
             leaves the timeline — struck, not deleted, which is the point
     67      editor_add_text    → v5 · a shorter title takes its place
     71      the agent answers; 71–92 holds the finished state to be read
     92–100  everything clears back to an empty prompt box
   Base (unanimated) styles are the END state, so a reduced-motion visitor
   gets the finished conversation, journal and timeline rather than a blank. */
.lp-loop { --lp-loop-01: 20s; }

.lp-compose__text {
  /* 112ch is the prompt's own length in this mono face, so the reveal lands
     exactly on the final character. */
  animation: lp-ag-type var(--lp-loop-01) steps(112, end) infinite;
}
.lp-compose__caret {
  animation: lp-ag-blink 0.9s step-end infinite,
    lp-ag-caret var(--lp-loop-01) step-end infinite;
}
.lp-compose__send { animation: lp-ag-send var(--lp-loop-01) var(--ease-sharp) infinite; }

.lp-turn--t1 { animation: lp-ag-in-26 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t3 { animation: lp-ag-in-54 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t2 .lp-turn__body { animation: lp-ag-in-48 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t4 .lp-turn__body { animation: lp-ag-in-71 var(--lp-loop-01) var(--ease-smooth) infinite; }
/* The whole agent row, dots included, only exists once its turn is due. */
.lp-turn--t2 { animation: lp-ag-in-28 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t4 { animation: lp-ag-in-57 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t2 .lp-turn__working { animation: lp-ag-work-1 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn--t4 .lp-turn__working { animation: lp-ag-work-2 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-turn__working i { animation: lp-ag-dot 1.2s var(--ease-smooth) infinite; }
.lp-turn__working i:nth-child(2) { animation-delay: 0.15s; }
.lp-turn__working i:nth-child(3) { animation-delay: 0.3s; }

.lp-journal__op--o1 { animation: lp-ag-in-35 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__op--o2 { animation: lp-ag-in-40 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__op--o3 { animation: lp-ag-in-45 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__op--o4 { animation: lp-ag-in-67 var(--lp-loop-01) var(--ease-smooth) infinite; }
/* The note talks about v4 having been undone, so it waits for that to be true. */
.lp-journal__note { animation: lp-ag-in-71 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__op--undone .lp-journal__name { animation: lp-ag-undone var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__op--undone .lp-journal__name::after { animation: lp-ag-strike var(--lp-loop-01) var(--ease-sharp) infinite; }
.lp-journal__args > span:nth-child(1) { animation: lp-ag-out-63 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__args > span:nth-child(2) { animation: lp-ag-in-63 var(--lp-loop-01) var(--ease-smooth) infinite; }

.lp-journal__ver > span:nth-child(1) { animation: lp-ag-in-0 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__ver > span:nth-child(2) { animation: lp-ag-in-35 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__ver > span:nth-child(3) { animation: lp-ag-in-40 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__ver > span:nth-child(4) { animation: lp-ag-in-45 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__ver > span:nth-child(5) { animation: lp-ag-in-63 var(--lp-loop-01) var(--ease-smooth) infinite; }
.lp-journal__ver > span:nth-child(6) { animation: lp-ag-in-67 var(--lp-loop-01) var(--ease-smooth) infinite; }

.lp-result__el--clip { animation: lp-ag-clip var(--lp-loop-01) var(--ease-sharp) infinite; }
.lp-result__el--text { animation: lp-ag-title var(--lp-loop-01) var(--ease-sharp) infinite; }

/* One shape, nine trigger points: fade up, hold to the end of the loop, clear
   during the rewind. Elements that react to the same op share a keyframe. */
@keyframes lp-ag-in-0 { 0%, 34% { opacity: 1; } 36%, 100% { opacity: 0; } }
@keyframes lp-ag-in-26 {
  0%, 25% { opacity: 0; transform: translateY(6px); }
  28%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-28 {
  0%, 27% { opacity: 0; transform: translateY(6px); }
  30%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-35 {
  0%, 34% { opacity: 0; transform: translateY(6px); }
  37%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-40 {
  0%, 39% { opacity: 0; transform: translateY(6px); }
  42%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-45 {
  0%, 44% { opacity: 0; transform: translateY(6px); }
  47%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-48 {
  0%, 47% { opacity: 0; transform: translateY(4px); }
  50%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(4px); }
}
@keyframes lp-ag-in-54 {
  0%, 53% { opacity: 0; transform: translateY(6px); }
  56%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-57 {
  0%, 56% { opacity: 0; transform: translateY(6px); }
  59%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-63 {
  0%, 62% { opacity: 0; }
  65%, 92% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
@keyframes lp-ag-in-67 {
  0%, 66% { opacity: 0; transform: translateY(6px); }
  69%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(6px); }
}
@keyframes lp-ag-in-71 {
  0%, 70% { opacity: 0; transform: translateY(4px); }
  73%, 92% { opacity: 1; transform: translateY(0); }
  98%, 100% { opacity: 0; transform: translateY(4px); }
}
@keyframes lp-ag-out-63 { 0%, 62% { opacity: 1; } 65%, 100% { opacity: 0; } }

@keyframes lp-ag-type {
  0%, 1.5% { width: 0; }
  24%, 25.5% { width: 112ch; }
  26%, 100% { width: 0; }
}
@keyframes lp-ag-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes lp-ag-caret {
  0%, 1% { visibility: hidden; }
  1.1%, 25.5% { visibility: visible; }
  26%, 100% { visibility: hidden; }
}
@keyframes lp-ag-send {
  0%, 24% { background: transparent; color: var(--lp-faint-text); border-color: var(--border); }
  25%, 26% { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
  29%, 100% { background: transparent; color: var(--lp-faint-text); border-color: var(--border); }
}
@keyframes lp-ag-work-1 {
  0%, 29% { opacity: 0; }
  31%, 46% { opacity: 1; }
  48%, 100% { opacity: 0; }
}
@keyframes lp-ag-work-2 {
  0%, 58% { opacity: 0; }
  60%, 69% { opacity: 1; }
  71%, 100% { opacity: 0; }
}
@keyframes lp-ag-dot {
  0%, 100% { opacity: 0.25; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-3px); }
}
@keyframes lp-ag-strike {
  0%, 62% { transform: scaleX(0); }
  65%, 92% { transform: scaleX(1); }
  98%, 100% { transform: scaleX(0); }
}
@keyframes lp-ag-undone {
  0%, 62% { color: var(--fg); }
  65%, 92% { color: var(--lp-faint-text); }
  98%, 100% { color: var(--fg); }
}
/* The clip is imported whole, then loses its first 8 seconds; the title is
   added, undone, and replaced by a shorter one — the elements the ops name. */
@keyframes lp-ag-clip {
  0%, 34% { opacity: 0; width: 97%; transform: scaleX(0.9); }
  37%, 39.5% { opacity: 1; width: 97%; transform: scaleX(1); }
  41.5%, 92% { opacity: 1; width: 80%; transform: scaleX(1); }
  98%, 100% { opacity: 0; width: 80%; transform: scaleX(0.9); }
}
@keyframes lp-ag-title {
  0%, 44% { opacity: 0; width: 22%; transform: scaleX(0.1); }
  47%, 62% { opacity: 1; width: 22%; transform: scaleX(1); }
  64%, 66% { opacity: 0; width: 22%; transform: scaleX(1); }
  66.1% { opacity: 0; width: 14%; transform: scaleX(0.1); }
  69%, 92% { opacity: 1; width: 14%; transform: scaleX(1); }
  98%, 100% { opacity: 0; width: 14%; transform: scaleX(0.1); }
}

/* Same off-screen budget — and the same !important — as the editor mock. */
.lp-loop.is-offscreen *,
.lp-loop.is-offscreen *::before,
.lp-loop.is-offscreen *::after {
  animation-play-state: paused !important;
}

/* ============================================================ */
/* 02 · Three surfaces                                           */
/* ============================================================ */
.lp-surfaces {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-4);
}
.lp-panel {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  overflow: hidden;
  transition: transform var(--dur-fast) var(--ease-sharp),
    border-color var(--dur-fast) var(--ease-sharp);
}
.lp-panel:hover {
  transform: translateY(-2px);
  border-color: rgba(79, 143, 247, 0.4);
}
.lp-panel::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--lp-rule, var(--accent));
}
.lp-panel--mcp { --lp-rule: var(--el-clip-border); }
.lp-panel--app { --lp-rule: var(--el-audio-border); }
.lp-panel--ui { --lp-rule: var(--el-overlay-border); }
.lp-panel__route {
  font-family: var(--font-mono);
  font-size: var(--fs-h3);
  font-weight: 600;
  margin: var(--sp-2) 0 var(--sp-2);
}
.lp-panel__body { color: var(--fg-muted); margin: 0; }
.lp-panel__body code { font-family: var(--font-mono); color: var(--fg); }
.lp-note {
  color: var(--fg-muted);
  margin-top: var(--sp-4);
  max-width: 72ch;
}

/* ============================================================ */
/* 03 · In the editor — a CSS replica of the /app chrome         */
/* ============================================================ */
/* Deliberately NOT a screenshot: it stays crisp at any zoom, inherits the
   product's own design tokens, and cannot drift into showing a stale build.
   Everything here is decorative (the block is aria-hidden and summarised by
   a .lp-visually-hidden sibling), so no interactive element is faked with a
   <button> a keyboard user could reach and find dead. */
.lp-editor {
  /* One duration for the whole edit loop — every keyframe below is written as
     a percentage of it, so the playhead, the title, the cut, the version chip
     and the JS timecode all stay on a single clock. */
  --lp-edit-loop: 14s;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-app);
  overflow: hidden;
  font-size: var(--fs-sm);
  box-shadow: 0 24px 64px -32px rgba(0, 0, 0, 0.9);
}

.lp-editor__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--fg-muted);
  flex-wrap: wrap;
}
.lp-editor__crumb { color: var(--lp-faint-text); }
.lp-editor__id { color: var(--fg); }
.lp-editor__spacer { flex: 1; }
.lp-editor__icon { color: var(--lp-faint-text); }
.lp-editor__chip {
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  color: var(--accent);
}
.lp-editor__btn {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px 8px;
  background: var(--bg-elevated);
  color: var(--fg);
}
.lp-editor__btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }

.lp-editor__body {
  display: grid;
  grid-template-columns: 200px 1fr 190px;
  min-height: 210px;
  border-bottom: 1px solid var(--border);
}

.lp-editor__rail {
  border-right: 1px solid var(--border);
  padding: var(--sp-2);
  display: grid;
  gap: var(--sp-2);
  align-content: start;
  background: var(--bg-panel);
}
.lp-editor__tabs { display: flex; flex-wrap: wrap; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--lp-faint-text); }
.lp-editor__tabs .is-active { color: var(--accent); border-bottom: 1px solid var(--accent); }
.lp-editor__url {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  padding: 4px 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--lp-faint-text);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.lp-editor__mini { color: var(--fg-muted); border: 1px solid var(--border); border-radius: 3px; padding: 0 5px; }
.lp-editor__drop {
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-4) var(--sp-2);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--lp-faint-text);
}
.lp-editor__asset { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--fg-muted); }
.lp-editor__thumb { width: 26px; height: 16px; border-radius: 2px; background: var(--el-clip); border: 1px solid var(--el-clip-border); flex: none; }
.lp-editor__asset:last-child .lp-editor__thumb { background: var(--el-audio); border-color: var(--el-audio-border); }

.lp-editor__stage { display: grid; place-items: center; gap: var(--sp-2); padding: var(--sp-3); }
.lp-editor__frame {
  position: relative;
  width: 74px;
  height: 132px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: #000;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.lp-editor__ratio { font-family: var(--font-mono); font-size: 9px; color: var(--lp-faint-text); }
.lp-editor__transport { font-size: var(--fs-xs); color: var(--fg-muted); font-family: var(--font-mono); }
.lp-editor__tc { color: var(--fg); }

.lp-editor__inspect {
  border-left: 1px solid var(--border);
  padding: var(--sp-2);
  background: var(--bg-panel);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--fg-muted);
  display: grid;
  gap: 6px;
  align-content: start;
}
.lp-editor__inspect p { margin: 0; }
.lp-editor__chip--draft { justify-self: start; }
/* Version chip and selection line both cross-fade between fixed states, so
   each stacks its variants in one grid cell: the box never resizes mid-loop
   and the widest label sets the width once. */
.lp-editor__ver,
.lp-editor__sel {
  display: grid;
  justify-items: start;
}
.lp-editor__ver > span,
.lp-editor__sel > span {
  grid-area: 1 / 1;
}
.lp-editor__sel > span:nth-child(1) { color: var(--lp-faint-text); }
.lp-editor__sel > span:nth-child(2) { color: var(--el-text-border); }
.lp-editor__sel > span:nth-child(3) { color: var(--el-clip-border); }
.lp-editor__slider { height: 3px; border-radius: 2px; background: var(--bg-elevated); position: relative; margin-top: var(--sp-1); }
.lp-editor__slider > span { position: absolute; left: 0; top: 0; bottom: 0; width: 62%; background: var(--accent); border-radius: 2px; }

.lp-editor__timeline { position: relative; padding: var(--sp-2) var(--sp-3) var(--sp-3); background: var(--bg-app); }
.lp-editor__ruler {
  display: flex;
  justify-content: space-between;
  margin-left: 2.2rem;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--lp-faint-text);
}
.lp-editor__row { display: grid; grid-template-columns: 2.2rem 1fr; align-items: center; gap: 0; margin-top: 5px; }
.lp-editor__rowlabel { font-family: var(--font-mono); font-size: 9px; color: var(--lp-faint-text); }
.lp-editor__track { position: relative; height: 22px; background: var(--bg-panel); border-radius: 3px; }
.lp-editor__el {
  position: absolute;
  top: 2px;
  bottom: 2px;
  border: 1px solid;
  border-radius: 3px;
  padding: 0 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 16px;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lp-editor__el--clip { background: var(--el-clip); border-color: var(--el-clip-border); }
.lp-editor__el--text { background: var(--el-text); border-color: var(--el-text-border); }
.lp-editor__el--audio { background: var(--el-audio); border-color: var(--el-audio-border); }
/* Selection reads exactly as it does in /app: a brighter ring, not a color change. */
.lp-editor__el.is-selected { box-shadow: 0 0 0 1px var(--accent), 0 0 0 3px rgba(79, 143, 247, 0.35); }

.lp-editor__playhead {
  position: absolute;
  left: calc(2.2rem + var(--sp-3));
  right: var(--sp-3);
  top: var(--sp-2);
  bottom: var(--sp-3);
  pointer-events: none;
  /* Lets the sweep below be expressed in cqw — i.e. a share of the track's own
     width — instead of a viewport unit that overshoots at some breakpoints. */
  container-type: inline-size;
}
.lp-editor__playhead::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  /* Rest position is the cut point: the frame a reduced-motion visitor sees. */
  left: 64%;
  width: 1px;
  background: var(--accent);
  box-shadow: 0 -3px 0 1px var(--accent);
}

/* ------------------------------------------------------------ */
/* The 14s edit loop                                             */
/* ------------------------------------------------------------ */
/* Beat sheet, as a share of --lp-edit-loop:
     0–17    the playhead sweeps one whole clip; a light pass drifts across
             the preview — it reads as playback without faking a video file
     17      TITLE lands on T1 and fades up in the preview; chip v3 → v4
     59      the clip splits under the playhead: the head shrinks, the tail
             separates behind a cut flash and takes the selection ring;
             chip v4 → v5 and the inspector follows the new selection
     59–92   plays out to the end
     92–100  rewind — each edit undoes itself, which is what the history
             actually allows, rather than a hard cut back to frame zero
   Every gesture bumps the version chip because every gesture is one journaled
   op; that is the same claim section 01 makes in prose.
   The unanimated (base) styles are the END of the story — split clip, title
   in place, v5 — so a reduced-motion visitor is left with a finished edit and
   not an empty timeline. */

.lp-editor__el--head {
  left: 1%;
  width: 63%;
  animation: lp-ed-clip-head var(--lp-edit-loop) var(--ease-sharp) infinite;
}
.lp-editor__el--tail {
  left: 64.5%;
  width: 33.5%;
  will-change: transform, opacity;
  animation: lp-ed-clip-tail var(--lp-edit-loop) var(--ease-sharp) infinite;
}
.lp-editor__el--title {
  left: 20%;
  width: 22%;
  transform-origin: left center;
  will-change: transform, opacity;
  animation: lp-ed-title var(--lp-edit-loop) var(--ease-smooth) infinite;
}

/* The blade itself: a one-frame flash at the split point, not a UI element. */
.lp-editor__cut {
  position: absolute;
  left: 63.6%;
  top: -3px;
  bottom: -3px;
  width: 2px;
  border-radius: 1px;
  background: #fff;
  box-shadow: 0 0 6px 1px rgba(255, 255, 255, 0.75);
  opacity: 0;
  will-change: transform, opacity;
  animation: lp-ed-cut var(--lp-edit-loop) var(--ease-sharp) infinite;
}

.lp-editor__playhead::after {
  will-change: transform;
  animation: lp-ed-playhead var(--lp-edit-loop) var(--ease-linear) infinite;
}

/* Preview: a slow light pass on its own short cycle (an exact quarter of the
   loop, so a restart never lands it mid-drift) plus the title it just got. */
.lp-editor__pass {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 30%,
    rgba(79, 143, 247, 0.34) 45%,
    rgba(255, 255, 255, 0.28) 50%,
    rgba(79, 143, 247, 0.34) 55%,
    transparent 70%
  );
  will-change: transform;
  animation: lp-ed-pass calc(var(--lp-edit-loop) / 4) var(--ease-linear) infinite;
}
.lp-editor__ratio { position: relative; }
.lp-editor__pvtitle {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 0.08em;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  opacity: 0;
  animation: lp-ed-pvtitle var(--lp-edit-loop) var(--ease-smooth) infinite;
}

/* Version chip and inspector selection change on the same beats, so they run
   the same three-state cross-fade. */
.lp-editor__ver > span:nth-child(1),
.lp-editor__sel > span:nth-child(1) { opacity: 0; animation: lp-ed-state-1 var(--lp-edit-loop) var(--ease-smooth) infinite; }
.lp-editor__ver > span:nth-child(2),
.lp-editor__sel > span:nth-child(2) { opacity: 0; animation: lp-ed-state-2 var(--lp-edit-loop) var(--ease-smooth) infinite; }
.lp-editor__ver > span:nth-child(3),
.lp-editor__sel > span:nth-child(3) { animation: lp-ed-state-3 var(--lp-edit-loop) var(--ease-smooth) infinite; }

@keyframes lp-ed-clip-head {
  0%, 58.6% { width: 97%; }
  60%, 93% { width: 63%; }
  97%, 100% { width: 97%; }
}
@keyframes lp-ed-clip-tail {
  0%, 58.6% { opacity: 0; transform: translateX(-6px); }
  60%, 93% { opacity: 1; transform: translateX(0); }
  96%, 100% { opacity: 0; transform: translateX(-6px); }
}
@keyframes lp-ed-title {
  0%, 16.5% { opacity: 0; transform: scaleX(0.04); }
  19% { opacity: 1; transform: scaleX(1.05); }
  21%, 93% { opacity: 1; transform: scaleX(1); }
  96%, 100% { opacity: 0; transform: scaleX(0.04); }
}
@keyframes lp-ed-cut {
  0%, 58.6% { opacity: 0; transform: scaleY(0.3); }
  59.5% { opacity: 1; transform: scaleY(1.35); }
  63%, 100% { opacity: 0; transform: scaleY(0.3); }
}
@keyframes lp-ed-pvtitle {
  0%, 16.5% { opacity: 0; transform: translateY(3px); }
  19%, 36% { opacity: 1; transform: translateY(0); }
  40%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes lp-ed-pass {
  0% { transform: translateY(-100%); }
  100% { transform: translateY(100%); }
}
@keyframes lp-ed-state-1 {
  0%, 15% { opacity: 1; }
  17.5%, 94% { opacity: 0; }
  97%, 100% { opacity: 1; }
}
@keyframes lp-ed-state-2 {
  0%, 15% { opacity: 0; }
  17.5%, 58% { opacity: 1; }
  60%, 100% { opacity: 0; }
}
@keyframes lp-ed-state-3 {
  0%, 58% { opacity: 0; }
  60%, 94% { opacity: 1; }
  97%, 100% { opacity: 0; }
}
/* The line rests at the cut (left: 64%), so the sweep is expressed as an
   offset either side of it: -62cqw puts it at 2%, +34cqw at 98%. Same reason
   the hero uses cqw — a viewport unit overshoots this card's real width.
   See the note there on why @keyframes cannot live inside @container. */
@keyframes lp-ed-playhead {
  0% { transform: translateX(-62cqw); opacity: 1; }
  92% { transform: translateX(34cqw); opacity: 1; }
  94% { transform: translateX(34cqw); opacity: 0; }
  96% { transform: translateX(-62cqw); opacity: 0; }
  100% { transform: translateX(-62cqw); opacity: 1; }
}
@supports not (width: 1cqw) {
  @keyframes lp-ed-playhead {
    0% { left: 2%; opacity: 1; }
    92% { left: 98%; opacity: 1; }
    94% { left: 98%; opacity: 0; }
    96% { left: 2%; opacity: 0; }
    100% { left: 2%; opacity: 1; }
  }
}

/* Off-screen: nothing animates that nobody is looking at. .is-resetting is the
   companion JS uses to restart the loop from zero on re-entry, so the CSS
   clock and the JS timecode never drift apart across a pause. */
/* !important is load-bearing: the `animation` shorthand in the rules above
   resets animation-play-state to running, and several of them (the nth-child
   selectors) outrank this one. A longhand !important beats them all. */
.lp-editor.is-offscreen *,
.lp-editor.is-offscreen *::before,
.lp-editor.is-offscreen *::after {
  animation-play-state: paused !important;
}
.lp-editor.is-resetting *,
.lp-editor.is-resetting *::before,
.lp-editor.is-resetting *::after {
  animation: none !important;
}

/* The four things a person actually does here, stated plainly. */
.lp-uses {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}
.lp-use__title { margin: 0 0 var(--sp-1); font-size: var(--fs-md); font-weight: 600; }
.lp-use__body { margin: 0; color: var(--fg-muted); font-size: var(--fs-body); line-height: 1.55; }

/* ============================================================ */
/* 04 · Capabilities datasheet                                  */
/* ============================================================ */
.lp-specs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.lp-spec {
  background: var(--bg-elevated);
  padding: var(--sp-4);
}
.lp-spec__label {
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  color: var(--fg);
  margin: 0 0 var(--sp-2);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.lp-spec__value { color: var(--fg-muted); margin: 0; }
.lp-spec__value code { font-family: var(--font-mono); color: var(--fg); }
.lp-swatches { display: inline-flex; gap: var(--sp-1); }
.lp-swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  display: inline-block;
}
.lp-swatch--clip { background: var(--el-clip-border); }
.lp-swatch--text { background: var(--el-text-border); }
.lp-swatch--audio { background: var(--el-audio-border); }
.lp-swatch--overlay { background: var(--el-overlay-border); }

/* ============================================================ */
/* 05 · How it works — ordered pipeline on a mini track          */
/* ============================================================ */
.lp-flow {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}
.lp-step {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-top: 3px solid var(--lp-rule, var(--accent));
  border-radius: var(--radius);
  padding: var(--sp-4);
}
.lp-flow > .lp-step:nth-child(1) { --lp-rule: var(--el-clip-border); }
.lp-flow > .lp-step:nth-child(2) { --lp-rule: var(--el-text-border); }
.lp-flow > .lp-step:nth-child(3) { --lp-rule: var(--el-audio-border); }
.lp-flow > .lp-step:nth-child(4) { --lp-rule: var(--el-overlay-border); }
.lp-step__num {
  font-family: var(--font-mono);
  font-size: var(--fs-mono-label);
  color: var(--lp-faint-text);
}
.lp-step__title {
  font-size: var(--fs-h3);
  font-weight: 600;
  margin: var(--sp-2) 0;
}
.lp-step__body { color: var(--fg-muted); margin: 0; font-size: var(--fs-body); }

/* ============================================================ */
/* 06 · For agents (MCP)                                        */
/* ============================================================ */
.lp-agents {
  display: grid;
  grid-template-columns: 1.7fr 1fr;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  align-items: start;
}
.lp-code {
  /* Grid items default to min-width:auto (their content's intrinsic min
     width), so the wide, non-wrapping <pre> below was forcing this track —
     and the whole page — wider than the viewport on mobile instead of
     scrolling internally via the <pre>'s own overflow-x:auto. */
  min-width: 0;
  position: relative;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.lp-code__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--lp-faint-text);
}
.lp-copy {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--fg-muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.2rem 0.55rem;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-sharp),
    border-color var(--dur-fast) var(--ease-sharp);
}
.lp-copy:hover { color: var(--fg); border-color: var(--accent); }
.lp-copy:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(79, 143, 247, 0.2);
}
.lp-code pre {
  margin: 0;
  padding: var(--sp-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--fg);
}
.lp-agents__prose { color: var(--fg-muted); }
.lp-agents__prose code { font-family: var(--font-mono); color: var(--fg); }
.lp-agents__cta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  align-items: flex-start;
  margin-top: var(--sp-4);
}

/* ============================================================ */
/* 07 · CTA band                                                */
/* ============================================================ */
.lp-cta-band {
  background: var(--bg-panel);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  text-align: center;
}
.lp-cta-band__inner {
  max-width: var(--lp-maxw);
  margin: 0 auto;
  padding: clamp(3rem, 7vw, 4.5rem) var(--lp-gutter);
}
.lp-cta-band .lp-strip {
  max-width: 220px;
  margin: 0 auto var(--sp-4);
}
.lp-cta-band__title {
  font-size: var(--fs-h2);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-4);
}
.lp-cta-band .lp-cta-row { justify-content: center; }

/* ============================================================ */
/* Footer                                                       */
/* ============================================================ */
.lp-footer {
  max-width: var(--lp-maxw);
  margin: 0 auto;
  padding: var(--sp-4) var(--lp-gutter) calc(var(--sp-4) * 2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  border-top: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--fg-muted);
}
.lp-footer a { color: var(--fg-muted); }
.lp-footer a:hover { color: var(--fg); }
.lp-footer a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(79, 143, 247, 0.35);
  border-radius: var(--radius-sm);
}
.lp-footer__links { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.lp-footer__tagline { color: var(--lp-faint-text); }

/* ============================================================ */
/* Scroll-reveal (motion-spec §3 + §5 Layer A)                  */
/* ============================================================ */
/* Default: fully visible — a no-JS / reduced-motion visitor sees a complete
   page. The animated hidden-then-reveal is opted into ONLY when JS confirms
   motion is allowed by adding .js-motion-ready to <html>. */
.reveal { opacity: 1; transform: none; }

html.js-motion-ready .reveal {
  opacity: 0;
  transform: translateY(var(--dist-md));
  transition: opacity var(--dur-normal) var(--ease-smooth),
    transform var(--dur-normal) var(--ease-smooth);
  will-change: opacity, transform;
}
html.js-motion-ready .reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.reveal-group > .reveal:nth-child(1) { transition-delay: 0ms; }
.reveal-group > .reveal:nth-child(2) { transition-delay: 80ms; }
.reveal-group > .reveal:nth-child(3) { transition-delay: 160ms; }
.reveal-group > .reveal:nth-child(4) { transition-delay: 240ms; }
.reveal-group > .reveal:nth-child(5) { transition-delay: 320ms; }

/* ============================================================ */
/* Responsive                                                   */
/* ============================================================ */
@media (max-width: 860px) {
  .lp-rail { display: none; }
  .lp-hero,
  .lp-surfaces,
  .lp-specs,
  .lp-flow,
  .lp-agents,
  .lp-loop {
    grid-template-columns: 1fr;
  }
  .lp-hero__stage { order: 2; }
  .lp-uses { grid-template-columns: repeat(2, 1fr); }
  /* The editor replica keeps its three panes down to tablet width; below that
     the inspector column is the first thing a real user collapses too. */
  .lp-editor__body { grid-template-columns: 150px 1fr; }
  .lp-editor__inspect { display: none; }
}

@media (max-width: 560px) {
  .lp-uses { grid-template-columns: 1fr; }
  /* Below phone width the media rail goes too — the timeline is the part
     worth showing, and a 3-pane mock at 360px is unreadable mush. */
  .lp-editor__body { grid-template-columns: 1fr; }
  .lp-editor__rail { display: none; }
}

/* ============================================================ */
/* prefers-reduced-motion (motion-spec §5 Layer B) — mandatory  */
/* ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .hero-timeline__clip,
  .hero-timeline__playhead::before {
    animation: none !important;
    opacity: 0.9;
    transform: none !important;
  }
  .lp-rail__head { transition: none !important; }
  /* The blanket 0.01ms rule above would run both figure loops straight to
     their 100% frame — which is the REWIND, i.e. an empty timeline and an
     empty conversation. Killing their animations outright instead leaves the
     base styles, and those are written as the finished state: the whole
     exchange, the journal through v5, the trimmed clip and its title. */
  .lp-editor *,
  .lp-editor *::before,
  .lp-editor *::after,
  .lp-loop *,
  .lp-loop *::before,
  .lp-loop *::after {
    animation: none !important;
  }
}
