/* ==========================================================================
   act1.css — ACT ONE · "Why & Method"
   Mood: warm, unhurried, human, editorial. Warm paper + terracotta/gold.
   The heart of the pitch — generous whitespace, slow rhythm, expensive calm.

   EVERY rule is scoped under #act-one. Colors come only from the semantic
   theme vars set by .theme-warm; type from --font-display / inherited --font-sans;
   spacing/size from the fluid scale. Nothing is hard-coded.

   Contents
     1. Act shell + ambient warm glow + layering
     2. Hero / cover
     3. Belief & statements
     4. Method intro big-line
     5. The three questions (the spine) — index numerals + detail prose
     6. Case studies (product-card treatment + variants + ManifestIQ stat)
     7. Payoff list (network-echo nodes)
     8. Reduced-motion: disable every decorative animation I add
   ========================================================================== */


/* ==========================================================================
   1. ACT SHELL + AMBIENT GLOW + LAYERING
   The act is the positioning context for a soft, faint warm radial glow near
   the top. .act__bg (network.js canvas) already sits at --z-bg; my glow lives
   just above the page background but below content, and never intercepts input.
   ========================================================================== */
#act-one {
  position: relative;
  isolation: isolate;          /* keep my ::before glow contained to this act */
  background:
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 62%, var(--bg) 100%);
  color: var(--fg);
}

/* Soft warm radial wash near the top of the act — sets the editorial warmth.
   Sits above the flat background but beneath the network canvas + content. */
#act-one::before {
  content: "";
  position: absolute;
  inset-block-start: -8vh;
  inset-inline: 0;
  block-size: 90vh;
  z-index: -1;                 /* below content; isolation keeps it act-local */
  pointer-events: none;
  background:
    radial-gradient(60% 55% at 50% 0%, var(--glow) 0%, transparent 70%),
    radial-gradient(40% 38% at 82% 8%, var(--glow) 0%, transparent 72%);
  opacity: 0.9;
  /* very slow, barely-there breathing so the warmth feels alive, not static */
  animation: a1-glow-drift 22s var(--ease-breathe) infinite alternate;
}

@keyframes a1-glow-drift {
  from { opacity: 0.72; transform: translate3d(0, 0, 0) scale(1); }
  to   { opacity: 1;    transform: translate3d(0, 1.4%, 0) scale(1.05); }
}

/* Make sure act content reliably stacks above the network canvas. base.css
   already lifts .act > .moment/.section; reinforce for the nested blocks
   that aren't direct children of .act (questions/cases live inside wrappers). */
#act-one > .section,
#act-one > .moment,
#act-one .question-block {
  position: relative;
  z-index: var(--z-content);
}


/* ==========================================================================
   2. HERO / COVER — full-viewport cinematic opener.
   Content placed lower-left for editorial impact; scroll-cue near the bottom.
   ========================================================================== */
#act-one .hero {
  /* .hero is also a .moment (min-height:100svh, centered grid) from base.css.
     Override the alignment so the title settles into the lower-left third. */
  min-block-size: 100vh; /* fallback */
  min-block-size: 100svh;
  align-content: end;
  padding-block: clamp(var(--space-2xl), 12vh, var(--space-4xl));
  overflow: clip;
}

#act-one .hero__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(var(--space-m), 3.2vh, var(--space-xl));
}

/* Brand kicker — small, tracked, with a short leading rule echoing the network. */
#act-one .hero__kicker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-s);
  color: var(--muted);
}
#act-one .hero__kicker::before {
  content: "";
  inline-size: clamp(1.6rem, 4vw, 3rem);
  block-size: 1px;
  background: var(--accent);
  opacity: 0.8;
  flex: 0 0 auto;
}

/* The hero line — huge display serif, tight, a narrow measure for drama. */
#act-one .hero__title {
  font-family: var(--font-display);
  font-size: var(--step-7);
  font-weight: 340;
  line-height: 0.98;
  letter-spacing: -0.022em;
  max-inline-size: 14ch;
  text-wrap: balance;
  color: var(--fg);
}
#act-one .hero__title em {
  font-style: italic;
  font-weight: 420;
  color: var(--accent);        /* terracotta accent on "more human" */
}

