/*
 * /compare/firecrawl-alternative — Act 1 only (v4).
 *
 * Hero: compact editorial stack + a live demo card.  The card
 * is scroll-driven on desktop: the section pins sticky for
 * ~240vh while --state walks 0→2 with the scroll position, so
 * the user advances the demo by scrolling.  Below 1100px the
 * card falls back to a timer loop (JS handles the swap).
 *
 * Card sized for breathing room: wider container + taller pane
 * so the markdown / Cloudflare wall / JSON each have space to
 * read at a glance.
 */

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

main {
  width: 100%;
  max-width: 100vw;
  position: relative;
}

/* Cursor portal scope — only when the demo is showing the
   Zenrows state (state=2).  In Firecrawl states the native
   pointer is fine; the SVG portal only kicks in over the
   protected-page response. */
.fa-demo[data-state="2"] { cursor: pointer; }
.fa-demo[data-state="2"] * { cursor: pointer; }

/* ══════════════════════════════════════════════════════════
   Act 1 — hero-demo (sticky scroll-driven on desktop).
══════════════════════════════════════════════════════════ */

.fa-act-1 {
  position: relative;
  background: var(--background);
  /* Sticky budget: ~240vh gives 3 states × ~80vh each — wide
     enough that a typical trackpad flick advances exactly one
     state instead of skipping two. */
  min-height: 240vh;
}

.fa-act-1-frame {
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Hero at top, demo card at bottom-right. */
  justify-content: space-between;
  align-items: stretch;
  gap: clamp(20px, 3vh, 40px);
  /* Top padding clears the 72px fixed topbar + adds breathing.
     Bottom padding gives the demo card room to float above
     the act's bottom edge. */
  padding: clamp(104px, 14vh, 152px) clamp(20px, 6vw, 96px) clamp(64px, 8vh, 104px);
  max-width: 1240px;
  margin: 0 auto;
}

@media (min-width: 1600px) { .fa-act-1-frame { max-width: 1400px; } }
@media (min-width: 1920px) { .fa-act-1-frame { max-width: 1560px; } }
@media (min-width: 2400px) { .fa-act-1-frame { max-width: 1760px; } }

/* Short-viewport tier (laptops once browser chrome eats
   ~120-160px of the panel).  Compress padding so the whole
   act still fits in 100vh, but leave real breathing on both
   ends so the H1 doesn't crowd the topbar. */
@media (max-height: 820px) {
  .fa-act-1-frame {
    padding-top: clamp(88px, 11vh, 112px);
    padding-bottom: clamp(48px, 6vh, 72px);
    gap: clamp(14px, 1.8vh, 22px);
  }
}

.fa-hero { align-self: flex-start; }

/* ── Editorial stack — tight, synthetic. */

.fa-hero { width: 100%; }

.fa-hero-kicker { margin: 0 0 clamp(14px, 1.6vw, 22px); }

.fa-hero-h1 {
  margin: 0;
  font-family: var(--font-base);
  font-weight: 500;
  letter-spacing: -0.026em;
  line-height: 1.06;
  font-size: var(--mkt-hero-xl);
  color: var(--text-primary);
  /* No per-element max-width — the H1 fills the full frame
     width.  text-wrap: balance + the frame's max-width
     (1240/1400/1560/1760) shape the line wrap naturally. */
  text-wrap: balance;
}

@media (min-width: 1600px) {  }
@media (min-width: 1920px) {  }
@media (min-width: 2400px) {  }

/* Short viewports — smaller H1 so the card has room. */
@media (max-height: 820px) {
  .fa-hero-h1 { font-size: var(--mkt-h2); line-height: 1.08; }
}

.fa-hero-sub {
  margin: clamp(14px, 1.6vw, 22px) 0 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.5;
  color: var(--text-secondary);
  max-width: 56ch;
}

@media (min-width: 1920px) { .fa-hero-sub { font-size: 18px; } }

/* ══════════════════════════════════════════════════════════
   Demo card — wider + taller, scroll-driven.
══════════════════════════════════════════════════════════ */

/* Wrap groups the demo card with the Firecrawl flame so the
   flame can sit absolutely above the card without being clipped
   by the card's overflow:hidden, and so both right-align as a
   single unit. */
.fa-demo-wrap {
  position: relative;
  width: min(100%, 920px);
  align-self: flex-end;
}

@media (min-width: 1600px) { .fa-demo-wrap { width: min(100%, 1040px); } }
@media (min-width: 1920px) { .fa-demo-wrap { width: min(100%, 1160px); } }
@media (min-width: 2400px) { .fa-demo-wrap { width: min(100%, 1320px); } }

.fa-demo {
  --bar-h: clamp(52px, 5.6vh, 62px);
  /* Pane height covers: artifact (markdown / wall / json),
     status pill, internal gap, padding-top, and padding-bottom
     (which reserves space for progress ticks + scroll hint).
     Conservative max so wall content never overflows. */
  --pane-h: clamp(340px, 38vh, 460px);
  position: relative;
  width: 100%;
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  transition: border-color 320ms ease;
}

@media (min-width: 1600px) { .fa-demo { --pane-h: clamp(380px, 42vh, 500px); } }
@media (min-width: 1920px) { .fa-demo { --pane-h: clamp(420px, 44vh, 540px); } }
@media (min-width: 2400px) { .fa-demo { --pane-h: clamp(480px, 46vh, 620px); --bar-h: 68px; } }

