/* ═══════════════════════════════════════════════════════════════════
   The sweep hero. Loaded by the homepage only, but it lives here rather
   than inline because scripts/build-workflow-pages.py owns index.html
   and rewrites it wholesale: anything inline in that file is one
   regeneration away from being silently discarded.

   Tokens, type, buttons, nav chrome and the footer all come from
   funnel.css and workflow.css. This file is the hero and nothing else.
   ═══════════════════════════════════════════════════════════════════ */

/* ── the sweep hero ───────────────────────────────────────────── */
.track { position: relative; height: 250vh; }
.stage { position: sticky; top: 0; height: 100vh; overflow: hidden; background: var(--sand); }
#cv { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Scrim over the canvas so the copy column stays legible whatever the
   diagram is doing underneath. A contrast device, not decoration. */
.veil { position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, rgba(242,241,233,.98) 0%, rgba(242,241,233,.95) 40%, rgba(242,241,233,.86) 50%, rgba(242,241,233,.12) 64%, rgba(242,241,233,0) 74%); }

.hero-copy { position: absolute; z-index: 2; left: 0; right: 0; top: 0; bottom: 0;
  display: flex; flex-direction: column; justify-content: center; pointer-events: none; padding: 0; }
/* Full bleed, on the same gutter as the nav, so the brand mark and the
   headline share a left edge. width:100% matters: a cross-axis flex
   item with auto margins centres at CONTENT width instead of spanning. */
.hero-copy .bleed { width: 100%; pointer-events: none; }
.hero-copy .bleed > * { pointer-events: auto; }
.hero-inner { max-width: 620px; }
.hero-copy h1 { font-family: var(--f-display); font-weight: 700; font-size: clamp(38px, 4.6vw, 60px);
  line-height: 1.04; letter-spacing: -0.01em; margin: 14px 0 0; max-width: none; color: var(--ink); }
.hero-copy h1 em { font-style: normal; color: var(--terra); }
/* Each line is its own mask; the span inside rises out of it. The
   staggered delays are what make the headline land rather than appear. */
.hero-copy h1 .line { display: block; overflow: hidden; padding-bottom: .06em; }
.hero-copy h1 .line > span { display: block; transform: translateY(112%);
  animation: rise .9s var(--ease) forwards; }
.hero-copy h1 .line:nth-child(2) > span { animation-delay: .12s; }
.hero-copy h1 .line:nth-child(3) > span { animation-delay: .24s; }
@keyframes rise { to { transform: translateY(0); } }

/* Everything under the headline arrives after it, in reading order. */
@keyframes fade { to { opacity: 1; } }
.hero-copy .answer, .hero-copy .captions, .hero-copy .rail,
.hero-copy .btn-row, .hero-copy .call-note {
  opacity: 0; animation: fade .9s var(--ease) forwards; }
.hero-copy .answer    { animation-delay: .45s; }
.hero-copy .btn-row   { animation-delay: .55s; }
.hero-copy .call-note { animation-delay: .65s; }
.hero-copy .captions  { animation-delay: .75s; }
.hero-copy .rail      { animation-delay: .85s; }

.hero-copy .answer { margin-top: 16px; font-size: var(--t-base); line-height: 1.6; color: var(--ink-2); max-width: 52ch; }

/* Captions cross-fade in place, so the box has to clear the tallest
   one or its last line lands on the rail underneath. */
.captions { position: relative; margin-top: 26px; min-height: 152px; }
.cap { position: absolute; inset: 0; opacity: 0; transform: translateY(12px);
  transition: opacity .5s var(--ease), transform .5s var(--ease); }
.cap.on { opacity: 1; transform: none; }
.cap h2 { font-family: var(--f-display); font-size: var(--t-h3); font-weight: 600; margin: 0; color: var(--ink); }
.cap h2 span { color: var(--link); }
.cap p { margin-top: 6px; color: var(--ink-2); font-size: var(--t-sm); line-height: 1.55; max-width: 48ch; }

.rail { display: flex; gap: 14px; margin-top: 16px; }
.rail button { appearance: none; background: none; border: 0; padding: 9px 0 0;
  border-top: 2px solid var(--border); flex: 1; font: inherit; font-size: var(--t-sm);
  text-align: left; color: var(--ink-2); cursor: pointer; transition: color .4s var(--ease), border-color .4s var(--ease); }
.rail button:hover { color: var(--ink); }
.rail button[aria-current="true"] { color: var(--ink); border-color: var(--terra); font-weight: 500; }

.hero-copy .btn-row { margin-top: 24px; }
.hero-copy .call-note { margin-top: 18px; max-width: 54ch; }

.hint { position: absolute; z-index: 2; left: 50%; bottom: 26px; transform: translateX(-50%);
  font-size: var(--t-sm); color: var(--ink-2); transition: opacity .5s var(--ease); }
.hint.off { opacity: 0; }
/* The arrow is the invitation. Without it the first screen reads as a
   static page and nobody discovers that the diagram runs. */
.hint i { display: inline-block; font-style: normal; animation: bob 2.2s ease-in-out infinite; }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(6px); } }

/* Matches funnel.css's own 860px breakpoint exactly, so there is no band
   where the nav has collapsed but the hero has not. */
@media (max-width: 860px) {
  /* The concept pins a full-viewport canvas behind the copy at every
     width, but it is desktop-only in practice: its three 158px node
     boxes end up 67px apart at phone width, and the copy column needs
     more vertical room than a phone has to give. So the hero unpins
     here. The copy reads as an ordinary block and the diagram becomes
     its own panel underneath, animating as it travels through the
     viewport. Same four phases, same choreography, nothing clipped. */
  .track { height: auto; }
  .stage { position: static; height: auto; overflow: visible; padding: 56px 0 40px;
    display: flex; flex-direction: column; }
  .hero-copy { position: static; display: block; order: 1; }
  .hero-inner { max-width: none; }
  .hero-copy h1 { font-size: clamp(30px, 8.6vw, 40px); }
  #cv { position: relative; order: 2; width: 100%; height: clamp(420px, 112vw, 560px);
    margin-top: 30px; }
  .veil, .hint { display: none; }
  /* CTA sits directly under the opening explanation before the method. */
  .hero-copy .btn-row { margin-top: 20px; }
  .hero-copy .call-note { margin-top: 14px; margin-bottom: 8px; }
  .captions { position: static; min-height: 0; margin-top: 22px; }
  .cap { position: static; opacity: 1; transform: none; display: none; }
  .cap.on { display: block; }
  .rail { margin-top: 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .cap { transition: none; }
  /* Nothing may be left mid-entrance. An animation whose duration is
     clamped but which is cancelled outright would otherwise strand the
     headline inside its mask and the rest of the column at zero. */
  .hero-copy h1 .line > span, .hero-copy .answer, .hero-copy .captions,
  .hero-copy .rail, .hero-copy .btn-row, .hero-copy .call-note {
    animation: none; opacity: 1; transform: none; }
  .hint i { animation: none; }
}