/* Sub-line — the quiet truth under the headline. */
#act-one .hero__sub {
  font-size: var(--step-2);
  line-height: 1.4;
  max-inline-size: 34ch;
  color: var(--muted);
  text-wrap: pretty;
}

/* Kicker labels: warm --accent (terracotta) is only ~3.6:1 on the paper bg,
   failing AA for this small label text. Use --muted (5.4:1) for the words and
   keep the accent on the leading rule so it still reads as a chapter label. */
#act-one .kicker { color: var(--muted); }
#act-one .kicker::before { background: var(--accent); opacity: 1; }

/* Scroll cue — anchored visually to the bottom, a thin descending line that
   gently pulses to invite the first scroll. */
#act-one .scroll-cue {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2xs);
  margin-block-start: clamp(var(--space-s), 2vh, var(--space-l));
  color: var(--muted); /* AA on warm paper (5.4:1); --faint was 2.89:1 for this link */
  font-size: var(--step--1);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* Per-property: this ID-specificity rule REPLACES base.css's reveal
     transition, so opacity/transform must be redeclared here or the cue's
     entrance (and its --reveal-delay) silently stops working. Color answers
     instantly on hover; the entrance honors the hero choreography delay. */
  transition:
    color var(--dur-0) var(--ease-out),
    opacity calc(var(--dur-2) * 0.55) var(--ease-soft),
    transform var(--dur-2) var(--ease-out);
  transition-delay: 0s, var(--reveal-delay, 0ms), var(--reveal-delay, 0ms);
}
#act-one .scroll-cue:hover { color: var(--fg); } /* --accent fails AA on warm; --fg darkens-on-hover and passes */
#act-one .scroll-cue__text { font-weight: 500; }
#act-one .scroll-cue__line {
  inline-size: 1px;
  block-size: clamp(2.4rem, 7vh, 4.5rem);
  background: linear-gradient(180deg, var(--line-strong), transparent);
  transform-origin: top;
  animation: a1-cue-pulse 2.4s var(--ease-breathe) infinite;
}
/* Hold the pulse until the opening shot has settled (cue arrives at ~2.1s). */
html.js #act-one .scroll-cue__line { animation-delay: 2.1s; }
@keyframes a1-cue-pulse {
  0%, 100% { transform: scaleY(0.55); opacity: 0.5; }
  50%      { transform: scaleY(1);    opacity: 1; }
}


/* ==========================================================================
   3. BELIEF & STATEMENTS — large, slow, lots of air; narrow measure.
   ========================================================================== */
#act-one .belief {
  padding-block: clamp(var(--space-2xl), 16vh, var(--space-4xl));
}

/* The core belief — display serif, generously sized, calm leading. */
#act-one .statement {
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 350;
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--fg);
  max-inline-size: 24ch;
  text-wrap: pretty;
}

/* The turn — "The work was always the side effect…" — gets the accent voice. */
#act-one .statement--accent {
  color: var(--accent);
  font-style: italic;
  font-weight: 400;
}

/* "Your story" slot — a soft framed placeholder that feels intentional, not raw. */
#act-one .slot--story {
  display: block;
  margin-block-start: var(--space-s);
  padding: var(--space-m) var(--space-l);
  border-inline-start: 2px solid var(--accent);
  background: var(--surface);
  border-radius: 0 var(--radius-m) var(--radius-m) 0;
  color: var(--muted);
}
#act-one .slot--story .slot__label {
  display: block;
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted); /* AA on warm; accent failed at ~3.7:1 for this label text */
  margin-block-end: var(--space-3xs);
}
#act-one .slot--story .slot__hint {
  font-size: var(--step-0);
  color: var(--muted); /* AA on warm; --faint was ~3:1 for this hint text */
}


/* ==========================================================================
   4. METHOD INTRO — centered, commanding big-line.
   ========================================================================== */
#act-one .method-intro { text-align: center; }
#act-one .method-intro .container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-m);
}
#act-one .method-intro .big-line {
  font-family: var(--font-display);
  font-size: var(--step-5);
  font-weight: 350;
  line-height: 1.08;
  letter-spacing: -0.02em;
  max-inline-size: 20ch;
  text-wrap: balance;
}