/* Short viewports — pane still tall enough for the wall to
   fit without bleeding into the progress-tick row. */
@media (max-height: 820px) {
  .fa-demo {
    --bar-h: 50px;
    --pane-h: clamp(280px, 34vh, 340px);
  }
}

/* No hover-border effect — keeps the card calm, the only
   interactive feedback is the cursor portal on state=2. */

/* ── Top bar.

   Two flavours stacked in the markup; state toggles which one
   is visible:
     .fa-demo-bar--curl  (default — states 0 and 1, Firecrawl)
     .fa-demo-bar--mesh  (state 2, Zenrows — MCP/CLI mesh
                          background with drifting colour bubbles)
   Snap swap via display:none/flex.  No transition between
   bars; the state pane crossfade carries the continuity. */

.fa-demo-bar {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 24px);
  padding: 0 clamp(18px, 2vw, 26px);
  height: var(--bar-h);
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-xs);
}

.fa-demo-bar--mesh { display: none; }
.fa-demo[data-state="2"] .fa-demo-bar--curl { display: none; }
.fa-demo[data-state="2"] .fa-demo-bar--mesh { display: flex; }

.fa-demo-bar-dots {
  display: inline-flex;
  gap: 6px;
  flex-shrink: 0;
}

.fa-demo-bar-dots span {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--border);
}

.fa-demo-bar-url {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

.fa-demo-bar-method { color: var(--text-tertiary); flex-shrink: 0; }

.fa-demo-bar-host {
  color: var(--text-primary);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color 480ms ease;
}

.fa-demo-bar-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  background: #7C4FE8;
  vertical-align: -2px;
  flex-shrink: 0;
  animation: fa-demo-caret 1.05s steps(1) infinite;
}

@keyframes fa-demo-caret {
  0%, 50%   { opacity: 1; }
  51%, 100% { opacity: 0; }
}

.fa-demo-bar-actor {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--border-subtle);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  flex-shrink: 0;
  transition:
    color 360ms ease,
    border-color 360ms ease,
    background-color 360ms ease;
}

.fa-demo-bar-actor-via { opacity: 0.6; }

.fa-demo-bar-actor-name { font-weight: 700; }

/* Mesh bar — copied verbatim from /mcp .mc-convo-bar.
   Linear gradient base + 4 drifting blurred bubbles on
   independent loops (coprime durations so they never sync).
   Same vocabulary as MCP/CLI for visual continuity across
   spokes. */

.fa-demo-bar--mesh {
  position: relative;
  align-items: center;
  gap: 8px;
  padding: 0 18px;
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.78);
  overflow: hidden;
  isolation: isolate;
}

.fa-demo-mesh-bg {
  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%
  );
}

.fa-demo-mesh-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;
}

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

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

.fa-demo-bar--mesh > *:not(.fa-demo-mesh-bg) {
  position: relative;
  z-index: 1;
}

.fa-demo-mesh-dot {
  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;
}

.fa-demo-mesh-name {
  margin-left: 8px;
  color: #FFFFFF;
  font-weight: 600;
}

.fa-demo-mesh-arrow {
  color: rgba(255, 255, 255, 0.55);
  margin: 0 4px;
}

.fa-demo-mesh-status {
  margin-left: auto;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(122, 218, 230, 0.32);
  border: 1px solid rgba(122, 218, 230, 0.65);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #FFFFFF;
  font-weight: 600;
}

/* ── Pane — stacked states, crossfade. */

.fa-demo-pane {
  position: relative;
  height: var(--pane-h);
  overflow: hidden;
}

.fa-demo-state {
  position: absolute;
  inset: 0;
  /* Generous bottom padding so the artifact has real breathing
     room above the progress ticks + status pill row. */
  padding:
    clamp(24px, 2.6vw, 36px)
    clamp(22px, 2.4vw, 32px)
    clamp(88px, 8.4vw, 116px);
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.6vw, 22px);
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 540ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 540ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (max-height: 820px) {
  .fa-demo-state { padding: 22px 24px 76px; gap: 12px; }
}

.fa-demo[data-state="0"] .fa-demo-state[data-fa-state="0"],
.fa-demo[data-state="1"] .fa-demo-state[data-fa-state="1"],
.fa-demo[data-state="2"] .fa-demo-state[data-fa-state="2"] {
  opacity: 1;
  transform: translateY(0);
}

/* Markdown */

.fa-demo-md {
  margin: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-sm);
  line-height: 1.7;
  color: var(--text-secondary);
  white-space: pre-wrap;
  flex: 1;
  min-width: 0;
  overflow-wrap: break-word;
}

.fa-demo-md .md-h1   { color: var(--text-primary); font-weight: 700; }
.fa-demo-md .md-meta { color: var(--text-tertiary); }

/* Cloudflare wall */

.fa-demo-wall {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 12px;
  padding: 4px 6px;
}

.fa-demo-wall-spinner {
  width: 30px;
  height: 30px;
  border: 2px solid color-mix(in srgb, var(--text-secondary) 28%, transparent);
  border-top-color: var(--text-primary);
  border-radius: 50%;
  margin-bottom: 8px;
  animation: fa-demo-wall-spin 1.1s linear infinite;
}

@keyframes fa-demo-wall-spin { to { transform: rotate(360deg); } }

