@import url("../_ds/fonts.css");
@import url("../_ds/theme.css");
@import url("../_shared/chrome.css");
@import url("../_shared/components.css");

/* ──────────────────────────────────────────────────────────
   /cli — Terminal-native Zenrows.

   Editorial wedge: the page IS the terminal.  The hero
   centres an interactive terminal panel — chip row at the
   bottom lets the reader pick a subcommand and the terminal
   acts back.  When idle, a default 3-scenario cycle plays.

   Borrows the asymmetric hero pattern from /mcp
   (H1 left + demo right) but the demo is reactive, not just
   auto-playing.
─────────────────────────────────────────────────────────── */


main {
  position: relative;
  z-index: 1;
}

/* Cursor portal — the spinning O is the only pointer when
   hovering interactive surfaces (terminal, chips, install
   line, back-to-top).  Suppress the native cursor on every
   one of them so the cursor never doubles up. */
.back-to-top,
.cli-term,
.cli-term *,
.cli-chip,
.cli-wedge-pill,
.cli-wedge-panel,
.cli-wedge-panel * {
  cursor: pointer;
}

/* ──────────────────────────────────────────────────────────
   Act 1 — Hero.  Asymmetric editorial + interactive terminal.
─────────────────────────────────────────────────────────── */

[data-act="1"] {
  position: relative;
  min-height: 100svh;
  min-height: 100vh;
  padding: clamp(96px, 12vh, 140px) clamp(20px, 4vw, 48px) clamp(56px, 8vh, 96px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--background);
  z-index: 1;
}

.cli-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: stretch;
  gap: clamp(40px, 5vw, 88px);
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  min-height: calc(100vh - clamp(96px, 12vh, 140px) - clamp(56px, 8vh, 96px));
}

/* Editorial column — kicker + H1 + sub, centred vertically
   in the viewport-tall column.  No CTA here; the install
   line below the terminal and the closer-act button handle
   the call to action so the H1 area stays uncluttered. */
.cli-hero-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  max-width: 560px;
  min-width: 0;
  gap: clamp(20px, 3vh, 32px);
}
/* Kicker default margin-bottom kicks against the flex gap —
   reset locally so spacing is governed by the gap alone. */
.cli-hero-text .act-kicker { margin: 0; }

.cli-hero-h1 {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: clamp(40px, 5.4vw, 72px);
  line-height: 1.02;
  letter-spacing: var(--tracking-dense, -0.034em);
  font-weight: 500;
  color: var(--text-primary);
  text-wrap: balance;
}

.cli-hero-line { display: block; }

/* Single marked phrase — "Zenrows" stays in the display
   face (inherits Rawest from the H1) and switches to brand
   purple-7 for the accent. */
.cli-hero-mark {
  color: var(--zen-purple-7, #7C4FE8);
}

.cli-hero-sub {
  margin: 0;
  max-width: 460px;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.5;
  color: var(--text-secondary);
  text-wrap: balance;
}

.cli-hero-cta {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: clamp(16px, 1.8vw, 28px);
  flex-wrap: wrap;
}

.cli-hero-tag {
  margin: 0;
  font-family: var(--font-code, monospace);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
}

/* Demo column — terminal + install line stacked vertically. */
.cli-hero-demo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(14px, 2vh, 24px);
  min-width: 0;
}

/* Terminal — frame-only border-subtle, body holds the live
   output, chip row anchored at the bottom.  No fill, no
   shadow: the editorial weight is the content. */
.cli-term {
  position: relative;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-display, 20px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: clamp(320px, 44vh, 440px);
}

.cli-term-bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 18px;
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-code, monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.78);
  overflow: hidden;
  isolation: isolate;
  min-height: 44px;
}

/* Mesh-gradient backdrop — ported 1:1 from MCP's .mc-convo-bar.
   Four vibrant bubbles drift across the bar on independent
   loops (purple / orange / red / cyan on an orange→purple
   base).  No global rotation; the linear base guarantees the
   bar is always fully covered while the bubbles travel. */
.cli-term-mesh {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background: linear-gradient(
    135deg,
    var(--zen-orange-5, #C97A4E) 0%,
    var(--zen-purple-5, #6B4DCF) 100%
  );
}

.cli-term-bubble {
  position: absolute;
  width: 65%;
  height: 280%;
  border-radius: 50%;
  filter: blur(34px);
  transform: translateZ(0);
  backface-visibility: hidden;
  opacity: 0.92;
  will-change: transform;
}

.cli-term-bubble[data-bubble="1"] {
  background: var(--zen-purple-6, #9B6FFF);
  top: -90%;
  left: -10%;
  animation: cli-bubble-1 7s ease-in-out infinite alternate;
}
.cli-term-bubble[data-bubble="2"] {
  background: var(--zen-orange-6, #F38C5A);
  top: -80%;
  left: 35%;
  animation: cli-bubble-2 9s ease-in-out infinite alternate;
}
.cli-term-bubble[data-bubble="3"] {
  background: var(--zen-red-6, #F36A6A);
  top: -100%;
  left: 55%;
  animation: cli-bubble-3 11s ease-in-out infinite alternate;
}
.cli-term-bubble[data-bubble="4"] {
  background: #7ADAE6;
  top: -85%;
  left: 18%;
  animation: cli-bubble-4 13s ease-in-out infinite alternate;
}

@keyframes cli-bubble-1 {
  0%   { transform: translate(0,    0); }
  100% { transform: translate(55%,  20%); }
}
@keyframes cli-bubble-2 {
  0%   { transform: translate(0,    0); }
  100% { transform: translate(-40%, 30%); }
}
@keyframes cli-bubble-3 {
  0%   { transform: translate(0,    0); }
  100% { transform: translate(45%, -25%); }
}
@keyframes cli-bubble-4 {
  0%   { transform: translate(0,    0); }
  100% { transform: translate(-30%,-20%); }
}

.cli-term-bar > *:not(.cli-term-mesh) {
  position: relative;
  z-index: 1;
}

.cli-term-dots {
  display: inline-flex;
  gap: 6px;
}
.cli-term-dots span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.35);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
  flex-shrink: 0;
}

.cli-term-title {
  margin-left: 8px;
  font-weight: 500;
  color: #FFFFFF;
}

.cli-term-status {
  margin-left: auto;
  padding: 2px 8px;
  border-radius: var(--radius-full, 999px);
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.20);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
  font-weight: 500;
  transition: background 240ms ease, border-color 240ms ease, color 240ms ease;
}

.cli-term-status[data-cli-status="busy"] {
  background: rgba(0, 0, 0, 0.35);
  border-color: rgba(255, 255, 255, 0.45);
  color: #FFFFFF;
}
.cli-term-status[data-cli-status="done"] {
  background: rgba(122, 218, 230, 0.32);
  border-color: rgba(122, 218, 230, 0.65);
  color: #FFFFFF;
}

.cli-term-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: clamp(18px, 2vw, 26px) clamp(18px, 2vw, 26px) clamp(8px, 1vw, 12px);
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body-xs);
  line-height: 1.6;
  color: var(--text-secondary);
  overflow-y: hidden;
  overflow-x: clip;
  display: flex;
  flex-direction: column;
  gap: 6px;
  scrollbar-width: none;
}
.cli-term-body::-webkit-scrollbar { display: none; }