/* ==========================================================================
   5. THE THREE QUESTIONS — the spine of Act One.
   Each is a full-viewport .moment with a large faint numeral (01/02/03) paired
   to the question text, followed by narrow detail prose. Deliberate rhythm.
   ========================================================================== */

/* The big outlined/faint display numeral. Sized large, kept airy and quiet
   so it frames rather than competes with the question text. */
#act-one .question__index {
  display: block;
  font-family: var(--font-display);
  font-size: var(--step-7);
  font-weight: 300;
  line-height: 0.9;
  letter-spacing: -0.02em;
  /* Accent-tinted hollow "chapter number", with layered fallbacks so it never
     just vanishes: a solid faint fill if text-fill-color/stroke is unsupported,
     a solid stroke if color-mix() is unsupported, then the preferred tinted
     stroke + transparent fill where everything is supported. */
  color: var(--faint);
  -webkit-text-stroke: 1.4px var(--accent);
  text-stroke: 1.4px var(--accent);
  -webkit-text-stroke: 1.4px color-mix(in srgb, var(--accent) 55%, transparent);
  text-stroke: 1.4px color-mix(in srgb, var(--accent) 55%, transparent);
  /* settled state (also the no-JS frame): outline + a faint accent ink wash */
  -webkit-text-fill-color: color-mix(in srgb, var(--accent) 14%, transparent);
  opacity: 0.9;
  margin-block-end: clamp(var(--space-2xs), 1.5vh, var(--space-m));
}

/* THE NUMERAL RITUAL — the same learnable two-stage entrance on all three
   chapter numerals: (1) the outline wipes up via data-reveal="line", then
   (2) the faint accent ink fades into the counters a beat later. The wipe's
   top/side insets stay open so the stroke and digit tops are never shaved. */
html.js #act-one .question__index {
  -webkit-text-fill-color: transparent;
  transition:
    opacity 0.01s linear,
    -webkit-text-fill-color var(--dur-2) var(--ease-out) 0.55s;
}
html.js #act-one .question__index.is-visible {
  -webkit-text-fill-color: color-mix(in srgb, var(--accent) 14%, transparent);
}
html.js #act-one .question__index > .line-wipe { clip-path: inset(-25% -10% 105% -10%); }
html.js #act-one .question__index.is-visible > .line-wipe { clip-path: inset(-25% -10% -25% -10%); }
/* Question 03 — the heaviest beat: its ink stage lands slower. */
html.js #act-one #q-impossible .question__index {
  transition-duration: 0.01s, var(--dur-3);
}

/* The question itself — the line that lands. */
#act-one .question__text {
  font-family: var(--font-display);
  font-size: var(--step-6);
  font-weight: 340;
  line-height: 1.02;
  letter-spacing: -0.022em;
  max-inline-size: 18ch;
  text-wrap: balance;
  color: var(--fg);
}
#act-one .question__text em {
  font-style: italic;
  color: var(--accent);
  font-weight: 400;
  /* Draw-on underline — a thin accent rule painted as a bottom-anchored
     gradient on the word itself (no absolute pseudo, so it renders reliably
     across engines). It wipes in from the left a beat AFTER the question's
     line-reveal lands. padding-bottom drops it just clear of descenders. */
  padding-bottom: 0.1em;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0.05em;   /* no-JS / reduced-motion: shown statically */
}
/* JS-gated collapsed state; reveal expands it once the question is visible.
   The delay rides on the question's own --reveal-delay so the draw always
   lands a beat after the line itself. */
html.js #act-one .question__text em {
  background-size: 0% 0.05em;
  transition: background-size 0.85s var(--ease-out) calc(0.42s + var(--reveal-delay, 0ms));
}
html.js #act-one .question__text.is-visible em {
  background-size: 100% 0.05em;
}

/* Detail prose — narrow measure, muted, sits just under the question moment. */
#act-one .question__detail {
  padding-block-start: 0;
  padding-block-end: clamp(var(--space-xl), 8vh, var(--space-3xl));
}
#act-one .question__detail .prose {
  font-size: var(--step-1);
  line-height: 1.62;
  max-inline-size: var(--measure-wide);
  color: var(--muted);
  text-wrap: pretty;
}
/* Lead the first detail paragraph with a short accent rule — visually tying
   the prose back to the numeral/spine without adding markup. */
