const { useState: useS, useEffect: useE, useRef: useR } = React;
const { Reveal, ChapterHead, Counter, InboxFrame, PilotDashboard, GodOSHero, FrameShell, Check, smooth } = window;

/* ===================== PROBLEM ===================== */
function Problem({ copy, motionOn = true }) {
  const p = copy.problem;
  const ref = useR(null);

  useE(() => {
    const sec = ref.current;
    if (!sec) return;
    if (!motionOn) { sec.style.setProperty('--prob-e', '1'); return; }
    let raf = 0;
    const apply = () => {
      raf = 0;
      const r = sec.getBoundingClientRect();
      const ih = window.innerHeight;
      sec.style.setProperty('--prob-e', smooth(ih - r.top, ih * 0.10, ih * 0.6).toFixed(4));
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(apply); };
    apply();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); if (raf) cancelAnimationFrame(raf); };
  }, [motionOn]);

  return (
    <section id="problem" className="problem" ref={ref}>
      <div className="problem-bg" aria-hidden="true"></div>
      <div className="container">
        <div className="stage stage-top">
          <div className="prob-left">
            <ChapterHead
              chapter="01"
              label={p.eyebrow}
              title={<>{p.title[0]}<em>{p.title[1]}</em>{p.title[2]}</>}
              lede={p.lede}
              ledeRight={false}
            />
            <div className="prob-list">
              {p.cards.map((c, i) => (
                <Reveal key={c.t} delay={i * 70} className="prob-row">
                  <div className="prob-row-num mono">0{i + 1}</div>
                  <div className="prob-row-body">
                    <h3 className="prob-row-t serif">{c.t}</h3>
                    <p className="prob-row-d">{c.d}</p>
                    <div className="prob-bar"><span></span></div>
                  </div>
                </Reveal>
              ))}
            </div>
          </div>

          <div className="prob-right">
            <Reveal delay={120}><InboxFrame copy={copy} mode="overflow" /></Reveal>
          </div>
        </div>
      </div>

      <style>{`
        .problem { position: relative; overflow: hidden; padding: 104px 0; }
        .prob-left .ch-mark { margin-bottom: 16px; }
        .prob-left .ch-head { margin-bottom: 24px; }
        .prob-left .ch-title { font-size: clamp(30px, 3.4vw, 50px); max-width: 15ch; }
        .stage-top { align-items: stretch; }
        @media (min-width: 1025px) {
          .stage-top { grid-template-columns: minmax(300px, 4.4fr) 7.6fr; gap: 56px; }
        }
        /* entry bg: warm "cost" wash + a faint time-ruler drifting (hours slipping by) */
        .problem-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: var(--prob-e, 0); }
        .problem-bg::before {
          content: ""; position: absolute; inset: 0;
          background:
            linear-gradient(165deg, rgba(201,162,75,0.12) 0%, transparent 42%),
            radial-gradient(54% 76% at 84% 28%, rgba(201,162,75,0.18), transparent 60%);
        }
        /* drifting time-ruler — minor ticks every 44px + a taller "hour" mark every 264px */
        .problem-bg::after {
          content: ""; position: absolute; inset: 0;
          background-image:
            repeating-linear-gradient(90deg, rgba(28,27,23,0.07) 0 1px, transparent 1px 44px),
            repeating-linear-gradient(90deg, rgba(28,27,23,0.10) 0 1.5px, transparent 1.5px 264px);
          background-position: 0 0, 0 0;
          background-size: auto 22px, auto 46px;
          background-repeat: repeat-x;
          background-position-y: bottom;
          -webkit-mask-image: linear-gradient(90deg, transparent, #000 24%, #000 76%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 24%, #000 76%, transparent);
          opacity: 0.7;
          animation: probDrift 7s linear infinite;
        }
        @keyframes probDrift { from { background-position-x: 0, 0; } to { background-position-x: 264px, 264px; } }
        body.no-motion .problem-bg::after { animation: none; }
        .problem .container { position: relative; z-index: 1; }
        .prob-list { margin-top: 22px; display: flex; flex-direction: column; }
        .prob-row { display: grid; grid-template-columns: 36px 1fr; gap: 14px; padding: 14px 0; border-top: 1px solid var(--line); }
        .prob-row:last-child { border-bottom: 1px solid var(--line); }
        .prob-row-num { font-size: 12px; color: var(--ink-3); letter-spacing: 0.12em; padding-top: 4px; }
        .prob-row-t { font-family: var(--serif); font-size: clamp(18px, 1.9vw, 23px); line-height: 1.15; letter-spacing: -0.02em; color: var(--ink); }
        .prob-row-d { color: var(--ink-2); font-size: 13px; line-height: 1.5; margin: 4px 0 0; }
        .prob-bar { height: 1px; background: var(--line); margin-top: 10px; position: relative; overflow: hidden; }
        .prob-bar span { display: block; height: 100%; width: 0; background: var(--accent); transition: width 1s cubic-bezier(0.2,0.7,0.2,1); }
        .reveal.in .prob-bar span { width: 100%; }
        body.no-motion .prob-bar span { width: 100%; transition: none; }
        .prob-right { display: flex; min-width: 0; }
        .prob-right > .reveal { display: flex; flex: 1; min-width: 0; }
        .prob-right .ws-shell { flex: 1; }
        @media (max-width: 1024px) {
          .prob-right { display: block; }
          .prob-right > .reveal { display: block; }
        }
      `}</style>
    </section>
  );
}

/* ===================== SOLUTION ===================== */
function ChatView({ f }) {
  return (
    <div className="sv sv-chat">
      <div className="sv-head mono">internal_chat · session_42</div>
      <div className="sv-chat-msg user"><div className="bub">{f.q}</div></div>
      <div className="sv-chat-msg ai">
        <div className="bub">
          {f.a}
          <div className="sv-srcs">
            <span className="mono">↳ {f.src}</span>
            <span className="sv-role mono">{f.role}</span>
          </div>
        </div>
      </div>
      <div className="sv-input">
        <span className="mono">▍ frag etwas internes…</span>
        <span className="sv-tag mono">PRIVAT</span>
      </div>
    </div>
  );
}

function EmailView({ f }) {
  return (
    <div className="sv sv-email">
      <div className="sv-head mono"><span style={{ color: 'var(--accent)' }}>●</span> draft · auto-composed</div>
      <div className="sv-mailrow"><span className="sv-l mono">TO</span><span className="sv-v">{f.to}</span></div>
      <div className="sv-mailrow"><span className="sv-l mono">SUBJ</span><span className="sv-v" style={{ color: 'var(--text)' }}>{f.subj}</span></div>
      <p className="sv-body">{f.line}<span className="sv-caret">▍</span></p>
      <div className="sv-actions">
        <span className="sv-pill primary">Approve &amp; send ↗</span>
        <span className="sv-pill">Regenerate</span>
        <span className="sv-pill">Edit</span>
      </div>
    </div>
  );
}