.cli-line {
  display: block;
  height: 1.6em;
  line-height: 1.6em;
  white-space: pre;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 220ms ease, transform 220ms ease;
}
.cli-line.is-shown {
  opacity: 1;
  transform: translateY(0);
}

.cli-line[data-kind="cmd"]    { color: var(--text-primary); }
.cli-line[data-kind="cmd"]::before {
  content: "$ ";
  color: var(--zen-cyan-6, #7ADAE6);
  font-weight: 500;
}
.cli-line[data-kind="ok"]     { color: var(--zen-green-6, #6BD9A1); }
.cli-line[data-kind="info"]   { color: var(--text-tertiary); }
.cli-line[data-kind="data"]   { color: var(--text-secondary); }
.cli-line[data-kind="arrow"]  { color: var(--text-tertiary); }
.cli-line[data-kind="warn"]   { color: var(--zen-yellow-6, #F5C56A); }

/* Blinking caret on the active typed line. */
.cli-line.is-typing::after {
  content: "▍";
  display: inline-block;
  margin-left: 2px;
  color: var(--zen-cyan-6, #7ADAE6);
  animation: cli-caret 0.9s steps(1) infinite;
}
@keyframes cli-caret {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* Chip row — the interactive part.  Horizontal scroll on
   narrow viewports so all 7 chips stay reachable. */
.cli-term-chips {
  display: flex;
  flex-direction: row;
  gap: 8px;
  padding: 12px clamp(14px, 2vw, 20px) 14px;
  border-top: 1px solid var(--border-subtle);
  overflow-x: auto;
  scrollbar-width: none;
}
.cli-term-chips::-webkit-scrollbar { display: none; }

.cli-chip {
  flex-shrink: 0;
  font-family: var(--font-code, monospace);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 7px 14px;
  border-radius: var(--radius-full, 999px);
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--text-secondary);
  transition: color 180ms ease, border-color 180ms ease, background 180ms ease;
  outline: none;
}
.cli-chip:hover {
  color: var(--text-primary);
  border-color: rgba(255, 255, 255, 0.32);
}
.cli-chip[aria-selected="true"],
.cli-chip.is-active {
  color: #FFFFFF;
  background: #7C4FE8;
  border-color: var(--zen-purple-7, #7C4FE8);
}

/* Install line — quiet copy-able single-row strip under the
   terminal.  Mono prompt + cmd + secondary aux line with
   alternative package managers. */
.cli-install {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px clamp(14px, 2vw, 20px);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill, 14px);
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body-xs);
  color: var(--text-secondary);
}
.cli-install-prompt {
  color: var(--zen-cyan-6, #7ADAE6);
  font-weight: 500;
}
.cli-install-cmd {
  color: var(--text-primary);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cli-install-aux {
  margin-left: auto;
  color: var(--text-tertiary);
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* ── Mobile responsive ──────────────────────────────────── */

@media (max-width: 1023px) {
  [data-act="1"] {
    padding: clamp(80px, 11vh, 120px) clamp(18px, 5vw, 32px) clamp(48px, 8vh, 80px);
  }
  .cli-hero {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    gap: clamp(36px, 5vh, 56px);
    max-width: 640px;
    min-height: 0;
  }
  .cli-hero-text { max-width: none; }
  .cli-term { min-height: 360px; }
}

@media (max-width: 600px) {
  .cli-hero-h1 { font-size: var(--mkt-h2); }
  .cli-install-aux { display: none; }
  .cli-term-body { font-size: 12px; }
}

/* ── Wide-desktop tiers ─────────────────────────────────── */

@media (min-width: 1600px) {
  .cli-hero          { max-width: 1440px; }
  .cli-hero-text     { max-width: 660px; }
  .cli-hero-h1       { font-size: 84px; }
  .cli-hero-sub      { font-size: 19px; max-width: 540px; }
  .cli-hero-tag      { font-size: 13px; }
  .cli-term          { min-height: 520px; }
  .cli-term-body     { font-size: 15px; }
  .cli-install       { font-size: 15px; }
}

@media (min-width: 1920px) {
  .cli-hero          { max-width: 1560px; }
  .cli-hero-text     { max-width: 740px; }
  .cli-hero-h1       { font-size: 96px; }
  .cli-hero-sub      { font-size: 20px; max-width: 600px; }
  .cli-hero-tag      { font-size: 13.5px; }
  .cli-term          { min-height: 580px; }
  .cli-term-body     { font-size: 16px; }
  .cli-install       { font-size: 16px; }
}

@media (min-width: 2400px) {
  .cli-hero          { max-width: 1740px; }
  .cli-hero-text     { max-width: 860px; }
  .cli-hero-h1       { font-size: 116px; }
  .cli-hero-sub      { font-size: 22px; max-width: 680px; }
  .cli-hero-tag      { font-size: 14px; }
  .cli-term          { min-height: 640px; }
  .cli-term-body     { font-size: 18px; }
  .cli-install       { font-size: 17.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .cli-line { transition: none; opacity: 1; transform: none; }
  .cli-line.is-typing::after { animation: none; }
  .cli-term-bubble { animation: none; }
}


/* ──────────────────────────────────────────────────────────
   Act 2 — The wedge / duel.

   Dark canvas.  Different topology from Act 1:
     • Act 1 was editorial-left + demo-right (1fr / 1.15fr).
     • Act 2 stacks vertically — editorial head TOP-RIGHT
       aligned with picker pill row, full-width arena BELOW
       with two side-by-side panels facing each other.

   Scroll-driven entry: as the section enters viewport,
   --enter goes 0 → 1; the naive panel slides in from the
   LEFT edge, the zenrows panel from the RIGHT, both meeting
   at the centre.  Once entered, the battle plays in unison
   per scenario: naive's progress fills then halts + the
   panel shakes + a BLOCKED stamp drops in; in parallel
   zenrows' progress sweeps to 100% + 3 adaptive chips light
   up + a 200 OK stamp fades in + the panel border pulses
   purple-7.
─────────────────────────────────────────────────────────── */

/* Section is taller than 1 viewport so the sticky stage can
   hold for the scroll-driven scenario advance.  --enter
   drives panel slide-in during entry; --beat drives the
   active scenario index. */
[data-act="2"] {
  position: relative;
  z-index: 2;
  background: var(--background);
  color: var(--text-primary);
  isolation: isolate;
  --enter: 0;
  --beat: 0;
  /* 280vh: ~80vh of entry + ~180vh of sticky duration
     covering 5 scenarios (~45vh per beat).  Tight but each
     beat carries the active scenario's animation. */
  min-height: 280vh;
}

/* Stage pins for the duration of the section.  Inside: head
   above, arena below.  100vh of pinned viewport. */
.cli-wedge-stage {
  position: sticky;
  top: 0;
  z-index: 1;
  width: 100%;
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(96px, 13vh, 160px) clamp(20px, 5vw, 80px) clamp(56px, 8vh, 96px);
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 4vh, 48px);
}

/* Head — single column, top-down stack.  Meta row (eyebrow
   + scenario counter) at top, then H2, then sub, then a
   hairline separator above the pills.  Reads as a clean
   magazine section opener with a built-in segmented control. */
.cli-wedge-head {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* Meta row — eyebrow LEFT, counter RIGHT, on the same line. */
.cli-wedge-head-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
}

.cli-wedge-counter {
  margin: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Tight vertical rhythm — gaps tuned per pair instead of a
   uniform stack gap. */
.cli-wedge-head-meta + .cli-wedge-h2 { margin-top: clamp(20px, 2.6vh, 32px); }
.cli-wedge-h2 + .cli-wedge-sub       { margin-top: clamp(14px, 1.8vh, 22px); }
.cli-wedge-sub + .cli-wedge-pick     { margin-top: clamp(28px, 4vh, 48px); }

/* Eyebrow — leading hairline mark (24px line) followed by
   the label. */

.cli-wedge-h2 {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.05;
  letter-spacing: var(--tracking-dense, -0.028em);
  font-weight: 500;
  color: var(--text-primary);
  text-wrap: balance;
  max-width: 22ch;
}

.cli-wedge-sub {
  margin: 0;
  max-width: 560px;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.5;
  color: var(--text-secondary);
  text-wrap: balance;
}

/* Picker — full-width segmented strip below the editorial
   copy.  Driven by scroll, click works as manual override. */
.cli-wedge-pick {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 8px;
}

.cli-wedge-pill {
  font-family: var(--font-code, monospace);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 8px 14px;
  border-radius: var(--radius-full, 999px);
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  outline: none;
  transition: color 180ms ease, background 180ms ease, border-color 180ms ease;
}
.cli-wedge-pill:hover {
  color: var(--text-primary);
  border-color: rgba(255, 255, 255, 0.32);
}
.cli-wedge-pill.is-active {
  color: #FFFFFF;
  background: #7C4FE8;
  border-color: var(--zen-purple-7, #7C4FE8);
}

/* Arena — single column, widgets STACKED vertically.  Naive
   on top, zenrows below.  Each widget is full-width so the
   code lines occupy the same x-axis space in both — a line
   from naive sits directly above the corresponding line in
   zenrows, line-by-line.  Reader compares top-to-bottom
   rather than side-by-side. */
.cli-wedge-arena {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vh, 40px);
  width: 100%;
}

/* Divider — sits between naive + zenrows panels.  Carries
   a "VS" centre label + a horizontal spark that fires per
   scenario change.  The VS has a subtle infinite breathing
   pulse so the divider never reads inert between scenario
   changes. */
.cli-wedge-divider {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(10px, 1.4vh, 18px) 0;
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
  overflow: hidden;
}

.cli-wedge-divider-vs {
  position: relative;
  z-index: 1;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h4);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  padding: 0 clamp(14px, 2vw, 24px);
  background: var(--background);
  animation: cli-vs-breathe 3.6s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
}

@keyframes cli-vs-breathe {
  0%, 100% { opacity: 0.6; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.03); }
}

/* Horizontal spark — fires left → right when JS adds
   .is-firing.  Single-shot keyframe; .is-firing is added
   then removed via reflow trick on each scenario change. */
.cli-wedge-divider::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    color-mix(in srgb, var(--zen-purple-7, #7C4FE8) 80%, transparent) 50%,
    transparent 100%);
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}
.cli-wedge-divider.is-firing::before {
  animation: cli-spark 900ms cubic-bezier(0.22, 1, 0.36, 1) 1;
}

@keyframes cli-spark {
  0%   { transform: translateX(-100%); opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: translateX(100%); opacity: 0; }
}

/* Panels — frameless.  No border, no background, no
   overflow:hidden container.  Each panel is just a column
   of content that GROWS FROM THE BOTTOM as output streams
   in; older content can bleed past the top edge (overflow
   visible).  The header label + badge guide which side is
   which. */
.cli-wedge-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  background: transparent;
  border: 0;
  border-radius: 0;
  overflow: visible;
  min-height: clamp(120px, 18vh, 180px);
  padding: 0;
  width: 100%;
}

/* Scroll-driven entry — both panels rise into place from
   below as --enter ramps 0 → 1.  Naive lands first, zenrows
   shortly after (visually it reads as "naive collapsed,
   zenrows answered"). */
.cli-wedge-panel[data-mode="naive"] {
  transform: translateY(calc((1 - var(--enter, 0)) * 24px));
  opacity: clamp(0, calc((var(--enter, 0) - 0.05) * 2.2), 1);
}
.cli-wedge-panel[data-mode="zenrows"] {
  transform: translateY(calc((1 - var(--enter, 0)) * 32px));
  opacity: clamp(0, calc((var(--enter, 0) - 0.10) * 2.4), 1);
}

/* Battle state — minimal.  Borders stay subtle throughout
   (DS border-subtle) regardless of fail/win.  The fight
   reads through the dot / tag / stamp / layer chip colour
   states + the one-shot shake on naive failure.  No coloured
   panel border, no win-pulse box-shadow — keeps the act
   restrained. */
.cli-wedge-panel.is-shaking { animation: cli-shake 360ms ease-out 1; }

@keyframes cli-shake {
  0%, 100% { translate: 0 0; }
  20%      { translate: -6px 0; }
  40%      { translate:  5px 0; }
  60%      { translate: -4px 0; }
  80%      { translate:  3px 0; }
}


/* Tag — text-only label, no border, no bg, no colour swap.
   Stays text-tertiary throughout the run; the dot + stamp
   are the badges that carry fail/win state. */
.cli-wedge-panel-tag {
  margin-left: auto;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--text-tertiary);
  transition: color 200ms ease;
}

/* Progress rail — neutral throughout (no red / no purple).
   The fill is text-tertiary; the rail track is border-
   subtle.  Position + speed of the fill carry the contrast
   (naive halts ~70%, zenrows sweeps to 100%). */
.cli-wedge-progress {
  height: 2px;
  background: var(--border-subtle);
  overflow: hidden;
  margin-bottom: clamp(12px, 1.8vh, 18px);
}
.cli-wedge-progress-bar {
  height: 100%;
  width: 0;
  background: var(--text-tertiary);
  transition: width 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Adaptive layers — chips above the zenrows output.  Off
   state border-subtle + tertiary; on state opacity bumps to
   text-secondary so they "wake up" without leaning on
   colour. */
.cli-wedge-layers {
  list-style: none;
  margin: 0 0 clamp(12px, 1.6vh, 16px);
  padding: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 28px;
}
.cli-wedge-layers li {
  font-family: var(--font-code, monospace);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 3px 10px;
  border-radius: var(--radius-full, 999px);
  border: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
  background: transparent;
  transition: color 240ms ease, border-color 240ms ease;
  white-space: nowrap;
  opacity: 0.55;
}
.cli-wedge-layers li.is-on {
  color: var(--text-primary);
  border-color: rgba(255, 255, 255, 0.32);
  opacity: 1;
}

/* Body — content anchored to the BOTTOM of the panel.  Each
   .cli-line gets an explicit `height: 1.6em` so every row
   takes the same vertical slot regardless of content; gap
   is dropped so spacing comes purely from line-height.  Two
   widgets sharing the same min-height + same row heights
   means line N in one widget sits at the exact same Y as
   line N in the other.  Reads as a 2-col code diff. */
.cli-wedge-panel-body {
  margin: 0;
  padding: 0;
  flex: 1 1 auto;
  min-height: 0;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body-xs);
  line-height: 1.6;
  color: var(--text-secondary);
  white-space: pre;
  overflow: visible;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0;
  /* Right-align the code lines — breaks the conventional
     left-aligned terminal rhythm.  All lines end at the right
     edge of the panel; shorter lines pad inward from the
     left.  Reads as editorial typography rather than a
     literal shell session. */
  text-align: right;
}

/* Naive widget (red, first) flips to left-aligned so the two
   widgets read as a mirrored matchup — naive runs L→R, zenrows
   R→L, both bottoms still aligned across the divider. */
.cli-wedge-panel[data-mode="naive"] .cli-wedge-panel-body {
  text-align: left;
}

.cli-wedge-panel-body .cli-line { gap: 0; }
.cli-wedge-panel-body .cli-line[data-kind="cmd"]::before {
  content: "$ ";
  color: var(--zen-purple-7, #7C4FE8);
  font-weight: 500;
}
.cli-wedge-panel[data-mode="naive"]  .cli-line[data-kind="cmd"]::before { color: var(--zen-red-6, #F36A6A); }
.cli-wedge-panel-body .cli-line[data-kind="cmd"]  { color: var(--text-primary); }
.cli-wedge-panel-body .cli-line[data-kind="err"]  { color: var(--zen-red-6, #F36A6A); }
.cli-wedge-panel-body .cli-line[data-kind="ok"]   { color: var(--zen-green-6, #6BD9A1); }
.cli-wedge-panel-body .cli-line[data-kind="info"] { color: var(--text-tertiary); }
.cli-wedge-panel-body .cli-line[data-kind="data"] { color: var(--text-secondary); }

/* Result stamps — drop in at the end of each run.  Absolute
   bottom-right of the panel; data-show="true" reveals. */
.cli-wedge-stamp {
  position: absolute;
  right: clamp(18px, 2vw, 28px);
  bottom: clamp(18px, 2vw, 28px);
  padding: 8px 16px;
  border-radius: 6px;
  font-family: var(--font-code, monospace);
  font-size: clamp(13px, 1.1vw, 17px);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border: 2px solid var(--zen-red-6, #F36A6A);
  color: var(--zen-red-6, #F36A6A);
  background: rgba(243, 106, 106, 0.08);
  opacity: 0;
  transform: rotate(-8deg) translateY(-20px) scale(0.85);
  pointer-events: none;
  transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}
.cli-wedge-stamp[data-show="true"] {
  opacity: 1;
  transform: rotate(-8deg) translateY(0) scale(1);
}
.cli-wedge-stamp.cli-wedge-stamp--good {
  border-color: var(--zen-purple-7, #7C4FE8);
  color: var(--zen-purple-7, #7C4FE8);
  background: rgba(124, 79, 232, 0.08);
  transform: rotate(4deg) translateY(-20px) scale(0.85);
}
.cli-wedge-stamp.cli-wedge-stamp--good[data-show="true"] {
  transform: rotate(4deg) translateY(0) scale(1);
}

/* ── Mobile responsive ──────────────────────────────────── */

@media (max-width: 1023px) {
  [data-act="2"] {
    /* Mobile drops the sticky stage and scroll-driven beat
       — section becomes a plain flow block.  Scenarios still
       cycle on their own + are clickable. */
    min-height: 0;
  }
  .cli-wedge-stage {
    position: static;
    height: auto;
    padding: clamp(72px, 10vh, 120px) clamp(20px, 5vw, 32px) clamp(96px, 12vh, 140px);
    gap: clamp(32px, 5vh, 56px);
  }
  .cli-wedge-head-meta { flex-wrap: wrap; }
  .cli-wedge-pick { justify-content: flex-start; }
  .cli-wedge-arena {
    gap: clamp(24px, 4vh, 40px);
  }
  .cli-wedge-panel[data-mode="naive"],
  .cli-wedge-panel[data-mode="zenrows"] {
    transform: translateY(calc((1 - var(--enter, 0)) * 32px));
  }
}

@media (max-width: 600px) {
  .cli-wedge-h2 { font-size: var(--mkt-h3); }
  .cli-wedge-stamp { font-size: 12px; padding: 6px 12px; }
}

/* ── Wide-desktop tiers ─────────────────────────────────── */

@media (min-width: 1600px) {
  .cli-wedge-stage      { max-width: 1440px; }
  .cli-wedge-h2         { font-size: 60px; }
  .cli-wedge-sub        { font-size: 18px; max-width: 480px; }
  .cli-wedge-panel-body { font-size: 14px; }
  .cli-wedge-stamp      { font-size: 17px; padding: 9px 18px; }
}

@media (min-width: 1920px) {
  .cli-wedge-stage      { max-width: 1560px; }
  .cli-wedge-h2         { font-size: 72px; }
  .cli-wedge-sub        { font-size: 19px; max-width: 540px; }
  .cli-wedge-panel-body { font-size: 15px; }
  .cli-wedge-stamp      { font-size: 19px; padding: 10px 20px; }
}

@media (min-width: 2400px) {
  .cli-wedge-stage      { max-width: 1740px; }
  .cli-wedge-h2         { font-size: 86px; }
  .cli-wedge-sub        { font-size: 21px; max-width: 600px; }
  .cli-wedge-panel-body { font-size: 16.5px; }
  .cli-wedge-stamp      { font-size: 22px; padding: 11px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .cli-wedge-panel.is-shaking { animation: none; }
}

/* ──────────────────────────────────────────────────────────

/* ──────────────────────────────────────────────────────────


/* ──────────────────────────────────────────────────────────
   Act 3 — Compose the run.

   Ported 1:1 from /home Act 2 ("the pattern"): sticky 400vh
   stage with a 100vh frame split editorial-left / cards-
   track-right; track of 4 cards laid out horizontally drifts
   LEFT as the reader scrolls, so cards traverse the right
   column right → left.  Each card carries a saturated linear-
   gradient base + a blurred radial-gradient mesh on top.
─────────────────────────────────────────────────────────── */

[data-act="3"] {
  /* Reset the generic act padding; the stage owns its layout. */
  padding: 0;
  position: relative;
  z-index: 2;
  background: var(--background);
  color: var(--text-primary);
  isolation: isolate;
}

.cli-spec-stage {
  position: relative;
  /* 4 viewports of scroll room — same budget as /home Act 2. */
  min-height: 400vh;
}

.cli-spec-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
  padding: 0;
  overflow: hidden;
}

/* Left editorial column — natural top-down flow: kicker,
   H2, closer immediately below the H2 (no bottom-pin). */
.cli-spec-text {
  z-index: 2;
  max-width: 560px;
  padding-left: clamp(20px, 4vw, 48px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.cli-spec-text .act-kicker { margin: 0 0 18px; }

.cli-spec-line {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.04;
  letter-spacing: var(--tracking-dense, -0.028em);
  font-weight: 500;
  color: var(--text-primary);
  text-wrap: balance;
}

.cli-spec-cards {
  position: relative;
  height: 100%;
  overflow: hidden;
}

.cli-spec-track {
  position: absolute;
  top: 50%;
  left: clamp(16px, 2vw, 32px);
  display: flex;
  gap: clamp(24px, 3vw, 48px);
  transform: translate3d(0, -50%, 0);
  will-change: transform;
}

.cli-spec-card {
  flex-shrink: 0;
  width: clamp(260px, 26vw, 380px);
  aspect-ratio: 5 / 6;
  border-radius: var(--radius-lg, 12px);
  padding: clamp(20px, 2.4vw, 36px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  contain: paint;
}

/* Per-card linear-gradient base — saturated mid-tones so the
   surface stays in-palette even where the radials fade out. */
.cli-spec-card[data-card="1"] { background: linear-gradient(135deg, var(--zen-purple-5) 0%, var(--zen-blue-5) 100%); }
.cli-spec-card[data-card="2"] { background: linear-gradient(135deg, var(--zen-yellow-5) 0%, var(--zen-purple-5) 100%); }
.cli-spec-card[data-card="3"] { background: linear-gradient(135deg, var(--zen-cyan-5)   0%, var(--zen-green-5) 100%); }
.cli-spec-card[data-card="4"] { background: linear-gradient(135deg, var(--zen-red-5)    0%, var(--zen-orange-5) 100%); }

/* Mesh — 3 radials, blurred 36px, baseline scale(1.2).  JS
   applies scroll-linked translate/rotate so the mesh visibly
   drifts as the reader scrolls. */
.cli-spec-card .card-mesh {
  position: absolute;
  inset: 0;
  z-index: 0;
  filter: blur(36px);
  opacity: 1;
  transform: translateZ(0) scale(1.2);
  backface-visibility: hidden;
  transform-origin: center;
  will-change: transform;
}
.cli-spec-card[data-card="1"] .card-mesh {
  background:
    radial-gradient(ellipse 85% 75% at 28% 30%, var(--zen-purple-6) 0%, transparent 78%),
    radial-gradient(ellipse 85% 80% at 78% 38%, var(--zen-cyan-6)   0%, transparent 78%),
    radial-gradient(ellipse 80% 80% at 52% 80%, var(--zen-blue-6)   0%, transparent 78%);
}
.cli-spec-card[data-card="2"] .card-mesh {
  background:
    radial-gradient(ellipse 85% 75% at 25% 72%, var(--zen-purple-6) 0%, transparent 78%),
    radial-gradient(ellipse 85% 80% at 76% 30%, var(--zen-yellow-6) 0%, transparent 78%),
    radial-gradient(ellipse 80% 80% at 55% 65%, var(--zen-orange-6) 0%, transparent 78%);
}
.cli-spec-card[data-card="3"] .card-mesh {
  background:
    radial-gradient(ellipse 85% 75% at 28% 30%, var(--zen-cyan-6)   0%, transparent 78%),
    radial-gradient(ellipse 85% 80% at 76% 68%, var(--zen-green-6)  0%, transparent 78%),
    radial-gradient(ellipse 80% 80% at 52% 80%, var(--zen-purple-6) 0%, transparent 78%);
}
.cli-spec-card[data-card="4"] .card-mesh {
  background:
    radial-gradient(ellipse 85% 75% at 28% 75%, var(--zen-purple-6) 0%, transparent 78%),
    radial-gradient(ellipse 85% 80% at 75% 32%, var(--zen-red-6)    0%, transparent 78%),
    radial-gradient(ellipse 80% 80% at 55% 58%, var(--zen-orange-6) 0%, transparent 78%);
}

.cli-spec-card .setup {
  position: relative;
  z-index: 1;
  margin: 0 0 12px;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-body);
  line-height: 1.4;
  letter-spacing: var(--tracking-dense, -0.012em);
  font-weight: 400;
  color: color-mix(in srgb, #FFFFFF 72%, transparent);
}

.cli-spec-card .punchline {
  position: relative;
  z-index: 1;
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h4);
  line-height: 1.04;
  letter-spacing: var(--tracking-dense, -0.028em);
  font-weight: 500;
  color: #FFFFFF;
  text-wrap: balance;
}

/* Closer line — pinned to the BOTTOM of the editorial
   column inside the sticky frame (via margin-top: auto on
   the H2 line above it).  Sits as a quiet mono tagline
   below the H2. */
.cli-spec-closer {
  margin: clamp(28px, 4vh, 48px) 0 0;
  max-width: 560px;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body-sm);
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}

/* ── Mobile ─────────────────────────────────────────────── */

@media (max-width: 1199px) {
  /* Drop the horizontal drift — cards stack vertically and
     the frame becomes a normal-flow block.  Mesh wiggle
     still runs (JS) so the cards stay alive. */
  .cli-spec-stage   { min-height: auto; }
  .cli-spec-frame {
    position: static;
    height: auto;
    grid-template-columns: 1fr;
    row-gap: clamp(36px, 5vh, 56px);
    padding: clamp(72px, 10vh, 110px) clamp(20px, 5vw, 32px);
    overflow: visible;
  }
  .cli-spec-text { max-width: 100%; padding-left: 0; }
  .cli-spec-cards { height: auto; overflow: visible; }
  .cli-spec-track {
    position: static;
    transform: none !important;
    flex-direction: column;
    gap: clamp(16px, 2.5vh, 24px);
  }
  .cli-spec-card { width: 100%; aspect-ratio: auto; min-height: 280px; }
}

/* ── Wide-desktop tiers ─────────────────────────────────── */

@media (min-width: 1600px) {
  .cli-spec-text     { max-width: 640px; }
  .cli-spec-line     { font-size: 72px; }
  .cli-spec-card     { width: clamp(280px, 24vw, 420px); }
  .cli-spec-card .punchline { font-size: 40px; }
  .cli-spec-closer   { font-size: 16px; max-width: 800px; }
}

@media (min-width: 1920px) {
  .cli-spec-text     { max-width: 720px; }
  .cli-spec-line     { font-size: 84px; }
  .cli-spec-card     { width: clamp(320px, 22vw, 460px); }
  .cli-spec-card .punchline { font-size: 46px; }
  .cli-spec-closer   { font-size: 17px; }
}

@media (min-width: 2400px) {
  .cli-spec-text     { max-width: 820px; }
  .cli-spec-line     { font-size: 100px; }
  .cli-spec-card     { width: clamp(360px, 20vw, 520px); }
  .cli-spec-card .punchline { font-size: 52px; }
  .cli-spec-closer   { font-size: 18.5px; }
}

/* ──────────────────────────────────────────────────────────
   Act 4 — Bend the call.

   Saturated teal-5 brand band via bloom curtain (clip-path
   circle growing from top-right corner) + spotlight cards
   that crossfade through the CLI's adaptive flags.  Per
   DESIGN.md Act 4 controls cadence: brand band, right-
   aligned editorial, per-beat visuals.

   Topology break vs Act 3 (left-aligned dark editorial +
   horizontal mesh card drift): now right-aligned editorial
   on saturated teal with spotlight crossfade.
─────────────────────────────────────────────────────────── */

[data-act="4"] {
  position: relative;
  z-index: 2;
  background: var(--background);
  min-height: 320vh;
  isolation: isolate;
  color: #1D1612;
  padding: 0;
}

.cli-tune-stage {
  position: relative;
  min-height: 320vh;
}

.cli-tune-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
  display: grid;
  place-items: stretch;
}

/* Bloom curtain — teal-5 hardcoded per saturated-band rule.
   Clip-path circle at top-right (70%, 0%) grows from 0% to
   ~140% over the first ~12% of the sticky range. */
.cli-tune-curtain {
  position: absolute;
  inset: 0;
  background: #7ADAE6;
  clip-path: circle(calc(var(--bloom, 0) * 1%) at 70% 0%);
  pointer-events: none;
  z-index: 0;
}

.cli-tune-content {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(96px, 13vh, 140px) clamp(20px, 5vw, 80px) clamp(56px, 8vh, 96px);
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.8fr);
  grid-template-areas: "spotlight head";
  column-gap: clamp(40px, 5vw, 96px);
  height: 100%;
}

/* Head — top-right corner.  Right-aligned editorial; align-
   self: start pins it to the top of the frame so the
   diagonal whitespace runs between the head (top-right) and
   the spotlight cards (bottom-left). */
.cli-tune-head {
  grid-area: head;
  text-align: right;
  margin-left: auto;
  max-width: 480px;
  align-self: start;
}


.cli-tune-h2 {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-hero);
  line-height: 1.00;
  letter-spacing: var(--tracking-dense, -0.032em);
  font-weight: 500;
  color: #1D1612;
  text-wrap: balance;
  max-width: 14ch;
  margin-left: auto;
}

.cli-tune-h2 + .cli-tune-sub { margin-top: clamp(14px, 1.8vh, 22px); }
.cli-tune-sub {
  margin: 0 0 0 auto;
  max-width: 400px;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.5;
  color: rgba(29, 22, 18, 0.84);
  text-wrap: balance;
}

/* Spotlight cards — left column anchored to the BOTTOM
   (align-self: end).  All cards stacked grid-area 1/1; only
   data-active visible.  Crossfade per scroll beat.  The
   bottom anchor + the head's top-right pin creates the
   diagonal editorial break across the frame. */
.cli-tune-spotlight {
  grid-area: spotlight;
  position: relative;
  display: grid;
  align-self: end;
  min-height: clamp(320px, 46vh, 480px);
}

.cli-tune-card {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(10px, 1.4vh, 16px);
  /* Uniform min-height across all 4 cards so the bottom
     edge (where label + punchline sit) never shifts when
     scenarios swap.  Visual at the top, text anchored at
     the bottom via margin-top: auto on the label. */
  min-height: clamp(280px, 38vh, 360px);
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 540ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 540ms cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
  max-width: 620px;
}
.cli-tune-card[data-active="true"] {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Push label + punchline to the bottom of the card so the
   text Y position stays constant across all 4 cards. */
.cli-tune-card .cli-tune-card-label { margin-top: auto; }

.cli-tune-card-label {
  margin: 0;
  font-family: var(--font-code, monospace);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(29, 22, 18, 0.62);
}

.cli-tune-card-line {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h4);
  line-height: 1.04;
  letter-spacing: var(--tracking-dense, -0.022em);
  font-weight: 500;
  color: #1D1612;
  text-wrap: balance;
}

/* ── Per-flag visual posters ──────────────────────────────
   Each visual is an editorial typographic moment — a single
   big mono / display element framed by a small uppercase
   eyebrow on top and a foot caption underneath.  The
   animation is one delightful CSS-only motion per poster,
   looping continuously.  No diagrams, no UI mocks. */

.cli-tune-vis {
  width: 100%;
  max-width: 520px;
  margin-bottom: clamp(20px, 3vh, 32px);
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(10px, 1.4vh, 16px);
}

.eyebrow,
.vis-poster-foot {
  font-family: var(--font-code, monospace);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: color-mix(in srgb, #1D1612 64%, transparent);
}
.vis-poster-foot {
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 500;
  color: color-mix(in srgb, #1D1612 72%, transparent);
}

/* ─────────────────────────────────────────────────────────
   01 · --js — "Hello, world." typewriter.

   Big mono display line types out char-by-char via a width
   animation (steps), with a blinking caret beside it.  Loop
   4.4s: 0-3s typing + holding, 3-4.4s wipe + reset.
─────────────────────────────────────────────────────────── */
.vis-js-line {
  margin: 0;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-h3);
  line-height: 1.05;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: #1D1612;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  position: relative;
  overflow: hidden;
}
.vis-js-type {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  max-width: 100%;
  width: 0;
  animation: vis-js-type 4.4s steps(13, end) infinite;
}
@keyframes vis-js-type {
  0%   { width: 0; }
  60%  { width: 13ch; }
  86%  { width: 13ch; }
  92%  { width: 0; }
  100% { width: 0; }
}
.vis-js-caret {
  display: inline-block;
  color: var(--zen-purple-7, #7C4FE8);
  font-weight: 700;
  animation: vis-js-blink 0.7s steps(1, end) infinite;
}
@keyframes vis-js-blink {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* keep legacy class blocks unused so old rule stops painting */
.vis-js-window {
  width: 100%;
  border: 1px solid color-mix(in srgb, #1D1612 22%, transparent);
  border-radius: var(--radius-display, 20px);
  overflow: hidden;
  background: color-mix(in srgb, #FFFFFF 22%, transparent);
}
.vis-js-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid color-mix(in srgb, #1D1612 18%, transparent);
  background: color-mix(in srgb, #FFFFFF 14%, transparent);
}
.vis-js-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: color-mix(in srgb, #1D1612 28%, transparent);
}
.vis-js-dot:nth-child(1) { background: color-mix(in srgb, #F36A6A 80%, transparent); }
.vis-js-dot:nth-child(2) { background: color-mix(in srgb, #F5C56A 80%, transparent); }
.vis-js-dot:nth-child(3) { background: color-mix(in srgb, #6BD9A1 80%, transparent); }
.vis-js-url {
  margin-left: 8px;
  font-family: var(--font-code, monospace);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: color-mix(in srgb, #1D1612 60%, transparent);
}

.vis-js-body {
  position: relative;
  padding: 18px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 28px 64px 18px;
  grid-template-areas:
    "header header"
    "a      b"
    "row    row";
  gap: 12px;
  min-height: 160px;
}

/* Empty state — `<div id="root"></div>` text centered on
   first beat, fades out as tiles arrive. */
.vis-js-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body-xs);
  color: color-mix(in srgb, #1D1612 56%, transparent);
  letter-spacing: -0.005em;
  animation: vis-js-empty 5.2s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-js-empty {
  0%, 22%   { opacity: 1; }
  35%, 80%  { opacity: 0; }
  92%, 100% { opacity: 1; }
}

.vis-js-tile {
  background: #7C4FE8;
  border-radius: 6px;
  opacity: 0;
  transform: scale(0.92) translateY(6px);
  animation: vis-js-pop 5.2s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
.vis-js-tile--header { grid-area: header; }
.vis-js-tile--a      { grid-area: a; }
.vis-js-tile--b      { grid-area: b; background: color-mix(in srgb, #1D1612 32%, transparent); }
.vis-js-tile--row    { grid-area: row; }

.vis-js-tile--header { animation-delay: 1100ms; }
.vis-js-tile--a      { animation-delay: 1320ms; }
.vis-js-tile--b      { animation-delay: 1480ms; }
.vis-js-tile--row    { animation-delay: 1640ms; background: color-mix(in srgb, #1D1612 24%, transparent); }

@keyframes vis-js-pop {
  0%, 18%   { opacity: 0; transform: scale(0.92) translateY(6px); }
  30%, 78%  { opacity: 1; transform: scale(1) translateY(0); }
  92%, 100% { opacity: 0; transform: scale(0.92) translateY(6px); }
}


/* ─────────────────────────────────────────────────────────
   02 · --premium — IP brushstroke.

   Big mono IP "217.118.84.99" with a purple-7 brushstroke
   that draws across it on loop (background-size 0% → 100%
   on the text's underline track).  Loop 4s.
─────────────────────────────────────────────────────────── */
.vis-prem-ip {
  margin: 0;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-h3);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: #1D1612;
}
.vis-prem-ip-text {
  display: inline;
  background-image: linear-gradient(var(--zen-purple-7, #7C4FE8), var(--zen-purple-7, #7C4FE8));
  background-repeat: no-repeat;
  background-position: 0 88%;
  background-size: 0% 4px;
  padding: 0 2px;
  animation: vis-prem-stroke 4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-prem-stroke {
  0%, 10%   { background-size: 0% 4px; }
  55%       { background-size: 100% 4px; }
  90%       { background-size: 100% 4px; }
  100%      { background-size: 0% 4px; }
}

/* ─────────────────────────────────────────────────────────
   03 · --geo gb — Huge GB stamp.

   Display-size "GB" with a pin ▾ dropping onto it from
   above.  Eyebrow + coordinates frame the moment.  Loop
   4s.  Reads like a passport stamp landing.
─────────────────────────────────────────────────────────── */
.vis-geo-stamp {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 14px;
}
.vis-geo-pin {
  position: absolute;
  left: 16px;
  top: -10px;
  transform: translateY(-20px);
  font-size: var(--mkt-h4);
  color: var(--zen-purple-7, #7C4FE8);
  opacity: 0;
  animation: vis-geo-pin 4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-geo-pin {
  0%, 25%  { opacity: 0; transform: translateY(-20px); }
  45%      { opacity: 1; transform: translateY(0); }
  55%      { opacity: 1; transform: translateY(-4px); }
  65%, 88% { opacity: 1; transform: translateY(0); }
  100%     { opacity: 0; transform: translateY(-20px); }
}
.vis-geo-mark {
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: clamp(72px, 9vw, 132px);
  line-height: 0.9;
  letter-spacing: var(--tracking-dense, -0.034em);
  font-weight: 500;
  color: #1D1612;
  opacity: 0;
  transform: scale(0.92);
  animation: vis-geo-stamp 4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-geo-stamp {
  0%, 35%   { opacity: 0; transform: scale(0.92); }
  55%       { opacity: 1; transform: scale(1); }
  88%       { opacity: 1; transform: scale(1); }
  100%      { opacity: 0; transform: scale(0.92); }
}

/* ─────────────────────────────────────────────────────────
   04 · --session jar — Hash + ticking counter.

   Big mono token hash sits editorial; below it a counter
   ticks from 01 → 17 reqs showing requests reusing the
   session.  Loop 4.4s.  The counter increments via JS
   (initCounters) keyed off the same loop interval.
─────────────────────────────────────────────────────────── */
.vis-sess-hash {
  margin: 0;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-h3);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #1D1612;
}
.vis-sess-hash-text {
  display: inline-block;
  position: relative;
  padding-right: 8px;
  animation: vis-sess-hashIn 4.4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-sess-hashIn {
  0%, 8%   { opacity: 0; transform: translateY(4px); letter-spacing: 0.12em; }
  28%, 90% { opacity: 1; transform: translateY(0); letter-spacing: 0.02em; }
  100%     { opacity: 0; transform: translateY(4px); }
}

.vis-sess-count {
  display: inline-block;
  min-width: 1.6ch;
  font-variant-numeric: tabular-nums;
  color: var(--zen-purple-7, #7C4FE8);
  font-weight: 700;
  animation: vis-sess-countIn 4.4s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
@keyframes vis-sess-countIn {
  0%, 30%  { opacity: 0.4; color: color-mix(in srgb, #1D1612 50%, transparent); }
  60%      { opacity: 1; color: var(--zen-purple-7, #7C4FE8); }
  90%      { opacity: 1; color: var(--zen-purple-7, #7C4FE8); }
  100%     { opacity: 0.4; }
}

@media (max-width: 1023px) {
  [data-act="4"] { min-height: auto; }
  .cli-tune-stage { min-height: auto; }
  .cli-tune-frame {
    position: static;
    height: auto;
    overflow: visible;
  }
  /* On mobile, paint the teal flat — clip-path circle off. */
  .cli-tune-curtain { clip-path: none; }
  .cli-tune-content {
    grid-template-columns: 1fr;
    grid-template-areas:
      "head"
      "spotlight";
    padding: clamp(72px, 10vh, 110px) clamp(20px, 5vw, 32px);
    row-gap: clamp(28px, 4vh, 48px);
    height: auto;
  }
  .cli-tune-head { text-align: left; margin-left: 0; }
  .cli-tune-h2,
  .cli-tune-sub { margin-left: 0; }
  .cli-tune-spotlight {
    display: flex;
    flex-direction: column;
    gap: clamp(28px, 4vh, 40px);
    min-height: 0;
  }
  .cli-tune-card {
    grid-area: auto;
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }
}

@media (max-width: 600px) {
  
  .cli-tune-card-line { font-size: var(--mkt-h4); }
  .cli-tune-card-cmd  { white-space: normal; }
}

/* ── Wide-desktop tiers ─────────────────────────────────── */

@media (min-width: 1600px) {
  .cli-tune-content   { max-width: 1440px; }
  
  .cli-tune-card-line { font-size: 40px; }
  .cli-tune-sub       { font-size: 19px; max-width: 460px; }
  .cli-tune-card-sub  { font-size: 19px; max-width: 46ch; }
  .cli-tune-card-cmd  { font-size: 16px; }
}

@media (min-width: 1920px) {
  .cli-tune-content   { max-width: 1560px; }
  
  .cli-tune-card-line { font-size: 46px; }
  .cli-tune-sub       { font-size: 20px; max-width: 500px; }
  .cli-tune-card-sub  { font-size: 20px; max-width: 48ch; }
  .cli-tune-card-cmd  { font-size: 17px; }
}

@media (min-width: 2400px) {
  .cli-tune-content   { max-width: 1740px; }
  
  .cli-tune-card-line { font-size: 54px; }
  .cli-tune-sub       { font-size: 22px; max-width: 560px; }
  .cli-tune-card-sub  { font-size: 22px; max-width: 50ch; }
  .cli-tune-card-cmd  { font-size: 18.5px; }
}

/* ── Topbar adaptation while Act 4 covers viewport top ──── */

/* Hardcoded #1D1612 so chrome reads dark on teal in BOTH tech + BU. */

/* ──────────────────────────────────────────────────────────
   Act 5 — Closer with center bloom.

   Per DESIGN.md `closer with center bloom` pattern: single
   beat saturated purple-7 band, bloom anchored at viewport
   centre, max radius capped at ~130% so the four corners
   stay subtly dark (editorial vignette).  Topbar hides via
   body.is-closing while the closer holds the viewport.

   Single-viewport section, IO triggers .is-revealed once →
   curtain blooms in + H2 words pop in cascade.
─────────────────────────────────────────────────────────── */

[data-act="5"] {
  position: relative;
  z-index: 2;
  background: var(--background);
  min-height: 100vh;
  isolation: isolate;
  overflow: hidden;
  padding: 0;
  color: #FFFFFF;
}

.cli-end-frame {
  position: relative;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: clamp(96px, 14vh, 160px) clamp(20px, 5vw, 80px);
}

/* Center bloom — purple-7 hardcoded.  IO adds .is-revealed
   on first entry; clip-path circle expands from 0% to 130%
   at viewport centre.  Past 130% the corners stay slightly
   dark — editorial vignette per the recipe. */
.cli-end-curtain {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #7C4FE8;
  clip-path: circle(0% at 50% 50%);
  pointer-events: none;
  transition: clip-path 1400ms cubic-bezier(0.22, 1, 0.36, 1);
}
[data-act="5"].is-revealed .cli-end-curtain {
  clip-path: circle(130% at 50% 50%);
}

.cli-end-content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: clamp(24px, 3.4vh, 40px);
  max-width: 880px;
  margin-right: auto;
}

[data-act="5"].is-revealed .eyebrow {
  opacity: 1;
  transform: translateY(0);
}

/* H2 — word-by-word pop reveal with the overshoot easing
   from the motion-language tier (Home closer pattern). */
.cli-end-h2 {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: clamp(56px, 8.5vw, 132px);
  line-height: 0.94;
  letter-spacing: var(--tracking-dense, -0.038em);
  font-weight: 500;
  color: #FFFFFF;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: clamp(14px, 1.6vw, 28px);
}

.cli-end-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(16px) scale(0.94);
  transition: opacity 720ms cubic-bezier(0.34, 1.56, 0.64, 1),
              transform 720ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
[data-act="5"].is-revealed .cli-end-word {
  opacity: 1;
  transform: translateY(0) scale(1);
}
[data-act="5"].is-revealed .cli-end-word[data-i="0"] { transition-delay: 700ms; }
[data-act="5"].is-revealed .cli-end-word[data-i="1"] { transition-delay: 820ms; }
[data-act="5"].is-revealed .cli-end-word[data-i="2"] { transition-delay: 940ms; }

/* Accent word — no underline brushstroke (per Pablo's
   request).  Keeping the class as a hook in case a later
   accent treatment lands. */

/* Install cmd — no container, just text right-aligned with
   the rest of the content. */
.cli-end-cmd {
  display: inline-block;
  font-family: var(--font-code, monospace);
  font-size: var(--mkt-body);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: #FFFFFF;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 720ms cubic-bezier(0.22, 1, 0.36, 1) 1500ms,
              transform 720ms cubic-bezier(0.22, 1, 0.36, 1) 1500ms;
}
[data-act="5"].is-revealed .cli-end-cmd {
  opacity: 1;
  transform: translateY(0);
}

/* Layout + tag styles come from .cta-stack + .cta-stack-tag
   in components.css.  Only the reveal hook + on-purple tag
   color are page-specific. */
.cli-end-cta {
  gap: 12px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 720ms cubic-bezier(0.22, 1, 0.36, 1) 1700ms,
              transform 720ms cubic-bezier(0.22, 1, 0.36, 1) 1700ms;
}
[data-act="5"].is-revealed .cli-end-cta {
  opacity: 1;
  transform: translateY(0);
}

/* CTA pill — same teal-5 marketing button.  On the purple-7
   band the teal pops nicely; no swap needed. */

.cli-end-tag {
  color: color-mix(in srgb, #FFFFFF 84%, transparent);
}

/* Topbar — hides while the closer dominates the viewport.
   JS toggles body.is-closing via IO/scroll listener; CSS
   transitions opacity + translateY for a smooth lift-off. */
body.is-closing .topbar {
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
}
.topbar {
  transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ── Mobile ─────────────────────────────────────────────── */

@media (max-width: 600px) {
  
}

/* ── Wide-desktop tiers ─────────────────────────────────── */

@media (min-width: 1600px) {
  
  .cli-end-cmd { font-size: 19px; }
}

@media (min-width: 1920px) {
  
  .cli-end-cmd { font-size: 20px; }
}

@media (min-width: 2400px) {
  
  .cli-end-cmd { font-size: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .cli-end-curtain { transition: none; clip-path: circle(130% at 50% 50%); }
  .eyebrow,
  .cli-end-word,
  .cli-end-cmd,
  .cli-end-cta { opacity: 1; transform: none; transition: none; }
}

/* ══════════════════════════════════════════════════════════
   Audience switcher + BU light theme. */
[data-audience-tech][hidden],
[data-audience-bu][hidden] { display: none !important; }

.audience-switch {
  position: fixed;
  top: 50%;
  right: 16px;
  z-index: 250;
  display: grid;
  grid-template-rows: 1fr 1fr;
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  overflow: hidden;
  background: color-mix(in srgb, var(--background) 88%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  will-change: transform;
  transform: translateY(-50%) translateZ(0);
  backface-visibility: hidden;
}
.audience-switch::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 50%;
  background: #7C4FE8;
  z-index: 0;
  transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
body[data-audience="bu"] .audience-switch::before {
  transform: translateY(100%);
}
.audience-switch-btn {
  position: relative;
  z-index: 1;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  padding: 16px 11px;
  cursor: pointer;
  font-family: var(--font-code, var(--font-mono), "IBM Plex Mono", monospace);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  transition: color 220ms cubic-bezier(0.22, 1, 0.36, 1);
  writing-mode: vertical-rl;
}
.audience-switch-btn[aria-pressed="true"] { color: #FFFFFF; }

@media (max-width: 720px) {
  .audience-switch {
    top: auto;
    bottom: 20px;
    right: 16px;
    transform: translateZ(0);
    grid-template-rows: none;
    grid-template-columns: 1fr 1fr;
  }
  .audience-switch::before {
    top: 0; left: 0; right: auto; bottom: auto;
    width: 50%; height: 100%;
  }
  body[data-audience="bu"] .audience-switch::before { transform: translateX(100%); }
  .audience-switch-btn {
    writing-mode: horizontal-tb;
    padding: 10px 18px;
    font-size: 10px;
  }
}

/* ── BU light mode body + chrome ── */
html:not(.dark) body {
  background: var(--background);
  color: var(--text-primary);
}
html:not(.dark) .audience-switch {
  background: var(--zen-gray-1);
  border-color: var(--border-default);
  box-shadow: 0 12px 28px -12px rgba(29, 22, 18, 0.18);
}

/* Mq12 on every heading in BU. */
html:not(.dark) .cli-hero-h1,
html:not(.dark) .cli-wedge-h2,
html:not(.dark) .cli-spec-line,
html:not(.dark) .cli-tune-h2,
html:not(.dark) .cli-end-h2 {
  font-family: 'Mq12', system-ui, sans-serif;
  font-weight: 500;
}

/* Topbar inversion — yields to body.is-on-teal (Act 4 band). */

/* Nav popover light variant. */
html:not(.dark) .nav-dropdown {
  background: #FFFFFF;
  border-color: var(--border-subtle);
  box-shadow: 0 28px 56px -20px rgba(29, 22, 18, 0.18);
}
html:not(.dark) .nav-mega-item > a { color: var(--text-secondary); }
html:not(.dark) .nav-mega-item > a:hover,
html:not(.dark) .nav-mega-item > a:focus-visible {
  background: var(--sunken-hover);
  color: var(--text-primary);
}
html:not(.dark) .nav-mega-item.is-active > a {
  background: var(--sunken-active);
  color: var(--text-primary);
}
html:not(.dark) .nav-mega-item > span { color: var(--text-tertiary); }
html:not(.dark) .nav-mega-item.is-active > span {
  background: var(--sunken-active);
  color: var(--text-secondary);
}
html:not(.dark) .nav-mega-group-label { color: var(--text-tertiary); }
html:not(.dark) .nav-mega-headline {
  background-color: #1D1612;
  border-color: rgba(29, 22, 18, 0.18);
}
html:not(.dark) .nav-mega-preview-desc { color: var(--text-secondary); }