#act-one .question__detail .stack > .prose:first-child {
  position: relative;
  padding-inline-start: var(--space-m);
}
#act-one .question__detail .stack > .prose:first-child::before {
  content: "";
  position: absolute;
  inset-block: 0.35em auto;
  inset-inline-start: 0;
  inline-size: 2px;
  block-size: 1.4em;
  background: var(--accent);
  opacity: 0.7;
}


/* ==========================================================================
   6. CASE STUDIES — premium product-card treatment.
   Surface bg, hairline border, large radius, generous padding, soft shadow.
   Each variant carries a subtle distinguishing left edge, all within warm range.
   ========================================================================== */
#act-one .case {
  position: relative;
  max-inline-size: 58rem;
  margin-inline: auto;
  padding: clamp(var(--space-l), 4vw, var(--space-2xl));
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-soft);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  overflow: clip;
  /* release tier: floating back down is graceful… */
  transition:
    transform var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out);
}
/* A subtle distinguishing accent edge at the top of every card. */
#act-one .case::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  background: var(--accent);
  opacity: 0.85;
}
#act-one .case:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
  border-color: var(--line-strong);
  /* …but the answer to the cursor is instant (asymmetric hover timing) */
  transition-duration: var(--dur-0);
}

/* Per-variant accent: shift hue within the warm palette via accent/accent-2,
   each given a faint matching corner wash so the three cards read as a set
   while staying individually distinct. */
#act-one .case--strategic::before { background: var(--accent); }     /* terracotta */
#act-one .case--deerhunt::before {
  background: linear-gradient(90deg, var(--accent-2), var(--accent));  /* gold→terracotta */
}
#act-one .case--manifest::before { background: var(--accent-2); }    /* warm gold */

#act-one .case--strategic { --case-tint: var(--accent); }
#act-one .case--deerhunt  { --case-tint: var(--accent-2); }
#act-one .case--manifest  { --case-tint: var(--accent-2); }

#act-one .case::after {
  content: "";
  position: absolute;
  inset-block-start: -30%;
  inset-inline-end: -10%;
  inline-size: 40%;
  block-size: 60%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--case-tint, var(--accent)) 12%, transparent), transparent);
}
/* keep card content above the corner wash */
#act-one .case > * { position: relative; z-index: 1; }

/* Card head: tag pill → brand → role */
#act-one .case__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2xs);
  margin-block-end: var(--space-l);
}

/* Small uppercase pill */
#act-one .case__tag {
  display: inline-block;
  padding: 0.3em 0.85em;
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted); /* AA on the warm card; accent text was ~3.7:1 */
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--radius-pill);
  margin-block-end: var(--space-2xs);
}

/* Brand name — large display, with the TLD in accent. */
#act-one .case__brand {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-weight: 380;
  line-height: 1.0;
  letter-spacing: -0.02em;
  color: var(--fg);
}
#act-one .case__tld {
  color: var(--accent);
  font-style: italic;
  font-weight: 400;
}

/* Role line — muted, smaller, a subtitle. */
#act-one .case__role {
  font-size: var(--step-0);
  color: var(--muted);
  font-style: italic;
}

/* Body prose */
#act-one .case__body {
  --flow: 1.1em;
  max-inline-size: 56ch;
  color: var(--fg);
}
#act-one .case__body p {
  font-size: var(--step-0);
  line-height: 1.66;
  color: var(--muted);
  text-wrap: pretty;
}

/* ---- Product screenshot inside a case card — real proof of the tool. ---- */
#act-one .case__shot {
  margin-block-start: var(--space-l);
}
/* The square dossier is reined in and centered; wide app/banner shots fill. */
#act-one .case__shot--tall {
  max-inline-size: 30rem;
  margin-inline: auto;
}
/* The frame owns the chrome (radius/border/shadow) and clips the image, so
   the evidence can UNVEIL: the frame wipes open top-down while the image
   settles from a gentle zoom inside it. Negative clip insets keep the
   shadow's ~30px spill visible throughout the wipe. */