function AnalyzerView({ f }) {
  const tasks = [
    { name: "Rechnungs-Erinnerung", roi: 88, tag: "auto" },
    { name: "Status-Update an PM", roi: 72, tag: "auto" },
    { name: "CRM-Hygiene", roi: 55, tag: "review" }
  ];
  return (
    <div className="sv sv-analyzer">
      <div className="sv-head mono">analyzer · workflow_mining</div>
      {tasks.map((t) => (
        <div className="sv-anrow" key={t.name}>
          <div className="sv-an-top">
            <span className="sv-an-name">{t.name}</span>
            <span className={`sv-an-tag mono ${t.tag}`}>{t.tag === 'auto' ? '◇ AUTOMATISIERBAR' : '◇ REVIEW'}</span>
          </div>
          <div className="sv-anbar"><div className="sv-anbar-fill" style={{ width: `${t.roi}%` }}></div></div>
        </div>
      ))}
      <div className="sv-found">
        <div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--accent)', letterSpacing: '0.12em' }}>● {f.found.toUpperCase()}</div>
          <div style={{ fontSize: 13, color: 'var(--text)', marginTop: 4 }}>{f.detail} · {f.roi}</div>
        </div>
        <span className="sv-pill">{f.roll} →</span>
      </div>
    </div>
  );
}

