function HowItWorks() {
  const steps = [
  {
    title: "A new revision lands.",
    body: "A BLUE schedule drops. A DOOD supersedes. Krew spots the new version automatically."
  },
  {
    title: "Krew reads across every doc.",
    body: "Every page, every row, every scene — compared against the prior version, mapped across every connected doc."
  },
  {
    title: "Krew flags what changed.",
    body: "Page counts, scenes added or cut, travel and DOOD conflicts. Emailed with a shareable dashboard link."
  },
  {
    title: "You reply. Krew answers.",
    body: "Reply to the email. Text the production number. Sources and page references come with every answer."
  }];


  const pinRef = React.useRef(null);
  const stageRef = React.useRef(null);
  const lastActive = React.useRef(-1);
  const [active, setActive] = React.useState(0);

  // Scroll-driven progress. We write the continuous `phase` directly to
  // CSS custom props on the stage (no React render), and only setState
  // when the discrete active step index changes.
  React.useEffect(() => {
    const pin = pinRef.current;
    const stage = stageRef.current;
    if (!pin || !stage) return;
    let ticking = false;
    const compute = () => {
      const rect = pin.getBoundingClientRect();
      const vh = window.innerHeight || 800;
      const travel = Math.max(rect.height - vh, 1);
      const scrolled = Math.min(Math.max(-rect.top, 0), travel);
      const p = scrolled / travel; // 0..1
      const phase = Math.min(steps.length - 0.0001, Math.max(0, p * steps.length));
      const a = Math.min(steps.length - 1, Math.floor(phase));
      const local = Math.min(1, Math.max(0, phase - a));

      // Derive all fractional sub-phases in JS so the CSS is flat.
      const clamp01 = (x) => Math.min(1, Math.max(0, x));
      const fan = clamp01(phase / 0.85);
      const read = clamp01((phase - 1.05) / 0.85);
      const reportIn = clamp01((phase - 2.05) / 0.6);
      const reportOut = clamp01((phase - 2.9) / 0.2);
      const readOut = clamp01((phase - 1.9) / 0.2);
      const readIn = clamp01((phase - 1.05) / 0.6);
      const replyIn = clamp01((phase - 3.05) / 0.6);
      const blueShadow = phase < 2 ? 1 - clamp01((phase - 1.8) / 0.2) : 0;

      const s = stage.style;
      s.setProperty('--phase', phase.toFixed(3));
      s.setProperty('--local', local.toFixed(3));
      s.setProperty('--fan', fan.toFixed(3));
      s.setProperty('--read', read.toFixed(3));
      s.setProperty('--read-in', readIn.toFixed(3));
      s.setProperty('--read-out', readOut.toFixed(3));
      s.setProperty('--report-in', reportIn.toFixed(3));
      s.setProperty('--report-out', reportOut.toFixed(3));
      s.setProperty('--reply-in', replyIn.toFixed(3));
      s.setProperty('--blue-glow', blueShadow.toFixed(3));

      if (a !== lastActive.current) {
        lastActive.current = a;
        setActive(a);
      }
    };
    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      requestAnimationFrame(() => {compute();ticking = false;});
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    compute();
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, []);

  return (
    <section
      className="section how-section"
      id="how"
      style={{ background: 'var(--krew-grain-pale)', borderTop: '1px solid var(--border-hair)', borderBottom: '1px solid var(--border-hair)', padding: '50px 0 0' }}>
      
      <div className="container how-section-head-desktop">
        <div className="section-head reveal" style={{ marginBottom: 24 }}>
          <span className="eyebrow-row"><i className="dot"></i>How Krew works</span>
          <h2>The new schedule lands at 6:42pm. Here's what happens next.</h2>
          <p>No app. No login. Krew plugs into your document pipeline and shows up where your team already lives — email, SMS, iMessage.</p>
        </div>
      </div>

      {/* Pin container — one viewport of dwell per step */}
      <div className="how-pin" ref={pinRef} style={{ height: `${steps.length * 100}vh` }}>
        <div className="how-stage" ref={stageRef}>
          <div className="container how-stage-inner">
            {/* Mobile-only: section header pinned with the rest of the
                composition so eyebrow + h2 + p stay at the top of the
                screen alongside the visual and caption. Hidden ≥720px. */}
            <div className="section-head reveal how-section-head-mobile">
              <span className="eyebrow-row"><i className="dot"></i>How Krew works</span>
              <h2>The new schedule lands at 6:42pm. Here's what happens next.</h2>
              <p>No app. No login. Krew plugs into your document pipeline and shows up where your team already lives — email, SMS, iMessage.</p>
            </div>
            {/* Pinned visual — flex-grows, vertically centered */}
            <div className="how-visual">
              <HowPreview active={active} />
            </div>

            {/* Caption — fixed-height; only active one visible */}
            <div className="how-captions">
              {steps.map((s, i) =>
              <div
                key={i}
                className={`how-caption ${active === i ? 'is-active' : ''} ${active > i ? 'is-past' : ''}`}
                aria-hidden={active !== i}>
                
                  <div className="how-caption-step">
                    <span className="how-caption-step-num">{String(i + 1).padStart(2, '0')}</span>
                    <span className="how-caption-step-sep">/</span>
                    <span className="how-caption-step-total">{String(steps.length).padStart(2, '0')}</span>
                  </div>
                  <h3 className="how-caption-title">{s.title}</h3>
                  <p className="how-caption-body">{s.body}</p>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* MOBILE-ONLY: vertical step list. Hidden ≥720px via CSS.
          Each step is a self-contained card with its own visual,
          no pin / no horizontal fan. */}
      <div className="how-mobile-steps container" aria-hidden="false">
        {steps.map((s, i) => (
          <div key={i} className="how-mstep" data-step={i}>
            <div className="how-mstep-num">
              <strong>{String(i + 1).padStart(2, '0')}</strong>
              <span> / {String(steps.length).padStart(2, '0')}</span>
            </div>
            <h3 className="how-mstep-title">{s.title}</h3>
            <p className="how-mstep-body">{s.body}</p>
            <div className="how-mstep-visual">
              {i === 0 && (
                <div className="how-mstep-docs">
                  <div className="md-doc is-blue">
                    <h6>Blue rev</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                  <div className="md-doc is-white">
                    <h6>One-liner</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                  <div className="md-doc is-warm">
                    <h6>DOOD</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                </div>
              )}
              {i === 1 && (
                <div className="how-mstep-docs">
                  <div className="md-doc is-blue">
                    <h6>Compared</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                  <div className="md-doc is-white">
                    <h6>Call sheet</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                  <div className="md-doc is-warm">
                    <h6>Travel</h6>
                    <i></i><i></i><i></i><i></i>
                  </div>
                </div>
              )}
              {i === 2 && (
                <div className="how-mstep-email">
                  <div className="me-from">
                    <span className="me-avatar">
                      <img src="/assets/krew-icon-circle.png" alt="" />
                    </span>
                    Krew
                  </div>
                  <div className="me-subj">BLUE Schedule Change Report — 14 changes, 1 conflict</div>
                  <div className="me-snip">
                    Sc. 42 → June 4. Shawn lands LAX 3:08 PM, 7 hrs after his 8 AM call…
                  </div>
                  <div className="me-cta">Open report →</div>
                </div>
              )}
              {i === 3 && (
                <div className="how-mstep-sms">
                  <div className="ms-bubble out">What is Scene 42?</div>
                  <div className="ms-bubble in">Scene 42 is the rooftop chase, 11 AM–3 PM on location. 8 AM call.</div>
                  <div className="ms-bubble out">Shawn's record locator?</div>
                  <div className="ms-bubble in">JSJWLT — Travel memo v3</div>
                </div>
              )}
            </div>
          </div>
        ))}
      </div>
    </section>);

}

function HowPreview({ active }) {
  // All sub-phase values come from CSS custom props on the stage (no rerender on scroll).
  // The docs use calc() against --phase to interpolate continuously.
  const docs = [
  { label: "WHITE Schedule", color: "#FBF7EC" },
  { label: "BLUE Schedule", color: "#BBD4E8" },
  { label: "DOOD v7", color: "#FBF7EC" },
  { label: "TRAVEL MEMO v3", color: "#FBF7EC" },
  { label: "CALL SHEET v12", color: "#FBF7EC" }];


  return (
    <div className="how-visual-stage" data-active={active}>
      {docs.map((d, i) =>
      <div key={i} className={`doc how-doc how-doc-${i} ${i === 1 ? 'is-blue' : ''}`}
      style={{
        background: d.color,
        '--i': i,
        '--offset': i - 2
      }}>
        
          <h5>{d.label}</h5>
          <div className="lines">
            <i></i><i></i><i></i><i></i><i></i>
          </div>
          {i === 1 &&
        <div className="how-hits">
              <div className="hit how-hit-1"></div>
              <div className="hit how-hit-2"></div>
              <div className="hit how-hit-3"></div>
            </div>
        }
        </div>
      )}

      {/* Reading pane — CSS-driven opacity tied to --phase */}
      <div className="how-overlay how-overlay-read" aria-hidden>
        <div className="how-overlay-eyebrow">Cross-check · BLUE vs WHITE schedule</div>
        <div className="how-overlay-body">
          <div><span style={{ color: 'var(--accent)', fontWeight: 800 }}>Δ</span> Sc. 42 moved: June 5 → June 4</div>
          <div><span style={{ color: 'var(--fg-3)', fontWeight: 800 }}>·</span> Travel memo: Shawn landing in LAX at 3:08 PM</div>
          <div><span style={{ color: 'var(--fg-3)', fontWeight: 800 }}>·</span> Call sheet: 8:00 AM call</div>
          <div style={{ color: 'var(--krew-alert)', fontWeight: 700 }}>⚠ Conflict! Flight lands 7 hrs after call</div>
        </div>
      </div>

      {/* Report pane — stripped-down email card, same vocabulary as hero */}
      <div className="how-overlay how-overlay-report" aria-hidden>
        <div className="how-email-mini">
          <div className="how-email-mini-strip">
            <span className="how-email-mini-from">
              <span className="how-email-mini-avatar">
                <img src="/assets/krew-icon-circle.png" alt="" />
              </span>
              Krew
            </span>
            <span className="how-email-mini-time">7:14 AM</span>
          </div>
          <div className="how-email-mini-subj">BLUE Schedule Change Report<br />14 changes, 1 conflict</div>
          <div className="how-email-mini-snip">
            Sc. 42 → June 4. Shawn lands LAX 3:08 PM, 7 hrs after his 8 AM call…
          </div>
          <div className="how-email-mini-cta">Open report →</div>
        </div>
      </div>

      {/* Reply pane */}
      <div className="how-overlay how-overlay-reply" aria-hidden>
        <div className="how-reply-user">
          What is Scene 42? What's his record locator # and when's his call?
        </div>
        <div className="how-reply-krew">
          Scene 42 is the rooftop chase, currently scheduled 11 AM–3 PM on location. 8 AM call time. Stunt work starts at 4 PM.
          <span className="how-reply-src">BLUE One-Liner · Call Sheet · Calendar</span>
        </div>
        <div className="how-reply-krew how-reply-krew-2">
          Shawn's record locator: <strong style={{ color: 'var(--accent)', letterSpacing: '0.06em' }}>JSJWLT</strong>
          <span className="how-reply-src">Travel memo v3</span>
        </div>
      </div>
    </div>);

}

window.HowItWorks = HowItWorks;