#act-one .case__shot-frame {
  border-radius: var(--radius-m);
  border: 1px solid var(--surface-border);
  box-shadow: var(--shadow-soft);
  background: #0b1020;            /* matte behind any edge transparency */
  overflow: hidden;
}
#act-one .case__shot img {
  display: block;
  inline-size: 100%;
  block-size: auto;
}
html.js #act-one .case__shot-frame {
  clip-path: inset(-32px -32px 100% -32px);
  transition: clip-path var(--dur-3) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
html.js #act-one .case__shot.is-visible .case__shot-frame { clip-path: inset(-32px); }
html.js #act-one .case__shot img {
  transform: scale(1.06);
  transition: transform 1.6s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
html.js #act-one .case__shot.is-visible img { transform: none; }
#act-one .case__shot-cap {
  margin-block-start: var(--space-xs);
  font-size: var(--step--1);
  font-style: italic;
  color: var(--muted);
  text-wrap: pretty;
}

/* ---- ManifestIQ proof stat — the closing hammer of Act One ---- */
#act-one .case__stat {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-s) var(--space-l);
  margin-block-start: var(--space-l);
  padding-block-start: var(--space-l);
  border-block-start: 1px solid var(--line);  /* distinct hairline row */
}
#act-one .stat__value {
  font-family: var(--font-display);
  font-size: var(--step-7);
  font-weight: 360;
  line-height: 0.9;
  letter-spacing: -0.03em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  /* reserve width so the count-up animation never shifts surrounding layout */
  min-inline-size: 4.5ch;
  display: inline-block;
}
/* Settle pulse — a single, gentle scale as the count-up lands (counter.js adds
   .is-counted on completion). The global reduced-motion clamp makes it a no-op. */
#act-one .stat__value.is-counted {
  animation: a1-stat-settle 0.72s var(--ease-out);
}
@keyframes a1-stat-settle {
  0%   { transform: scale(1); }
  38%  { transform: scale(1.045); }
  100% { transform: scale(1); }
}
#act-one .stat__label {
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.35;
  color: var(--muted);
  text-wrap: balance;
  flex: 1 1 14ch;
}


/* ==========================================================================
   7. PAYOFF — confident closing list. Filled accent nodes echo the network,
   with a subtle connecting vertical line threading them together.
   ========================================================================== */
#act-one .payoff { text-align: left; }
#act-one .payoff .container {
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
}
#act-one .payoff .section-title {
  font-family: var(--font-display);
  font-size: var(--step-5);
  font-weight: 350;
  line-height: 1.08;
  letter-spacing: -0.02em;
  max-inline-size: 18ch;
  text-wrap: balance;
}

#act-one .payoff__list {
  display: flex;
  flex-direction: column;
  gap: clamp(var(--space-m), 3vh, var(--space-xl));
  max-inline-size: 46rem;
  margin-block-start: var(--space-m);
}

/* Each item: node + text in a row; relative for the connecting line. */
#act-one .payoff__item {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: var(--space-m);
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 340;
  line-height: 1.3;
  color: var(--fg);
  text-wrap: pretty;
}

/* Filled accent node — the network motif. */
#act-one .payoff__mark {
  position: relative;
  inline-size: 0.7em;
  block-size: 0.7em;
  margin-block-start: 0.5em;       /* optical align to first text line */
  border-radius: var(--radius-pill);
  background: var(--accent);
  flex: 0 0 auto;
  box-shadow: 0 0 0 0 var(--glow);
  animation: a1-node-pulse 3.6s var(--ease-breathe) infinite;
}
/* Subtle connecting line between consecutive nodes. */
#act-one .payoff__item:not(:last-child) .payoff__mark::after {
  content: "";
  position: absolute;
  inset-block-start: 0.7em;
  inset-inline-start: 50%;
  inline-size: 1px;
  /* span the gap to the next node */
  block-size: calc(clamp(var(--space-m), 3vh, var(--space-xl)) + 0.6em);
  transform: translateX(-50%);
  background: linear-gradient(180deg, var(--accent), transparent 85%);
  opacity: 0.4;
}
@keyframes a1-node-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--glow); }
  50%      { box-shadow: 0 0 0 6px transparent; }
}