function Solution({ copy }) {
  const s = copy.solution;
  const [active, setActive] = useS(0);
  const [paused, setPaused] = useS(false);

  useE(() => {
    if (paused || document.body.classList.contains('no-motion')) return;
    const id = setInterval(() => setActive(a => (a + 1) % s.modules.length), 4600);
    return () => clearInterval(id);
  }, [paused, s.modules.length]);

  const views = [ChatView, EmailView, AnalyzerView];

  return (
    <section id="solution" className="solution">
      <div className="container">
        <ChapterHead
          chapter="02"
          label={s.eyebrow}
          title={<>{s.title[0]}<em>{s.title[1]}</em></>}
        />
        <div className="stage sol-stage">
          <div className="sol-left" onMouseLeave={() => setPaused(false)}>
            {s.modules.map((m, i) => (
              <button
                key={m.id}
                className={`sol-row ${i === active ? 'active' : ''}`}
                onMouseEnter={() => { setActive(i); setPaused(true); }}
                onFocus={() => { setActive(i); setPaused(true); }}
                onClick={() => { setActive(i); setPaused(true); }}
              >
                <div className="sol-row-head">
                  <span className="sol-row-num mono">{m.id}</span>
                  <span className="sol-row-t serif">{m.t}</span>
                </div>
                <div className="sol-row-detail">
                  <p className="sol-row-d">{m.d}</p>
                  <div className="sol-feats">
                    {m.features.map((ft) => <span className="sol-feat mono" key={ft}>{ft}</span>)}
                  </div>
                </div>
                <span className="sol-row-bar"><span style={{ animationPlayState: (i === active && !paused) ? 'running' : 'paused' }}></span></span>
              </button>
            ))}
          </div>

          <div className="sol-right">
            <div className="frame sol-frame">
              {s.modules.map((m, i) => {
                const View = views[i];
                return (
                  <div className={`sol-view ${i === active ? 'on' : ''}`} key={m.id} aria-hidden={i !== active}>
                    <View f={m.frame} />
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>

      <style>{`
        .sol-stage { margin-top: 8px; align-items: center; }
        .sol-left { display: flex; flex-direction: column; }
        .sol-row {
          appearance: none; background: none; border: none; text-align: left; cursor: pointer;
          display: block; width: 100%; padding: 24px 0; position: relative;
          border-top: 1px solid var(--line); font-family: var(--sans);
        }
        .sol-left .sol-row:last-child { border-bottom: 1px solid var(--line); }
        .sol-row-head { display: grid; grid-template-columns: 40px 1fr; gap: 14px; align-items: baseline; }
        .sol-row-num { font-size: 12px; color: var(--ink-3); letter-spacing: 0.12em; transition: color 0.3s; }
        .sol-row.active .sol-row-num { color: var(--accent); }
        .sol-row-t { font-family: var(--serif); font-size: clamp(22px, 2.5vw, 32px); line-height: 1.12; letter-spacing: -0.02em; color: var(--ink-3); transition: color 0.3s; }
        .sol-row.active .sol-row-t { color: var(--ink); }
        .sol-row-detail { max-height: 0; overflow: hidden; opacity: 0; transition: max-height 0.5s cubic-bezier(0.2,0.7,0.2,1), opacity 0.4s; padding-left: 54px; }
        .sol-row.active .sol-row-detail { max-height: 180px; opacity: 1; margin-top: 12px; }
        .sol-row-d { color: var(--ink-2); font-size: 14px; line-height: 1.55; margin: 0; max-width: 42ch; }
        .sol-feats { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
        .sol-feat { font-size: 10px; padding: 5px 10px; background: var(--paper-3); border: 1px solid var(--line); border-radius: 999px; color: var(--ink-2); letter-spacing: 0.04em; }
        .sol-row-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: transparent; overflow: hidden; }
        .sol-row.active .sol-row-bar { background: var(--line); }
        .sol-row-bar span { display: block; height: 100%; width: 0; background: var(--accent); }
        .sol-row.active .sol-row-bar span { animation: solFill 4.6s linear forwards; }
        @keyframes solFill { from { width: 0; } to { width: 100%; } }
        body.no-motion .sol-row-detail { max-height: none; opacity: 1; margin-top: 12px; }
        body.no-motion .sol-row-bar span { animation: none; }
        body.no-motion .sv-caret { animation: none; }

        .sol-right { position: relative; }
        .sol-frame {
          position: relative; min-height: 440px;
          background: linear-gradient(180deg, #0E1014, var(--bg));
          border: 1px solid var(--line); border-radius: var(--r-frame);
          box-shadow: var(--sh-frame); overflow: hidden; padding: 26px;
          display: flex; align-items: center; justify-content: center;
        }
        .sol-view { position: absolute; inset: 26px; opacity: 0; transform: translateY(8px) scale(0.99); transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.2,0.7,0.2,1); display: flex; align-items: center; justify-content: center; pointer-events: none; }
        .sol-view.on { opacity: 1; transform: none; pointer-events: auto; }
        body.no-motion .sol-view { transition: none; }

        /* shared solution-view (dark, inside .frame) */
        .sv { width: 100%; max-width: 460px; display: flex; flex-direction: column; gap: 13px; }
        .sv-head { font-size: 10px; color: var(--text-3); letter-spacing: 0.14em; padding-bottom: 12px; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 6px; }

        .sv-chat-msg { display: flex; }
        .sv-chat-msg.user { justify-content: flex-end; }
        .sv-chat-msg .bub { max-width: 82%; padding: 12px 14px; border-radius: 14px; font-size: 13px; line-height: 1.5; }
        .sv-chat-msg.user .bub { background: rgba(255,255,255,0.06); color: var(--text); border-top-right-radius: 4px; }
        .sv-chat-msg.ai .bub { background: rgba(0,0,0,0.35); border: 1px solid var(--line); color: var(--text-2); border-top-left-radius: 4px; }
        .sv-srcs { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed rgba(255,255,255,0.08); font-size: 10px; color: var(--text-3); }
        .sv-role { color: var(--accent); }
        .sv-input { margin-top: 2px; display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; font-size: 12px; color: var(--text-3); }
        .sv-tag { font-size: 9px; padding: 3px 8px; background: var(--accent-soft); color: var(--accent); border-radius: 999px; border: 1px solid var(--accent-line); }

        .sv-mailrow { display: flex; gap: 12px; font-size: 12px; padding: 8px 0; border-bottom: 1px dashed rgba(255,255,255,0.06); }
        .sv-l { color: var(--text-3); width: 38px; }
        .sv-v { color: var(--text-2); }
        .sv-body { font-size: 13px; color: var(--text); line-height: 1.6; margin: 8px 0 4px; }
        .sv-caret { display: inline-block; width: 7px; color: var(--accent); animation: blink 1s steps(2) infinite; }
        .sv-actions { display: flex; gap: 8px; flex-wrap: wrap; }
        .sv-pill { font-size: 11px; padding: 7px 12px; background: rgba(255,255,255,0.04); border: 1px solid var(--line); color: var(--text-2); border-radius: 999px; }
        .sv-pill.primary { background: var(--text); color: #0a0a0a; border-color: var(--text); }

        .sv-anrow { padding: 10px 0; border-top: 1px dashed rgba(255,255,255,0.06); }
        .sv-anrow:first-of-type { border-top: 1px solid var(--line); }
        .sv-an-top { display: flex; justify-content: space-between; gap: 10px; align-items: center; }
        .sv-an-name { font-size: 13px; color: var(--text); }
        .sv-an-tag { font-size: 9px; padding: 3px 7px; border-radius: 4px; letter-spacing: 0.08em; }
        .sv-an-tag.auto { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-line); }
        .sv-an-tag.review { background: rgba(201,162,75,0.12); color: var(--warn); border: 1px solid rgba(201,162,75,0.3); }
        .sv-anbar { height: 3px; background: rgba(255,255,255,0.06); border-radius: 2px; margin-top: 8px; overflow: hidden; }
        .sv-anbar-fill { height: 100%; background: var(--accent); }
        .sv-found { margin-top: 6px; padding: 12px; background: rgba(255,255,255,0.025); border: 1px dashed var(--accent-line); border-radius: 8px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
      `}</style>
    </section>
  );
}

/* ===================== PROOF (results + security + pilot) ===================== */
function TrustIcon({ i }) {
  const paths = [
    <g key="0"><path d="M10 2l7 4v5c0 4-3 7-7 8-4-1-7-4-7-8V6l7-4z" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinejoin="round" /></g>,
    <g key="1"><rect x="4" y="8" width="12" height="9" rx="2" stroke="currentColor" strokeWidth="1.3" fill="none" /><path d="M6 8V6a4 4 0 018 0v2" stroke="currentColor" strokeWidth="1.3" fill="none" /></g>,
    <g key="2"><circle cx="10" cy="7" r="3" stroke="currentColor" strokeWidth="1.3" fill="none" /><path d="M4 17c0-3 3-5 6-5s6 2 6 5" stroke="currentColor" strokeWidth="1.3" fill="none" /></g>,
    <g key="3"><path d="M3 10h14 M5 10V7a5 5 0 0110 0v3 M8 14h4" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinecap="round" /></g>,
  ];
  return <svg width="18" height="18" viewBox="0 0 20 20">{paths[i]}</svg>;
}

/* ---------- TreviFlagship: local Trevi-payment frame for the flagship carousel
   (built here on purpose — TreviPay lives in ecosystem.jsx which loads later) ---------- */
function TreviFlagship({ copy }) {
  const f = copy.trevi.frame;
  return (
    <FrameShell copy={copy} title={f.label} liveLabel="live" activeNav={0} sidebar={["Pay", "Wallet", "Cashback", "Coin", "Treasury", "Settings"]}>
      <div className="ws-card fl-pay">
        <div className="ws-card-head">
          <div className="ws-card-eyebrow mono"><span className="dot"></span>{f.label}</div>
          <div className="mono fl-method">⚡ {f.method}</div>
        </div>
        <div className="fl-amount"><span className="ws-bignum">{f.amount}</span><span className="mono fl-unit">{f.unit}</span></div>
        <div className="fl-paybody">
          <div className="fl-qr" aria-hidden="true">
            {Array.from({ length: 36 }).map((_, i) => <span key={i} className={(i * 7 + (i % 5)) % 3 === 0 ? 'on' : ''}></span>)}
          </div>
          <div className="fl-paymeta">
            <div className="fl-addr mono">{f.addr}</div>
            <div className="fl-row"><span className="mono fl-l">{f.statusLabel}</span><span className="fl-status"><span className="fl-status-dot"></span>{f.statusVal}</span></div>
            <div className="fl-cashback mono">{f.cashback}</div>
          </div>
        </div>
      </div>
      <div className="ws-card fl-coin">
        <div className="ws-card-head">
          <div className="ws-card-eyebrow mono"><span className="dot"></span>{f.coin}</div>
        </div>
        <div className="fl-coinbal"><span className="fl-coin-mark"></span><span className="ws-bignum">{f.coinVal}</span></div>
      </div>
      <style>{`
        .fl-pay { background: linear-gradient(180deg, rgba(91,147,184,0.07), rgba(255,255,255,0.005)); }
        .fl-method { font-size: 11px; color: var(--warn); }
        .fl-amount { display: flex; align-items: baseline; gap: 8px; margin-top: 12px; }
        .fl-unit { font-size: 12px; color: var(--text-3); }
        .fl-paybody { display: grid; grid-template-columns: 92px 1fr; gap: 16px; margin-top: 16px; align-items: center; }
        .fl-qr { width: 92px; height: 92px; display: grid; grid-template-columns: repeat(6, 1fr); grid-auto-rows: 1fr; gap: 2px; padding: 8px; background: #fff; border-radius: 8px; }
        .fl-qr span { background: transparent; border-radius: 1px; }
        .fl-qr span.on { background: #0B0C0E; }
        .fl-addr { font-size: 11px; color: var(--text-2); word-break: break-all; }
        .fl-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; }
        .fl-l { font-size: 11px; color: var(--text-3); }
        .fl-status { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--good); }
        .fl-status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--good); box-shadow: 0 0 8px var(--good); }
        .fl-cashback { margin-top: 10px; font-size: 11px; color: var(--good); }
        .fl-coinbal { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
        .fl-coin-mark { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), #6FA8C9); box-shadow: 0 0 0 4px rgba(91,147,184,0.14); flex-shrink: 0; }
      `}</style>
    </FrameShell>
  );
}

/* ---------- ProductShot: a REAL product screenshot (images/*.png) wrapped in a
   macOS window frame, matching the dark FrameShell siblings in the carousel ---------- */
function ProductShot({ src, alt, title, chrome = true }) {
  return (
    <div className={`shot frame ${chrome ? '' : 'shot-bare'}`}>
      {chrome && (
        <div className="shot-chrome">
          <div className="shot-dots">
            <span style={{ background: '#ff5f57' }}></span>
            <span style={{ background: '#ffbd2e' }}></span>
            <span style={{ background: '#28c941' }}></span>
          </div>
          <div className="shot-title mono">{title}</div>
          <div className="shot-tools mono"><span className="shot-live"></span> live</div>
        </div>
      )}
      <img src={src} alt={alt} loading="lazy" />
      <style>{`
        .shot {
          width: 100%;
          border-radius: var(--r-frame);
          overflow: hidden;
          border: 1px solid rgba(255,255,255,0.10);
          box-shadow: 0 30px 90px -24px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.05);
          background: #0B0C0E;
          display: flex;
          flex-direction: column;
          transition: transform 0.45s cubic-bezier(0.2,0.7,0.2,1), box-shadow 0.45s cubic-bezier(0.2,0.7,0.2,1);
          will-change: transform;
        }
        /* images carry the proof — lift + scale a touch on hover */
        .shot:hover { transform: scale(1.028); box-shadow: 0 46px 116px -28px rgba(0,0,0,0.82), 0 0 0 1px rgba(255,255,255,0.09); }
        body.no-motion .shot { transition: none; }
        body.no-motion .shot:hover { transform: none; }
        /* macOS window chrome — matches the FrameShell siblings (tokens from .frame) */
        .shot-chrome { display: flex; align-items: center; gap: 16px; padding: 12px 16px; border-bottom: 1px solid var(--line); background: rgba(255,255,255,0.015); flex-shrink: 0; }
        .shot-dots { display: flex; gap: 6px; }
        .shot-dots span { width: 11px; height: 11px; border-radius: 50%; display: block; }
        .shot-title { flex: 1; font-size: 11px; color: var(--text-3); text-align: center; letter-spacing: 0.04em; }
        .shot-tools { font-size: 11px; color: var(--text-3); display: flex; align-items: center; gap: 6px; }
        .shot-live { width: 6px; height: 6px; border-radius: 50%; background: var(--good); box-shadow: 0 0 8px var(--good); }
        .shot img { display: block; width: 100%; height: auto; }
      `}</style>
    </div>
  );
}

/* ---------- FlowDiagram: explains each flagship's REAL named flow (honest, figure-free)
   pipeline = sequential steps with arrows; hub = one core powering N capabilities ---------- */
function FlowDiagram({ flow }) {
  if (!flow) return null;
  if (flow.kind === 'hub') {
    return (
      <div className="fl-flow fl-flow-hub">
        <span className="fl-flow-label mono">{flow.label}</span>
        <div className="fl-hub">
          <div className="fl-hub-core">
            <span className="fl-hub-core-mark"></span>
            <span className="fl-hub-core-t serif">{flow.center}</span>
          </div>
          <span className="fl-hub-link" aria-hidden="true"></span>
          <div className="fl-hub-grid">
            {flow.steps.map((s, i) => (
              <span key={s} className="fl-hub-node" style={{ '--si': i }}><span className="fl-hub-dot"></span>{s}</span>
            ))}
          </div>
        </div>
      </div>
    );
  }
  return (
    <div className="fl-flow fl-flow-pipe">
      <span className="fl-flow-label mono">{flow.label}</span>
      <div className="fl-pipe">
        {flow.steps.map((s, i) => (
          <div className="fl-step" key={s} style={{ '--si': i }}>
            <span className="fl-step-label">
              <span className="fl-step-num mono">{String(i + 1).padStart(2, '0')}</span>
              <span className="fl-step-t">{s}</span>
            </span>
            {i < flow.steps.length - 1 && (
              <span className="fl-arrow" aria-hidden="true" style={{ '--si': i }}>
                <span className="fl-arrow-line"></span>
                <span className="fl-arrow-spark"></span>
              </span>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- Flagships: SCROLL-PINNED stage — GodOS · Realit · Trevi.
   The stage STICKS in the viewport while you scroll; the three projects shift
   1 → 2 → 3, then it releases and the page continues. Uses NATIVE position:sticky
   (compositor-driven → smooth on macOS momentum scroll; a JS translateY pin visibly
   "swims"/lags). The usual blockers were cleared: body is overflow-x:clip (not a
   scroll container), .proof.dark-room is overflow:clip, and Proof drops its scale
   transform + will-change once fully entered (which is exactly when the flagship pins).
   JS only sets the spacer height + sticky `top`, and reads progress to drive the rail. */
function Flagships({ copy, motionOn = true }) {
  const p = copy.proof;
  const slides = p.flagships;
  const n = slides.length;
  const [active, setActive] = useS(0);
  const pinRef = useR(null);                 // tall outer spacer (drives the scroll distance)
  const stickyRef = useR(null);              // inner block held in place during the pin

  const metrics = () => {
    const vh = window.innerHeight;
    const stickyH = stickyRef.current.offsetHeight;
    const span = vh * 0.82 * n;              // scroll distance spent pinned (≈0.82vh per slide)
    const pinTop = Math.max(72, (vh - stickyH) / 2);
    return { vh, stickyH, span, pinTop };
  };

  useE(() => {
    const pin = pinRef.current, sticky = stickyRef.current;
    if (!pin || !sticky) return;
    const reset = () => { pin.style.height = ''; sticky.style.top = ''; sticky.style.removeProperty('--p'); };
    if (!motionOn || document.body.classList.contains('no-motion')) { reset(); return; }
    let raf = 0;
    // give the spacer its scroll length and tell the sticky where to pin — the
    // PINNING itself is native CSS position:sticky (compositor-driven = perfectly smooth).
    const layout = () => { const { span, stickyH, pinTop } = metrics(); pin.style.height = (stickyH + span) + 'px'; sticky.style.top = pinTop + 'px'; };
    const apply = () => {
      raf = 0;
      const { span, pinTop } = metrics();
      const top = pin.getBoundingClientRect().top;
      // progress 0 (just pinned) → 1 (about to release); JS only reads it to drive the
      // rail fill + active slide — it never moves the heavy content, so no scroll-lag swim.
      let t = (pinTop - top) / span;
      t = t < 0 ? 0 : t > 1 ? 1 : t;
      sticky.style.setProperty('--p', t.toFixed(4));
      const idx = Math.max(0, Math.min(n - 1, Math.floor(t * n - 1e-6)));
      setActive(prev => (prev === idx ? prev : idx));
    };
    layout(); apply();
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(apply); };
    const onResize = () => { layout(); apply(); };
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onResize, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onResize); if (raf) cancelAnimationFrame(raf); };
  }, [n, motionOn]);

  // rail click / mobile tap → scroll to the slide's pinned position (or just switch under no-motion)
  const goTo = (i) => {
    const pin = pinRef.current;
    if (!pin || !motionOn || document.body.classList.contains('no-motion')) { setActive(i); return; }
    const { span, pinTop } = metrics();
    const regionTopDoc = pin.getBoundingClientRect().top + window.scrollY;
    const targetY = ((i + 0.5) / n) * span - pinTop + regionTopDoc;
    if (window.__lenis) window.__lenis.scrollTo(targetY);   // scroll through Lenis so it doesn't fight the smooth-scroll
    else window.scrollTo({ top: targetY, behavior: 'smooth' });
  };

  const frame = (key) => key === 'godos' ? <ProductShot src="images/God.png" alt="GodOS — chat, business and money in one workspace" title="godos · chat" />
    : key === 'trevi' ? <ProductShot src="images/Trevi.png" alt="Trevi — BTC & Lightning payments, cashback and treasury" title="trevi · pay" />
    : <PilotDashboard copy={copy} />;

  const cur = slides[active];

  return (
    <div className="proof-flag-pin" ref={pinRef}>
      <div className="proof-flag-sticky" ref={stickyRef}>
        <div className="proof-flag-head">
          <span className="eyebrow proof-flag-eyebrow">{p.flagshipsEyebrow}</span>
          <div className="proof-flag-rail" role="tablist">
            {slides.map((s, i) => (
              <button key={s.key} className={`proof-flag-railitem ${i === active ? 'on' : ''} ${i < active ? 'done' : ''}`} onClick={() => goTo(i)} aria-label={s.name} aria-selected={i === active}>
                <span className="proof-flag-railnum mono">{String(i + 1).padStart(2, '0')}</span>
                <span className="proof-flag-railname">{s.name}</span>
                <span className="proof-flag-railbar"><span style={{ '--ri': i }}></span></span>
              </button>
            ))}
          </div>
        </div>

        <div className="proof-flag-stage">
          <div className="proof-flag-top">
            <div className="proof-flag-left" key={'l' + active}>
              <div className="proof-flag-tag mono">{cur.tag}</div>
              <h3 className="proof-flag-name serif">{cur.name}</h3>
              <p className="proof-flag-desc">{cur.desc}</p>
              <div className="proof-flag-live mono"><span className="pulse-dot" style={{ position: 'static' }}></span>{cur.caption}</div>
            </div>
            <div className="proof-flag-right">
              <div className="proof-flag-frame" key={'f' + active}>{frame(cur.key)}</div>
            </div>
          </div>
          <div className="proof-flag-flowbar" key={'w' + active}>
            <FlowDiagram flow={cur.flow} />
          </div>
        </div>
      </div>

      <style>{`
        /* full-bleed breakout: the pinned stage spans wider than the 1280 container.
           overflow-anchor:none stops the browser nudging scroll when the active slide remounts. */
        .proof-flag-pin { position: relative; margin: 72px calc(50% - 50vw) 0; width: 100vw; overflow-anchor: none; }
        /* native scroll-pin: compositor handles it (smooth on macOS momentum scroll). top set by JS. */
        .proof-flag-sticky { width: min(1560px, 100% - 64px); margin: 0 auto; padding-top: 40px; border-top: 1px solid var(--line); position: sticky; }

        .proof-flag-head { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: 28px; flex-wrap: wrap; }
        .proof-flag-eyebrow::before { background: #C9A24B; }
        .proof-flag-rail { display: flex; gap: 10px; flex: 1; max-width: 560px; min-width: 280px; }
        .proof-flag-railitem { appearance: none; background: none; border: none; cursor: pointer; padding: 0; flex: 1; text-align: left; display: flex; flex-direction: column; gap: 8px; opacity: 0.5; transition: opacity 0.35s; }
        .proof-flag-railitem.on, .proof-flag-railitem.done { opacity: 1; }
        .proof-flag-railnum { font-size: 10px; color: #C9A24B; letter-spacing: 0.14em; }
        .proof-flag-railname { font-size: 13px; color: var(--ink); letter-spacing: -0.01em; }
        .proof-flag-railitem:not(.on) .proof-flag-railname { color: var(--ink-3); }
        .proof-flag-railbar { display: block; height: 3px; border-radius: 2px; background: var(--line-2); overflow: hidden; }
        /* fill is computed live from --p (scroll progress, set per-frame on .proof-flag-sticky)
           and the item's own --ri — pure CSS, so it updates without a React re-render */
        .proof-flag-railbar > span { display: block; height: 100%; background: #C9A24B; transform-origin: left; transform: scaleX(clamp(0, calc(var(--p, 0) * ${n} - var(--ri, 0)), 1)); }

        .proof-flag-stage { height: clamp(540px, 70vh, 660px); display: flex; flex-direction: column; gap: 16px; }
        .proof-flag-top { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(300px, 4.4fr) 7.6fr; grid-template-rows: minmax(0, 1fr); gap: 46px; align-items: center; }
        .proof-flag-left { min-width: 0; }
        .proof-flag-tag { font-size: 11px; color: #C9A24B; letter-spacing: 0.16em; }
        .proof-flag-name { font-size: clamp(34px, 4.2vw, 54px); line-height: 1.02; letter-spacing: -0.028em; color: var(--ink); margin-top: 14px; }
        .proof-flag-desc { color: var(--ink-2); font-size: 15.5px; line-height: 1.62; max-width: 46ch; margin: 16px 0 0; }
        .proof-flag-live { display: inline-flex; align-items: center; gap: 9px; margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 11px; color: var(--ink-2); letter-spacing: 0.06em; text-transform: uppercase; }
        .proof-flag-right { display: flex; min-width: 0; height: 100%; position: relative; align-items: center; }
        .proof-flag-right::before {
          content: ""; position: absolute; z-index: 0; inset: -8% -6%;
          background: radial-gradient(58% 62% at 58% 44%, rgba(201,162,75,0.18), rgba(201,162,75,0.05) 42%, transparent 72%);
          filter: blur(10px); pointer-events: none;
        }
        .proof-flag-frame { display: flex; flex: 1; min-width: 0; width: 100%; height: 100%; position: relative; z-index: 1; justify-content: center; }
        /* let the dark product window shrink to the fixed stage height instead of forcing 440px */
        .proof-flag-frame .ws-shell { height: 100%; }
        .proof-flag-frame .ws-body { min-height: 0; }
        /* screenshot frames are locked to the image's ~16/10 proportion + centred, so they
           read as a real window instead of a too-wide crop (the column is wider than this). */
        /* height-driven 3:2 window: the image area lands at ~native 16/10 once the chrome bar is
           subtracted, so the screenshot shows in full (no info cut) while still filling the wide column */
        .proof-flag-frame .shot { height: 100%; width: auto; aspect-ratio: 3 / 2; max-width: 100%; flex: 0 0 auto; align-self: center; }
        .proof-flag-frame .shot img { flex: 1 1 0; min-height: 0; object-fit: cover; object-position: top center; }
        .proof-flag-left, .proof-flag-frame, .proof-flag-flowbar { animation: flagIn 0.6s cubic-bezier(0.2,0.7,0.2,1) both; }
        @keyframes flagIn { from { opacity: 0; transform: translateY(18px) scale(0.99); } to { opacity: 1; transform: none; } }
        body.no-motion .proof-flag-left, body.no-motion .proof-flag-frame, body.no-motion .proof-flag-flowbar { animation: none; }

        /* ---- the explanatory flow "graph" — full width under the stage ---- */
        .proof-flag-flowbar { border-top: 1px solid var(--line); padding-top: 13px; }
        .fl-flow-label { display: block; font-size: 10px; color: var(--ink-3); letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 9px; }
        /* evenly-spaced steps; number floats ABOVE the label so the connector aligns with the label's centre */
        .fl-pipe { display: flex; align-items: center; padding-top: 15px; }
        .fl-step { flex: 1; min-width: 0; display: flex; align-items: center; }
        .fl-step:last-child { flex: 0 0 auto; }
        .fl-step-label { flex-shrink: 0; position: relative; }
        .fl-step-num { position: absolute; bottom: calc(100% + 7px); left: 0; font-size: 10px; color: #C9A24B; letter-spacing: 0.12em; }
        .fl-step-t { display: block; font-size: clamp(15px, 1.4vw, 19px); color: var(--ink); letter-spacing: -0.015em; white-space: nowrap; }
        .fl-arrow { position: relative; flex: 1; min-width: 32px; height: 2px; margin: 0 18px; }
        .fl-arrow-line { position: absolute; inset: 0; background: linear-gradient(90deg, var(--line-2), var(--line-2)); }
        .fl-arrow-line::after { content: ""; position: absolute; right: -1px; top: -3px; width: 7px; height: 7px; border-top: 1.5px solid var(--line-2); border-right: 1.5px solid var(--line-2); transform: rotate(45deg); }
        .fl-arrow-spark { position: absolute; top: -2px; left: 0; width: 26px; height: 6px; border-radius: 3px; background: linear-gradient(90deg, transparent, #C9A24B); filter: blur(0.5px); opacity: 0.9; animation: flSpark 2.6s cubic-bezier(0.5,0,0.5,1) infinite; animation-delay: calc(var(--si) * 0.5s); }
        @keyframes flSpark { 0% { left: -28px; opacity: 0; } 30% { opacity: 0.95; } 70% { opacity: 0.95; } 100% { left: 100%; opacity: 0; } }
        body.no-motion .fl-arrow-spark { display: none; }

        .fl-hub { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
        .fl-hub-core { display: inline-flex; align-items: center; gap: 12px; padding: 12px 20px; border: 1px solid var(--accent-line); background: var(--accent-soft); border-radius: 14px; }
        .fl-hub-core-mark { width: 22px; height: 22px; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #E9CE86, #C9A24B 70%); box-shadow: 0 0 0 4px rgba(201,162,75,0.14), 0 0 18px rgba(201,162,75,0.4); }
        .fl-hub-core-t { font-size: 22px; color: var(--ink); letter-spacing: -0.01em; }
        .fl-hub-link { width: 36px; height: 2px; background: linear-gradient(90deg, var(--accent-line), transparent); flex-shrink: 0; }
        .fl-hub-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; flex: 1; min-width: 320px; }
        .fl-hub-node { display: inline-flex; align-items: center; gap: 8px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; font-size: 13px; color: var(--ink); background: var(--paper-2); white-space: nowrap; min-width: 0; }
        .fl-hub-node { overflow: hidden; text-overflow: ellipsis; }
        .fl-hub-dot { width: 7px; height: 7px; border-radius: 50%; background: #C9A24B; box-shadow: 0 0 8px rgba(201,162,75,0.6); flex-shrink: 0; }

        @media (max-width: 1024px) {
          .proof-flag-pin { height: auto !important; margin-top: 56px; }
          .proof-flag-sticky { position: static !important; top: auto !important; width: 100%; }
          .proof-flag-stage { height: auto; }
          .proof-flag-top { grid-template-columns: 1fr; gap: 32px; }
          .proof-flag-right, .proof-flag-frame { display: block; height: auto; }
          .proof-flag-frame .ws-shell { height: auto; }
          .proof-flag-frame .shot { height: auto; width: 100%; aspect-ratio: auto; }
          .proof-flag-frame .shot img { flex: none; }
          .fl-hub-grid { grid-template-columns: repeat(3, 1fr); }
        }
        @media (max-width: 600px) {
          .proof-flag-rail { flex-wrap: wrap; }
          .fl-pipe { flex-direction: column; align-items: flex-start; gap: 26px; padding-top: 20px; }
          .fl-step { flex: none; width: 100%; }
          .fl-arrow { display: none; }
          .fl-hub-grid { grid-template-columns: 1fr 1fr; }
        }
      `}</style>
    </div>
  );
}

function Proof({ copy, motionOn = true }) {
  const p = copy.proof;
  const ref = useR(null);

  useE(() => {
    const sec = ref.current;
    if (!sec) return;
    if (!motionOn) { sec.style.setProperty('--enter', '1'); sec.style.transform = ''; sec.style.willChange = ''; return; }
    let raf = 0;
    const apply = () => {
      raf = 0;
      const r = sec.getBoundingClientRect();
      const ih = window.innerHeight;
      // scene entrance: content rises + fades as the dark room scrolls into view
      const e = smooth(ih - r.top, ih * 0.10, ih * 0.50);
      sec.style.setProperty('--enter', e.toFixed(4));
      // Once fully entered, DROP the scale transform + will-change so the room no longer
      // creates a containing block — that's what lets the flagship inside use native
      // position:sticky (smooth pin). During entrance the flagship is still below the
      // viewport, so the grow animation (shared .dark-room CSS) is unaffected.
      if (e > 0.999) { sec.style.transform = 'none'; sec.style.willChange = 'auto'; }
      else { sec.style.transform = ''; sec.style.willChange = ''; }
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(apply); };
    apply();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); if (raf) cancelAnimationFrame(raf); };
  }, [motionOn]);

  return (
    <section id="proof" className="proof section-dark dark-room" ref={ref}>
      <div className="proof-bg" aria-hidden="true"><div className="proof-aurora"></div></div>
      <div className="container">
        <ChapterHead
          chapter="02"
          label={p.eyebrow}
          title={<>{p.title[0]}<em>{p.title[1]}</em></>}
          lede={p.lede}
        />

        {/* Tier 1 — qualitative proof (no figures) */}
        <div className="proof-stats">
          {p.stats.map((s, i) => (
            <Reveal key={s.word} delay={i * 90} className="proof-stat">
              <div className="proof-stat-n proof-stat-word serif">{s.word}</div>
              <div className="proof-stat-t">{s.t}</div>
              <div className="proof-stat-d mono">{s.d}</div>
            </Reveal>
          ))}
        </div>

        {/* Tier 2 — real clients */}
        <div className="proof-trust">
          <div className="proof-trust-head">
            <span className="eyebrow">{p.clientsEyebrow}</span>
            <span className="proof-trust-note mono">{p.clientsNote}</span>
          </div>
          <div className="proof-trust-grid">
            {p.clients.map((t) => (
              <Reveal key={t.t} delay={0} className="proof-trust-item">
                <div className="proof-client-mark">{t.t.charAt(0)}</div>
                <div>
                  <div className="proof-trust-t">{t.t}</div>
                  <div className="proof-trust-d mono">{t.d}</div>
                </div>
              </Reveal>
            ))}
          </div>
          <div className="proof-ticker">
            <span className="proof-ticker-l mono">● {p.clientsNote}</span>
            <div className="proof-ticker-marquee">
              <div className="proof-ticker-track">
                {[...p.ticker, ...p.ticker].map((u, i) => <span className="proof-ticker-url mono" key={i}>{u}</span>)}
              </div>
            </div>
          </div>
        </div>

        {/* Tier 3 — flagship carousel: GodOS · Realit · Trevi */}
        <Flagships copy={copy} motionOn={motionOn} />
      </div>

      <style>{`
        /* bg, rounded sheet + scene entrance come from the shared .dark-room primitive.
           Proof drops the soft .room-fade bottom gradient — instead the dark room is a
           CONTAINED panel: rounded bottom corners that sit cleanly on the cream below. */
        /* overflow:clip (NOT hidden) clips the rounded corners WITHOUT becoming a scroll
           container — so the flagship inside can pin with native position:sticky. */
        .proof.dark-room { border-bottom-left-radius: 38px; border-bottom-right-radius: 38px; padding-bottom: 120px; overflow: clip; }
        @media (max-width: 900px) { .proof.dark-room { border-bottom-left-radius: 26px; border-bottom-right-radius: 26px; } }
        .proof-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
        .section-dark .proof-stat-n { text-shadow: 0 0 38px rgba(244,241,233,0.10); }
        .section-dark .proof-pilot-n { text-shadow: 0 0 30px rgba(244,241,233,0.08); }
        .section-dark .ws-shell { border-color: rgba(255,255,255,0.10); box-shadow: 0 30px 90px -24px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.05); }
        .proof-aurora { position: absolute; inset: 0; opacity: 0.55; pointer-events: none;
          background:
            radial-gradient(40% 50% at 78% 28%, rgba(91,147,184,0.16), transparent 70%),
            radial-gradient(46% 54% at 14% 82%, rgba(201,162,75,0.10), transparent 72%);
          animation: proofAurora 24s ease-in-out infinite alternate; will-change: transform; }
        @keyframes proofAurora { from { transform: translate3d(-3%,-2%,0) scale(1.05); } to { transform: translate3d(4%,3%,0) scale(1.18); } }
        body.no-motion .proof-aurora { animation: none; }
        .proof-stat-n.proof-stat-word { font-size: clamp(34px, 4vw, 62px); }
        .proof-pilot-live { display: inline-flex; align-items: center; gap: 9px; margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--line); font-size: 11px; color: var(--ink-2); letter-spacing: 0.06em; text-transform: uppercase; }
        .proof-ticker-marquee { flex: 1; min-width: 0; overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
        .proof-ticker-track { display: inline-flex; gap: 10px; white-space: nowrap; animation: proofTicker 26s linear infinite; }
        .proof-ticker-marquee:hover .proof-ticker-track { animation-play-state: paused; }
        @keyframes proofTicker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
        body.no-motion .proof-ticker-track { animation: none; flex-wrap: wrap; white-space: normal; }

        .proof-stats { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); border-left: 1px solid var(--line); margin-bottom: 0; }
        @media (max-width: 900px) { .proof-stats { grid-template-columns: repeat(2, 1fr); } }
        @media (max-width: 520px) { .proof-stats { grid-template-columns: 1fr; } }
        .proof-stat { padding: 34px 26px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); display: flex; flex-direction: column; min-height: 200px; }
        .proof-stat-n { font-size: clamp(56px, 7vw, 104px); line-height: 0.92; letter-spacing: -0.04em; color: var(--ink); }
        .proof-stat-t { font-size: 17px; color: var(--ink); margin-top: auto; padding-top: 22px; }
        .proof-stat-d { font-size: 11px; color: var(--ink-3); margin-top: 6px; letter-spacing: 0.04em; }

        .proof-trust { margin-top: 64px; padding-top: 40px; border-top: 1px solid var(--line); }
        .proof-trust-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 28px; }
        .proof-trust-note { font-size: 10px; color: var(--ink-3); letter-spacing: 0.12em; border: 1px solid var(--line); padding: 5px 10px; border-radius: 999px; }
        .proof-trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 28px; }
        @media (max-width: 900px) { .proof-trust-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; } }
        @media (max-width: 520px) { .proof-trust-grid { grid-template-columns: 1fr; } }
        .proof-trust-item { display: grid; grid-template-columns: 34px 1fr; gap: 12px; align-items: start; }
        .proof-trust-icon { color: var(--ink-2); margin-top: 1px; }
        .proof-client-mark { width: 32px; height: 32px; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-family: var(--serif); font-size: 17px; color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-line); }
        .proof-trust-t { font-size: 14px; color: var(--ink); line-height: 1.3; }
        .proof-trust-d { font-size: 11px; color: var(--ink-3); margin-top: 4px; letter-spacing: 0.04em; }
        .proof-ticker { margin-top: 32px; padding-top: 22px; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
        .proof-ticker-l { font-size: 10px; color: var(--accent); letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap; }
        .proof-ticker-urls { display: flex; gap: 10px; flex-wrap: wrap; }
        .proof-ticker-url { font-size: 11px; color: var(--ink-3); padding: 5px 11px; border: 1px solid var(--line); border-radius: 999px; }

        .proof-pilot { margin-top: 72px; padding-top: 56px; border-top: 1px solid var(--line); align-items: center; }
        .proof-pilot-eyebrow::before { background: var(--accent); }
        .proof-pilot-name { font-size: clamp(32px, 4vw, 48px); line-height: 1.04; letter-spacing: -0.025em; color: var(--ink); margin-top: 18px; }
        .proof-pilot-desc { color: var(--ink-2); font-size: 15px; line-height: 1.6; max-width: 44ch; margin: 14px 0 0; }
        .proof-pilot-metric { display: flex; align-items: baseline; gap: 12px; margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--line); }
        .proof-pilot-n { font-size: clamp(40px, 5vw, 64px); line-height: 1; letter-spacing: -0.035em; color: var(--ink); }
        .proof-pilot-l { font-size: 14px; color: var(--ink-2); }
      `}</style>
    </section>
  );
}

/* ===================== CTA ===================== */
function CTA({ copy }) {
  const c = copy.cta;
  const ref = useR(null);
  const [entered, setEntered] = useS(false);
  useE(() => {
    const el = ref.current;
    if (!el) return;
    if (document.body.classList.contains('no-motion')) { setEntered(true); return; }
    const io = new IntersectionObserver((es) => {
      es.forEach(e => { if (e.isIntersecting) { setEntered(true); io.unobserve(e.target); } });
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <section id="cta" className={`cta ${entered ? 'entered' : ''}`} ref={ref}>
      <div className="cta-fill" aria-hidden="true"></div>
      <div className="container">
        <div className="stage cta-stage">
          <div className="cta-left">
            <Reveal><div className="eyebrow">{c.eyebrow}</div></Reveal>
            <Reveal delay={80}>
              <h2 className="cta-title serif">{c.title[0]}<em>{c.title[1]}</em></h2>
            </Reveal>
            <Reveal delay={150}><p className="cta-lede">{c.lede}</p></Reveal>
            <Reveal delay={220}>
              <div className="cta-actions">
                <a href="mailto:hello@business-ai.com" className="btn btn-primary cta-btn">{c.btn1} <span className="arrow">↗</span></a>
                <a href="mailto:hello@business-ai.com" className="btn btn-ghost cta-btn">{c.btn2}</a>
              </div>
            </Reveal>
            <Reveal delay={300}><span className="cta-note mono">{c.note}</span></Reveal>
          </div>
          <div className="cta-right">
            <Reveal delay={160}>
              <div className="cta-stack">
                <div className="cta-stack-head mono">{c.stackTitle}</div>
                <ul className="cta-stack-list">
                  {c.products.map((p) => (
                    <li key={p.t}>
                      <span className="cta-stack-dot"></span>
                      <span className="cta-stack-name">{p.t}</span>
                      <span className="cta-stack-tag mono">LIVE</span>
                    </li>
                  ))}
                </ul>
                <div className="cta-stack-foot mono">● one brain · one login · on our servers</div>
              </div>
            </Reveal>
          </div>
        </div>
      </div>

      <style>{`
        .cta { background: transparent; position: relative; overflow: hidden; }
        /* entrance: a colour circle blooms from bottom-centre, painting the bg, then content shows */
        .cta-fill {
          position: absolute; inset: 0; z-index: 0; pointer-events: none;
          background:
            radial-gradient(46% 58% at 50% 100%, rgba(43,76,99,0.16), transparent 58%),
            var(--paper-3);
          clip-path: circle(0% at 50% 100%);
          transition: clip-path 1.15s cubic-bezier(0.62, 0, 0.2, 1);
          will-change: clip-path;
        }
        .cta.entered .cta-fill { clip-path: circle(150% at 50% 100%); }
        .cta .container { position: relative; z-index: 1; opacity: 0; transform: translateY(14px); transition: opacity 0.7s ease 0.5s, transform 0.8s cubic-bezier(0.2,0.7,0.2,1) 0.5s; }
        .cta.entered .container { opacity: 1; transform: none; }
        body.no-motion .cta-fill { clip-path: none; transition: none; }
        body.no-motion .cta .container { opacity: 1; transform: none; transition: none; }
        .cta-stage { align-items: center; }
        .cta-title { font-size: clamp(40px, 5.4vw, 76px); line-height: 1.0; letter-spacing: -0.03em; margin: 20px 0 0; max-width: 16ch; text-wrap: balance; color: var(--ink); }
        .cta-title em { font-style: italic; color: var(--ink-2); }
        .cta-lede { max-width: 46ch; margin: 22px 0 0; color: var(--ink-2); font-size: 17px; line-height: 1.6; }
        .cta-actions { margin-top: 32px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
        .cta-btn { padding: 16px 26px; font-size: 15px; }
        .cta-note { display: inline-block; margin-top: 18px; font-size: 11px; color: var(--ink-3); letter-spacing: 0.06em; }

        .cta-stack { background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--r-card); padding: 26px; box-shadow: var(--sh-md); }
        .cta-stack-head { font-size: 10px; color: var(--ink-3); letter-spacing: 0.16em; text-transform: uppercase; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
        .cta-stack-list { list-style: none; padding: 0; margin: 6px 0 0; }
        .cta-stack-list li { display: flex; align-items: center; gap: 12px; padding: 13px 0; border-bottom: 1px dashed var(--line); }
        .cta-stack-list li:last-child { border-bottom: none; }
        .cta-stack-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
        .cta-stack-name { font-size: 15px; color: var(--ink); }
        .cta-stack-tag { margin-left: auto; font-size: 9px; letter-spacing: 0.12em; color: var(--accent); border: 1px solid var(--accent-line); background: var(--accent-soft); padding: 3px 9px; border-radius: 999px; }
        .cta-stack-foot { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); font-size: 10px; color: var(--accent); letter-spacing: 0.08em; }
      `}</style>
    </section>
  );
}

Object.assign(window, { Problem, Solution, Proof, CTA, ProductShot });