.fa-demo-wall-title {
  margin: 0;
  font-family: var(--font-base);
  font-weight: 600;
  font-size: var(--mkt-body);
  color: var(--text-primary);
  letter-spacing: -0.005em;
}

.fa-demo-wall-meta {
  margin: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--text-tertiary);
}

/* JSON */

.fa-demo-json {
  margin: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-sm);
  line-height: 1.7;
  color: var(--text-secondary);
  white-space: pre;
  flex: 1;
  min-width: 0;
  overflow: auto;
}

.fa-demo-json .json-k { color: var(--text-primary); font-weight: 600; }
.fa-demo-json .json-s { color: #7ADAE6; }
.fa-demo-json .json-b { color: #7C4FE8; font-weight: 700; }

/* Status pill. */

.fa-demo-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  align-self: flex-start;
}

.fa-demo-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: currentColor;
}

.fa-demo-status--ok  { color: #6FE7B0; }
.fa-demo-status--err { color: #F47A6F; }
.fa-demo-status--zr  { color: #7C4FE8; }

/* ── Progress ticks. */

.fa-demo-progress {
  position: absolute;
  bottom: clamp(16px, 1.8vw, 22px);
  left: clamp(20px, 2.2vw, 30px);
  display: inline-flex;
  gap: 6px;
}

.fa-demo-progress-tick {
  display: inline-block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--border);
  transition: background-color 240ms ease, width 240ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fa-demo[data-state="0"] .fa-demo-progress-tick[data-tick="0"],
.fa-demo[data-state="1"] .fa-demo-progress-tick[data-tick="1"],
.fa-demo[data-state="2"] .fa-demo-progress-tick[data-tick="2"] {
  background: var(--text-primary);
  width: 32px;
}

.fa-demo[data-state="2"] .fa-demo-progress-tick[data-tick="2"] {
  background: #7C4FE8;
}

/* ── Scroll hint (subtle text-only cue when card is sticky). */

.fa-demo-scrollhint {
  position: absolute;
  bottom: clamp(16px, 1.8vw, 22px);
  right: clamp(20px, 2.2vw, 30px);
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-quaternary, var(--text-tertiary));
  opacity: 0.7;
  pointer-events: none;
  transition: opacity 360ms ease;
}

.fa-demo[data-state="2"] .fa-demo-scrollhint { opacity: 0; }

@media (max-width: 1100px) {
  /* Card is timer-driven below 1100; the scroll hint would lie. */
  .fa-demo-scrollhint { display: none; }
}

/* ══════════════════════════════════════════════════════════
   Firecrawl-style flame.

   Layered SVG (outer / mid / inner glow) anchored at the
   bottom-center of its bounding box.  Sits absolute, base
   flush with the top of the demo card.  Visible only when
   the demo is in a Firecrawl state (data-state 0 or 1);
   hides via :has() when the state flips to Zenrows.
══════════════════════════════════════════════════════════ */

.fa-flame {
  position: absolute;
  bottom: 100%;                       /* flame base = widget top */
  right: clamp(32px, 5vw, 72px);
  /* viewBox is 100x118; container aspect matches via aspect-ratio
     so the flame's painted base is flush with the container's
     bottom edge (which sits on the widget top). */
  width: clamp(56px, 7vw, 96px);
  aspect-ratio: 100 / 118;
  display: block;
  pointer-events: none;
  z-index: 1;
  /* Soft warm halo so the flame reads against dark. */
  filter: drop-shadow(0 4px 28px rgba(247, 107, 58, 0.38));
  transform-origin: 50% 100%;
  /* Mouse-react tilt — JS writes --flame-tilt on pointermove,
     lerped via rAF so the lean glides toward the cursor rather
     than snapping.  Negative values lean left, positive right. */
  transform: rotate(var(--flame-tilt, 0deg));
  transition:
    opacity 360ms ease,
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 800ms ease;
}

.fa-flame-svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

/* Each path animates independently for the alive flicker.
   transform-origin at the base keeps the flicker rooted. */
.fa-flame-outer,
.fa-flame-mid,
.fa-flame-inner {
  transform-origin: 50% 96%;
  will-change: transform, opacity;
}

.fa-flame-outer { animation: fa-flame-outer 2.4s ease-in-out infinite; }
.fa-flame-mid   { animation: fa-flame-mid 1.8s ease-in-out infinite; }
.fa-flame-inner { animation: fa-flame-inner 1.4s ease-in-out infinite; }

@keyframes fa-flame-outer {
  0%, 100% { transform: scale(1)    skewX(0deg)   translateY(0); }
  25%      { transform: scale(1.04) skewX(-1.5deg) translateY(-1px); }
  50%      { transform: scale(0.98) skewX(1deg)   translateY(0.5px); }
  75%      { transform: scale(1.03) skewX(-0.5deg) translateY(-0.5px); }
}

@keyframes fa-flame-mid {
  0%, 100% { transform: scale(1)    skewX(0deg)   translateY(0); }
  33%      { transform: scale(1.06) skewX(2deg)   translateY(-1px); }
  66%      { transform: scale(0.97) skewX(-1.5deg) translateY(0.5px); }
}

@keyframes fa-flame-inner {
  0%, 100% { transform: scale(1) translateY(0); opacity: 0.9; }
  50%      { transform: scale(1.08) translateY(-1px); opacity: 1; }
}

/* ── Embers — small glowing dots emerging from the flame tip,
   drifting upward + sideways with a slow fade.  Six instances,
   each with its own animation phase + drift so the emission
   feels natural, never synchronized. */

.fa-flame-ember {
  fill: #FFD89D;
  transform-origin: center;
  opacity: 0;
  will-change: transform, opacity;
  animation: fa-flame-ember 5s linear infinite;
}

/* Group wrapper controls the embers' collective opacity.
   SVG multiplies parent.opacity * child.opacity, so the
   transition here is independent of each ember's animated
   opacity and reads as a clean visible fade. */
.fa-flame-embers-group {
  opacity: 1;
  transition: opacity 900ms ease-out;
}

.fa-flame-ember[data-ember="0"] { --drift: -8;  fill: #FFB36B; animation-duration: 4.6s; animation-delay: 0s; }
.fa-flame-ember[data-ember="1"] { --drift: 10;  fill: #FFD89D; animation-duration: 5.4s; animation-delay: 0.8s; }
.fa-flame-ember[data-ember="2"] { --drift: -6;  fill: #F76B3A; animation-duration: 4.2s; animation-delay: 1.6s; }
.fa-flame-ember[data-ember="3"] { --drift: 4;   fill: #FFD89D; animation-duration: 5.0s; animation-delay: 2.4s; }
.fa-flame-ember[data-ember="4"] { --drift: -12; fill: #FFA34D; animation-duration: 4.8s; animation-delay: 3.2s; }
.fa-flame-ember[data-ember="5"] { --drift: 8;   fill: #FFD89D; animation-duration: 5.6s; animation-delay: 4.0s; }

@keyframes fa-flame-ember {
  0% {
    opacity: 0;
    transform: translate(0, 0) scale(0.5);
  }
  12% {
    opacity: 1;
    transform: translate(calc(var(--drift, 0) * 0.2px), -8px) scale(1);
  }
  60% {
    opacity: 0.85;
    transform: translate(calc(var(--drift, 0) * 0.7px), -40px) scale(0.85);
  }
  100% {
    opacity: 0;
    transform: translate(calc(var(--drift, 0) * 1px), -80px) scale(0.3);
  }
}

/* Container halo fade when in Zenrows state.  The paint group
   already retracts via scaleY; this kills the drop-shadow halo
   that would otherwise linger as a warm wash on dark. */
.fa-demo-wrap:has(.fa-demo[data-state="2"]) .fa-flame {
  filter: drop-shadow(0 4px 28px rgba(247, 107, 58, 0));
}

/* Reduced motion — kill flicker + ember emission, keep flame
   statically visible. */
@media (prefers-reduced-motion: reduce) {
  .fa-flame-outer,
  .fa-flame-mid,
  .fa-flame-inner,
  .fa-flame-ember { animation: none; }
  .fa-flame-ember { opacity: 0; }
}

/* ══════════════════════════════════════════════════════════
   Entry — IO-driven .is-in.
══════════════════════════════════════════════════════════ */

.fa-hero-kicker,
.fa-hero-h1,
.fa-demo {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 600ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fa-act-1.is-in .fa-hero-kicker {
  opacity: 1; transform: translateY(0);
  transition-delay: 100ms;
}
.fa-act-1.is-in .fa-hero-h1 {
  opacity: 1; transform: translateY(0);
  transition-delay: 220ms;
}
.fa-act-1.is-in .fa-demo {
  opacity: 1; transform: translateY(0);
  transition-delay: 540ms;
}

/* Paint animations.

   Two named animations toggle by switching `animation-name`
   when the state changes:
     fa-flame-ignite  scaleY 0 -> 1 (bottom-up grow)
     fa-flame-die     thin + rise + fade upward into embers

   Switching from die to ignite (Zenrows -> Firecrawl) restarts
   the ignite from its `from` keyframe = scaleY(0), so each
   Firecrawl entry re-ignites fresh from the base.

   Embers keep running through state changes — they're the
   "ascuas de arriba" that the dying flame dissolves into. */

.fa-flame-paint {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transform: scaleY(0);
}

/* FC state (0 or 1) + .is-in: ignite from base. */
.fa-act-1.is-in .fa-flame-paint {
  animation: fa-flame-ignite 1500ms cubic-bezier(0.22, 1, 0.36, 1) 200ms forwards;
}

/* ZR state (2): flame thins + rises + fades fast.  Embers keep
   drifting for 1s longer (JS toggles .is-ember-fading on the
   .fa-flame container after a setTimeout). */
.fa-demo-wrap:has(.fa-demo[data-state="2"]) .fa-flame-paint {
  animation: fa-flame-die 450ms cubic-bezier(0.55, 0, 0.85, 0.3) forwards;
}

/* Also force the mouse-tilt back to 0 when state=2 so the
   dying flame goes straight up.  JS clears --flame-tilt on
   state change too, but this is defense-in-depth. */
.fa-demo-wrap:has(.fa-demo[data-state="2"]) .fa-flame {
  --flame-tilt: 0deg;
}

@keyframes fa-flame-ignite {
  from { transform: scaleY(0); opacity: 1; }
  to   { transform: scaleY(1); opacity: 1; }
}

@keyframes fa-flame-die {
  from {
    transform: scaleY(1) scaleX(1) translateY(0);
    opacity: 1;
  }
  to {
    transform: scaleY(1.15) scaleX(0.08) translateY(-80%);
    opacity: 0;
  }
}

/* Embers — paused until .is-in fires.  Keep drifting through
   state changes until .is-ember-fading is added by JS (~1s
   after state=2 enters), at which point they fade out. */
.fa-flame-ember { animation-play-state: paused; }
.fa-act-1.is-in .fa-flame-ember { animation-play-state: running; }

/* Ember fade-out — drop the group wrapper's opacity from 1 to
   0 over 900ms.  Per-ember drift + individual opacity animations
   keep running underneath; the wrapper's opacity multiplies on
   top so the visible result is a clean fade from full to 0
   while the embers still drift in place. */
.fa-flame.is-ember-fading .fa-flame-embers-group { opacity: 0; }

/* ══════════════════════════════════════════════════════════
   Act 2 — wedge.

   Saturated purple-7 band.  Text-only editorial poster.  Two
   H2 lines placed asymmetrically — line 1 left, line 2 italic
   + warm-dark + right-aligned + indented.  Mirrored bloom
   corners (band-act recipe).  IO reveal stagger.
══════════════════════════════════════════════════════════ */

.fa-act-2 {
  position: relative;
  color: #FFFFFF;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(120px, 16vh, 200px) clamp(20px, 6vw, 96px);
}

/* Background lives on a dedicated child so the reveal can
   animate independently of the text frame.  Solid purple-7 —
   no gradient.  On entry the clip-path circle blooms from
   the center outward; direction-agnostic so the entrance
   reads the same whether the user scrolls into Act 2 from
   above or from below. */
.fa-act-2-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #7C4FE8;
  clip-path: circle(0% at 50% 50%);
  transition: clip-path 1200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fa-act-2.is-in .fa-act-2-bg {
  clip-path: circle(150% at 50% 50%);
}

.fa-act-2-frame {
  position: relative;
  z-index: 1;
  max-width: 1240px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  row-gap: clamp(48px, 10vh, 120px);
}

@media (min-width: 1600px) { .fa-act-2-frame { max-width: 1400px; } }
@media (min-width: 1920px) { .fa-act-2-frame { max-width: 1560px; } }
@media (min-width: 2400px) { .fa-act-2-frame { max-width: 1760px; } }

/* ── Eyebrow. */

.fa-act-2-kicker {
  margin: 0;
  color: rgba(255, 255, 255, 0.72);
}

/* ── H2 — display poster, two asymmetric lines. */

.fa-act-2-h2 {
  margin: 0;
  font-family: var(--font-base);
  font-weight: 500;
  letter-spacing: -0.028em;
  line-height: 1.0;
  font-size: clamp(48px, 8vw, 132px);
  color: #FFFFFF;
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 3vh, 48px);
}

@media (min-width: 1600px) { .fa-act-2-h2 { font-size: 152px; } }
@media (min-width: 1920px) { .fa-act-2-h2 { font-size: 176px; } }
@media (min-width: 2400px) { .fa-act-2-h2 { font-size: 208px; } }

.fa-act-2-line {
  display: inline-block;
  max-width: 16ch;
}

.fa-act-2-line--top {
  align-self: flex-start;
  text-align: left;
}

.fa-act-2-line--bottom {
  align-self: flex-end;
  text-align: right;
  margin-left: clamp(40px, 10vw, 200px);
}

.fa-act-2-line--bottom em {
  font-style: normal;
  font-weight: 500;
  color: #1D1612;
}

/* ── Sub — mono caps, bottom-right corner editorial. */

.fa-act-2-sub {
  margin: 0;
  align-self: end;
  justify-self: end;
  max-width: 38ch;
  text-align: right;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.78);
}

.fa-act-2-sub-mark {
  display: block;
  font-weight: 700;
  color: #FFFFFF;
  margin-bottom: 6px;
}

/* ── Entry — IO reveal with stagger. */

.fa-act-2-kicker,
.fa-act-2-line,
.fa-act-2-sub {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Text reveals early during the bloom — content arrives fast
   (kicker at ~200ms after bloom starts), H2 cascades quickly. */
.fa-act-2.is-in .fa-act-2-kicker {
  opacity: 1; transform: translateY(0);
  transition-delay: 180ms;
}
.fa-act-2.is-in .fa-act-2-line--top {
  opacity: 1; transform: translateY(0);
  transition-delay: 320ms;
}
.fa-act-2.is-in .fa-act-2-line--bottom {
  opacity: 1; transform: translateY(0);
  transition-delay: 500ms;
}
.fa-act-2.is-in .fa-act-2-sub {
  opacity: 1; transform: translateY(0);
  transition-delay: 720ms;
}

/* ── Mobile — keep the asymmetry but compress the indents
   so line 2 doesn't push off-screen. */
@media (max-width: 720px) {
  .fa-act-2 { padding: clamp(80px, 12vh, 140px) 20px; }
  .fa-act-2-h2 { font-size: clamp(40px, 12vw, 64px); gap: 18px; }
  .fa-act-2-line--bottom { margin-left: clamp(20px, 6vw, 40px); }
  .fa-act-2-sub { font-size: 11px; max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fa-act-2-bg {
    clip-path: circle(150% at 50% 50%);
    transition: none;
  }
  .fa-act-2-kicker,
  .fa-act-2-line,
  .fa-act-2-sub {
    opacity: 1; transform: none; transition: none;
  }
}

/* ══════════════════════════════════════════════════════════
   Act 3 — pick-by-job.

   Saturated teal-5 band (rhythm break from Act 2 purple-7).
   Brief Key message verbatim, split across two columns.
   Interactive weight: cursor X controls --pick-t (0..1) which
   shifts opacity + scale of each column inversely and slides
   a horizontal knob along the axis at the bottom.  Idle knob
   pulses softly; mouse takes control on hover.
══════════════════════════════════════════════════════════ */

.fa-act-3 {
  position: relative;
  color: #1D1612;                    /* warm-dark text on teal */
  isolation: isolate;
  overflow: hidden;
  padding: clamp(120px, 16vh, 200px) clamp(20px, 6vw, 96px);
}

/* ──────────────────────────────────────────────────────────
   Topbar adaptation on the teal Act 3.
   body.is-on-teal is toggled by the JS watcher when .fa-act-3
   covers the topbar slot.  Flips the chrome to dark-on-teal so
   it stays legible.  Same recipe as /workflows/serp-monitoring. */

/* Teal BG with the same center-bloom reveal mechanic as Act 2. */
.fa-act-3-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #7ADAE6;               /* teal-5 solid */
  clip-path: circle(0% at 50% 50%);
  transition: clip-path 1200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fa-act-3.is-in .fa-act-3-bg {
  clip-path: circle(150% at 50% 50%);
}

.fa-act-3-frame {
  position: relative;
  z-index: 1;
  max-width: 1240px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(48px, 8vh, 100px);
}

@media (min-width: 1600px) { .fa-act-3-frame { max-width: 1400px; } }
@media (min-width: 1920px) { .fa-act-3-frame { max-width: 1560px; } }
@media (min-width: 2400px) { .fa-act-3-frame { max-width: 1760px; } }

/* ── Head — kicker + H2, centered editorial. */

.fa-act-3-head {
  text-align: center;
  margin: 0 auto;
  /* No max-width — the head fills the frame width; H2 line
     wrap is shaped by text-wrap: balance + the frame's own
     max-width (1240/1400/1560/1760 across breakpoints).
     Reason: `max-width: Nch` on this wrapper resolved against
     its 16px font-size, capping it ~Nch*8px and crushing the
     huge H2 into 5+ narrow lines. */
}

.fa-act-3-h2 { text-wrap: balance; }

.fa-act-3-kicker {
  margin: 0 0 clamp(14px, 1.6vw, 22px);
  color: rgba(29, 22, 18, 0.6);
}

.fa-act-3-h2 {
  margin: 0;
  font-family: var(--font-base);
  font-weight: 500;
  letter-spacing: -0.024em;
  line-height: 1.04;
  font-size: var(--mkt-hero);
  color: #1D1612;
}

@media (min-width: 1600px) {  }
@media (min-width: 1920px) {  }
@media (min-width: 2400px) {  }

/* ── Pick — the interactive 2-column with axis below.

   --pick-t controls everything mouse-driven.  Default 0.5
   (centered).  Mouse over the .fa-pick area: target value
   maps to 0..1 (cursor X / area width), lerp-smoothed in JS.
   Pointer leave → returns to 0.5. */

.fa-pick {
  --pick-t: 0.5;
  position: relative;
}

.fa-pick-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 120px);
  align-items: start;
}

@media (max-width: 720px) {
  .fa-pick-row { grid-template-columns: 1fr; gap: 32px; }
}

/* Outer wrapper owns the entry reveal (opacity 0→1 + translate).
   Inner owns the mouse-driven weighting (opacity + scale based
   on --pick-t).  Splitting them means the entry transition
   doesn't fight the JS lerp — mouse moves update inner with
   no transition, JS lerps --pick-t smoothly. */

.fa-pick-side--fc { text-align: left; }
.fa-pick-side--zr { text-align: right; }

.fa-pick-side-inner {
  /* No transition — JS lerp on --pick-t IS the smoothing.
     Opacity range 0.15..1.0 so the off side fades much softer
     when the knob is fully on the other side. */
}

.fa-pick-side--fc .fa-pick-side-inner {
  opacity: calc(0.15 + (1 - var(--pick-t)) * 0.85);
  transform: scale(calc(0.94 + (1 - var(--pick-t)) * 0.08));
  transform-origin: top left;
}

.fa-pick-side--zr .fa-pick-side-inner {
  opacity: calc(0.15 + var(--pick-t) * 0.85);
  transform: scale(calc(0.94 + var(--pick-t) * 0.08));
  transform-origin: top right;
}

@media (max-width: 720px) {
  /* Mobile: text-align both columns to the start (no mirroring),
     but keep the --pick-t weighting active so the tap pills below
     still produce a visible focus on the chosen side. */
  .fa-pick-side { text-align: left !important; }
  .fa-pick-side--zr .fa-pick-side-inner { transform-origin: top left; }
}

.fa-pick-mark {
  margin: 0 0 clamp(12px, 1.4vw, 20px);
  font-family: var(--font-base);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: var(--mkt-h2);
  color: #1D1612;
}

@media (min-width: 1600px) { .fa-pick-mark { font-size: 64px; } }
@media (min-width: 1920px) { .fa-pick-mark { font-size: 76px; } }

/* Zenrows logo (SVG wordmark, already painted purple-7).  Sized
   to roughly match the FC text mark's visual height; right-
   aligned in the ZR column. */
.fa-pick-logo {
  display: block;
  height: clamp(22px, 2.6vw, 38px);
  width: auto;
  margin: 0 0 clamp(14px, 1.6vw, 22px);
  margin-left: auto;
}

@media (min-width: 1600px) { .fa-pick-logo { height: 42px; } }
@media (min-width: 1920px) { .fa-pick-logo { height: 50px; } }
@media (max-width: 720px)  { .fa-pick-logo { margin-left: 0; } }

.fa-pick-text {
  margin: 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.55;
  color: #1D1612;
  max-width: 36ch;
}

.fa-pick-side--zr .fa-pick-text {
  margin-left: auto;
}

/* ── Axis — horizontal track + sliding knob.  The visual
   indicator of the mouse-driven weighting. */

.fa-pick-axis {
  position: relative;
  margin-top: clamp(40px, 6vw, 80px);
  height: 32px;
  /* let the knob be dragged on touch without the page panning */
  touch-action: none;
}

.fa-pick-axis-rod {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(29, 22, 18, 0.28);
  transform: translateY(-0.5px);
}

.fa-pick-axis-knob {
  position: absolute;
  top: 50%;
  left: calc(var(--pick-t) * 100%);
  transform: translate(-50%, -50%);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #1D1612;
  box-shadow: 0 0 0 6px rgba(29, 22, 18, 0.08);
  /* No CSS transition on `left` — the JS lerp on --pick-t IS
     the smoothing; transitioning here was doubling the easing. */
  animation: fa-pick-pulse 2.4s ease-in-out infinite;
}

/* Mouse takes over → no pulse. */
.fa-pick[data-armed="true"] .fa-pick-axis-knob {
  animation: none;
  box-shadow: 0 0 0 10px rgba(29, 22, 18, 0.12);
}

@keyframes fa-pick-pulse {
  0%, 100% {
    transform: translate(-50%, -50%) scale(1);
    box-shadow: 0 0 0 6px rgba(29, 22, 18, 0.08);
  }
  50% {
    transform: translate(-50%, -50%) scale(1.15);
    box-shadow: 0 0 0 10px rgba(29, 22, 18, 0.06);
  }
}

.fa-pick-axis-label {
  position: absolute;
  top: calc(50% + 22px);
  appearance: none;
  border: 0;
  background: transparent;
  padding: 6px 14px;
  border-radius: 999px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(29, 22, 18, 0.6);
  cursor: pointer;
  transition: color 220ms ease, background 220ms ease;
}

.fa-pick-axis-label:hover,
.fa-pick-axis-label:focus-visible {
  color: rgba(29, 22, 18, 0.95);
  background: rgba(29, 22, 18, 0.06);
  outline: none;
}

.fa-pick[data-active-side="fc"] .fa-pick-axis-label--fc,
.fa-pick[data-active-side="zr"] .fa-pick-axis-label--zr {
  color: rgba(29, 22, 18, 1);
  background: rgba(29, 22, 18, 0.08);
}

.fa-pick-axis-label--fc { left: 0; }
.fa-pick-axis-label--zr { right: 0; }

/* ── Entry — IO reveal stagger, lands during second half of
   the BG bloom. */

.fa-act-3-kicker,
.fa-act-3-h2,
.fa-pick-side,
.fa-pick-axis {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fa-act-3.is-in .fa-act-3-kicker {
  opacity: 1; transform: translateY(0);
  transition-delay: 180ms;
}
.fa-act-3.is-in .fa-act-3-h2 {
  opacity: 1; transform: translateY(0);
  transition-delay: 320ms;
}
.fa-act-3.is-in .fa-pick-side--fc {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 520ms;
}
.fa-act-3.is-in .fa-pick-side--zr {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 660ms;
}
.fa-act-3.is-in .fa-pick-axis {
  opacity: 1; transform: translateY(0);
  transition-delay: 820ms;
}

@media (max-width: 720px) {
  /* Mobile: tighter padding + no scale on inner sides. */
  .fa-act-3 { padding: clamp(80px, 12vh, 140px) 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .fa-act-3-bg { clip-path: circle(150% at 50% 50%); transition: none; }
  .fa-act-3-kicker, .fa-act-3-h2, .fa-pick-side, .fa-pick-axis {
    opacity: 1; transform: none; transition: none;
  }
  .fa-pick-axis-knob { animation: none; transition: none; }
}

/* ══════════════════════════════════════════════════════════
   Act 4 — closer.

   Dark BG (no saturated band — rhythm break is composition,
   not colour).  MCP-style closer: word-pop H2 assembles word
   by word, mono trace murmurs underneath like a system print,
   centered CTA stack lands at the bottom.
══════════════════════════════════════════════════════════ */

.fa-act-4 {
  position: relative;
  background: var(--background);
  padding: clamp(120px, 18vh, 220px) clamp(20px, 6vw, 96px) clamp(120px, 18vh, 220px);
}

.fa-act-4-frame {
  position: relative;
  max-width: 1240px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(28px, 4vh, 56px);
}

@media (min-width: 1600px) { .fa-act-4-frame { max-width: 1400px; } }
@media (min-width: 1920px) { .fa-act-4-frame { max-width: 1560px; } }

/* ── Kicker. */

.fa-act-4-kicker {
  margin: 0;
  color: var(--text-tertiary);
}

/* ── H2 — word-pop assembly.  Each word fades + slides + de-
   blurs in with a per-index transition-delay cascade.  The
   last word ("back.") gets the accent colour (purple-7) so the
   final beat lands a brand note. */

.fa-act-4-h2 {
  margin: 0;
  font-family: var(--font-base);
  font-weight: 500;
  letter-spacing: -0.026em;
  line-height: 1.0;
  font-size: clamp(48px, 7.6vw, 132px);
  color: var(--text-primary);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.18em 0.32em;
}

@media (min-width: 1600px) { .fa-act-4-h2 { font-size: 152px; } }
@media (min-width: 1920px) { .fa-act-4-h2 { font-size: 176px; } }
@media (min-width: 2400px) { .fa-act-4-h2 { font-size: 208px; } }

.fa-act-4-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(28px);
  filter: blur(4px);
  transition:
    opacity 720ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 720ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 720ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: calc(var(--i, 0) * 110ms);
}

.fa-act-4-word--accent { color: #7C4FE8; }

.fa-act-4.is-in .fa-act-4-word {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* ── Mono trace — murmurs underneath the H2 like the system
   printing the user's choice. */

.fa-act-4-trace {
  list-style: none;
  margin: 0;
  padding: clamp(14px, 1.6vw, 24px) clamp(18px, 2vw, 28px);
  border-left: 1px solid var(--border-subtle);
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-xs);
  line-height: 1.85;
  color: var(--text-secondary);
  text-align: left;
}

.fa-act-4-trace-line {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 460ms ease,
    transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
  /* Trace lines start after the H2 finishes assembling — last
     H2 word ends at ~5*110+720 = 1270ms, so trace begins ~1300. */
  transition-delay: calc(1300ms + var(--i, 0) * 200ms);
}

.fa-act-4.is-in .fa-act-4-trace-line {
  opacity: 1;
  transform: translateY(0);
}

.fa-act-4-trace-prompt { color: var(--text-quaternary, var(--text-tertiary)); }
.fa-act-4-trace-brand  { color: #7C4FE8; font-weight: 700; }
.fa-act-4-trace-num    { color: var(--text-primary); font-weight: 600; }
.fa-act-4-trace-ok     { color: #6FE7B0; margin-left: 4px; }

/* ── CTA stack — uses the shared cta-stack atom; reveal lands
   after the trace finishes. */

.fa-act-4-cta {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 600ms ease,
    transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
  /* Trace ends at ~1300+2*200+460 = 2160ms; CTA at ~1900 (during
     trace's final fade so the eye moves smoothly). */
  transition-delay: 1900ms;
}

.fa-act-4.is-in .fa-act-4-cta {
  opacity: 1;
  transform: translateY(0);
}

/* ── Secondary link. */

.fa-act-4-secondary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 13px;
  letter-spacing: -0.005em;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: 6px;
  margin-top: clamp(8px, 1vw, 14px);
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 600ms ease,
    transform 600ms cubic-bezier(0.22, 1, 0.36, 1),
    color 200ms ease,
    border-bottom-color 200ms ease;
  transition-delay: 2200ms;
}

.fa-act-4.is-in .fa-act-4-secondary {
  opacity: 1;
  transform: translateY(0);
}

.fa-act-4-secondary:hover {
  color: #7C4FE8;
  border-bottom-color: #7C4FE8;
  /* Speed the hover transitions back up (override the entry
     transition-duration so hover isn't sluggish). */
  transition:
    color 200ms ease,
    border-bottom-color 200ms ease;
}

/* ── Mobile. */
@media (max-width: 720px) {
  .fa-act-4 { padding: clamp(80px, 14vh, 140px) 20px; }
  .fa-act-4-h2 { font-size: clamp(40px, 12vw, 64px); }
  .fa-act-4-trace { padding: 12px 16px; font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .fa-act-4-word,
  .fa-act-4-trace-line,
  .fa-act-4-cta,
  .fa-act-4-secondary {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
}

/* ──────────────────────────────────────────────────────────
   Below 1100px — collapse sticky stage; card becomes timer.
─────────────────────────────────────────────────────────── */

@media (max-width: 1100px) {
  .fa-act-1 { min-height: 100vh; }
  .fa-act-1-frame {
    position: relative;
    top: auto;
    min-height: auto;
  }
}

/* ──────────────────────────────────────────────────────────
   Reduced motion — show all states plainly via the timer loop
   the JS falls back to (sticky pin disabled).
─────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .fa-act-1 { min-height: 100vh; }
  .fa-act-1-frame { position: relative; top: auto; min-height: auto; }
  .fa-hero-kicker, .fa-hero-h1, .fa-hero-sub, .fa-demo {
    opacity: 1; transform: none; transition: none;
  }
  .fa-demo-state { transition: none; }
  .fa-demo-bar-caret { animation: none; opacity: 1; }
  .fa-demo-wall-spinner { animation: none; }
}

/* ══════════════════════════════════════════════════════════
   BU light overrides.  --font-display auto-flips to Mq12 via
   DS-level override.

   All non-saturated-band rgba-white usages on this page live
   inside .fa-demo-bar--mesh (colored mesh bar widget — backdrop
   stays colored in BU) or inside Act 2 / Act 3 saturated brand
   bands (purple / teal — chrome stays canonical).  So no per-
   element rgba flips are needed beyond the body recess.
═══════════════════════════════════════════════════════════ */
html:not(.dark) body {
  background: var(--zen-gray-3);
  color: var(--text-primary);
}

/* Teal text on light bg — JSON string highlight flip. */
html:not(.dark) .fa-demo-json .json-s {
  color: #1C9E97;
}