/* The payoff line is [data-em-beat]: its emphasized clause arrives after the
   rest of the line (text-anim.js), then this accent underline draws once the
   last em word has settled (--em-done, stamped by text-anim.js). Mirrors the
   question-em underline so the thesis closes with the same ritual. */
#act-one .payoff__line em {
  padding-bottom: 0.1em;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0.05em;   /* no-JS / reduced-motion: shown statically */
}
html.js #act-one .payoff__line em {
  background-size: 0% 0.05em;
  transition: background-size 0.9s var(--ease-out) var(--em-done, 0.42s);
}
html.js #act-one .payoff__line.is-visible em {
  background-size: 100% 0.05em;
}


/* ==========================================================================
   7b. SCROLL-LINKED DEPTH — pure-CSS view() timelines, compositor-thread,
   zero JS. Three moves: (a) the hero recedes like a title card as belief
   slides over its clipped edge; (b) each question (and the payoff) is a
   shallow 3-plane set — numeral lags, headline rides 1:1, robot spot leads.
   Planes are symmetric around the moment's centered position, so every
   presenter landing rests at exactly translate 0. The independent
   `translate` property never collides with the reveals' `transform`; the
   timeline longhand is declared AFTER the `animation` shorthand (which
   resets it). Non-supporting engines and reduced motion skip the block.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    #act-one .hero { view-timeline-name: --hero-exit; }
    #act-one .hero__inner {
      animation: a1-hero-recede linear both;
      animation-timeline: --hero-exit;
      animation-range: exit 0% exit 100%;
    }
    #act-one .spot--hero > .rscene {
      animation: a1-hero-spot-recede linear both;
      animation-timeline: --hero-exit;
      animation-range: exit 0% exit 100%;
    }

    #act-one .question,
    #act-one .payoff { view-timeline: --plane block; }
    #act-one .question .question__index {
      animation: a1-plane-far linear both;
      animation-timeline: --plane;
    }
    #act-one .question .spot,
    #act-one .payoff .spot {
      animation: a1-plane-near linear both;
      animation-timeline: --plane;
    }
  }
}
@keyframes a1-hero-recede {
  to { translate: 0 22vh; opacity: 0.3; }
}
@keyframes a1-hero-spot-recede {
  to { translate: 0 10vh; opacity: 0.45; }
}
/* far plane traverses slower than the page (background) */
@keyframes a1-plane-far {
  from { translate: 0 -2rem; }
  to   { translate: 0 2rem; }
}
/* near plane traverses faster (foreground) */
@keyframes a1-plane-near {
  from { translate: 0 2.5rem; }
  to   { translate: 0 -2.5rem; }
}


/* ==========================================================================
   8. RESPONSIVE REFINEMENTS
   ========================================================================== */

/* Phones: tighten the hero, soften numeral scale, keep cards comfortable. */
@media (max-width: 40rem) {
  #act-one .hero__title { max-inline-size: 16ch; }
  #act-one .question__index { font-size: var(--step-6); }
  #act-one .question__text  { font-size: var(--step-5); max-inline-size: 14ch; }
  #act-one .case { padding: var(--space-l) var(--space-m); }
  #act-one .case__stat { gap: var(--space-xs) var(--space-m); }
}

/* Large projector: let the hero breathe even more and cap measures gracefully. */
@media (min-width: 90rem) {
  #act-one .hero { align-content: center; }
}


/* ==========================================================================
   9. REDUCED MOTION — disable every decorative animation I introduced.
   base.css already neutralizes [data-reveal]; this covers my glows/pulses.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  #act-one::before,
  #act-one .scroll-cue__line,
  #act-one .payoff__mark {
    animation: none !important;
  }
  #act-one .case { transition: none; }
  #act-one .case:hover { transform: none; box-shadow: var(--shadow-soft); }
  /* evidence shows settled: no wipe, no zoom, no drawn underline motion */
  html.js #act-one .case__shot-frame { clip-path: none !important; }
  html.js #act-one .case__shot img { transform: none !important; }
  html.js #act-one .question__index > .line-wipe { clip-path: none !important; }
}
