/* ============================================================
   NFA · "watch a forecast run" — a self-looping hero preview of
   one forecast moving through the engine's 7 stages. Mirrors the
   production run view (market header · step rail · stage panel),
   condensed for a landing-page hero. Loops forever on a scripted
   clock; transforms + opacity only.
   ============================================================ */
const REDUCED = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

const clamp01 = (x) => Math.max(0, Math.min(1, x));
const outCubic = (t) => 1 - Math.pow(1 - clamp01(t), 3);
const inOutCubic = (t) => { t = clamp01(t); return t < .5 ? 4*t*t*t : 1 - Math.pow(-2*t+2,3)/2; };
const outBack = (t) => { t = clamp01(t); const c1 = 1.70158, c3 = c1+1; return 1 + c3*Math.pow(t-1,3) + c1*Math.pow(t-1,2); };
const rise = (p, at, span = 0.18) => {
  if (REDUCED) return { opacity: clamp01((p - at) / span) };
  const k = outCubic((p - at) / span);
  return { opacity: k, transform: `translateY(${(1 - k) * 8}px)` };
};
const fmtTime = (s) => `${Math.floor(s/60)}:${String(Math.floor(s%60)).padStart(2,'0')}`;

const STEPS = [
  { name: 'Bind market',        sub: 'Polymarket' },
  { name: 'Research market',    sub: 'corpus + adapters' },
  { name: 'Cast advocates',     sub: '2 advocates' },
  { name: 'Advocates research', sub: 'asymmetric' },
  { name: 'Debate',             sub: '3 rounds' },
  { name: 'Judge ensemble',     sub: 'K = 3' },
  { name: 'Result',             sub: 'Yes · 66%' },
];
const DUR  = [2.0, 3.4, 2.2, 2.6, 4.4, 3.8, 4.6];   /* interesting stages get more room */
const HOLD = 2.0;
const SPEED = 0.765;                                 /* 0.85 × 0.9 — 10% slower */
const STARTS = []; let acc = 0;
DUR.forEach((d) => { STARTS.push(acc); acc += d; });
const TOTAL = acc;
const CYCLE = TOTAL + HOLD;

const PipelineDemo = () => {
  const [active, setActive] = React.useState(0);
  const [prog, setProg] = React.useState(0);
  const startRef = React.useRef(0);
  const rafRef = React.useRef(0);

  React.useEffect(() => {
    startRef.current = performance.now();
    const tick = () => {
      const e = (((performance.now() - startRef.current) / 1000) * SPEED) % CYCLE;
      if (e >= TOTAL) { setActive(STEPS.length - 1); setProg(1); }
      else {
        let a = 0;
        for (let i = STEPS.length - 1; i >= 0; i--) { if (e >= STARTS[i]) { a = i; break; } }
        setActive(a); setProg(clamp01((e - STARTS[a]) / DUR[a]));
      }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, []);

  const done = active === STEPS.length - 1 && prog >= 1;
  const overall = clamp01((STARTS[active] + DUR[active] * prog) / TOTAL);
  const elapsed = fmtTime(overall * 533);                         /* maps to the real 8:53 run */
  const ent = outCubic(clamp01((prog * DUR[active]) / 0.42));      /* deterministic stage entrance */
  const entStyle = REDUCED ? { opacity: ent } : { opacity: ent, transform: `translateY(${(1 - ent) * 8}px)` };

  return (
    <div className="pl-wrap">
      {/* market header */}
      <div className="pl-market">
        <div className="pl-market-l">
          <div className="pl-eyebrow"><span className="status-dot" /> MARKET · BOUND</div>
          <div className="pl-title">
            Strait of Hormuz traffic returns to normal by July 31?
          </div>
        </div>
        <div className="pl-stats">
          <div className="pl-stat"><div className="pl-stat-k">Market</div><div className="pl-stat-v">0.435</div><div className="pl-stat-sub">$ Yes</div></div>
          <div className="pl-stat pl-stat-vol"><div className="pl-stat-k">Volume</div><div className="pl-stat-v">8.39M<small>$</small></div><div className="pl-stat-sub">Lifetime</div></div>
          <div className="pl-stat pl-stat-open"><div className="pl-stat-k">Open Int.</div><div className="pl-stat-v">771.8K<small>$</small></div><div className="pl-stat-sub">Current</div></div>
          <div className="pl-stat"><div className="pl-stat-k">Deadline</div><div className="pl-stat-v">2026-07-31</div><div className="pl-stat-sub">Polymarket</div></div>
        </div>
      </div>

      <div className="pl-body">
        {/* rail */}
        <div className="pl-rail">
          <div className="pl-rail-head"><span className="status-dot live" /> ADVOCATE DEBATE</div>
          {STEPS.map((s, i) => {
            const status = i < active ? 'done' : i === active ? 'active' : 'pending';
            const last = i === STEPS.length - 1;
            return (
              <div key={i} className="pl-step">
                <div className="pl-marker-col">
                  <span className={`pl-marker ${status}`}>
                    {status === 'done' ? <span className="pl-check">✓</span> : status === 'active' ? <span className="status-dot live" /> : ''}
                  </span>
                  {!last && <span className="pl-line"><span className="pl-line-fill" style={{ height: i < active ? '100%' : (i === active ? `${prog * 100}%` : '0%') }} /></span>}
                </div>
                <div className={`pl-step-body ${status === 'active' ? 'active' : ''}`}>
                  <div className="pl-step-name" style={{ color: status === 'pending' ? 'var(--fg-faint)' : 'var(--fg)', fontWeight: status === 'active' ? 600 : 500 }}>
                    <span className="pl-num">{i + 1}</span>{s.name}
                  </div>
                  {status !== 'pending' && s.sub && <div className="pl-step-sub"><span>{s.sub}</span></div>}
                </div>
              </div>
            );
          })}
        </div>

        {/* stage */}
        <div className="pl-stage">
          <div className="pl-crumb">
            <span className="pl-crumb-step">STEP {active + 1} · {STEPS[active].name}</span>
            <span className="pl-crumb-meta">{done ? '✓ done' : <><span className="pl-spin" /> running</>}</span>
          </div>
          <div className="pl-panel">
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', ...entStyle }}>
              <Stage active={active} p={prog} />
            </div>
            <div className="pl-foot">
              <span>ELAPSED {elapsed}</span>
              <span>RUN 315eeb2b</span>
              <span>JUDGE K=3</span>
              <span>PRICE-BLIND</span>
            </div>
          </div>
        </div>
      </div>

      <div className="pl-runbar" style={{ width: `${overall * 100}%` }} />
    </div>
  );
};

/* ---- per-stage panels ---- */
const Stage = ({ active, p }) => {
  /* 1 · BIND MARKET */
  if (active === 0) {
    const idChars = '0x7a3f91c4';
    const shown = Math.round(outCubic(p / 0.6) * idChars.length);
    return (
      <Panel label="MARKET BINDING">
        <div className="pl-kv" style={rise(p, 0.04)}><span className="pl-k">venue</span><span className="pl-v">Polymarket · binary</span></div>
        <div className="pl-kv" style={rise(p, 0.18)}><span className="pl-k">contract</span><span className="pl-v" style={{ color: 'var(--fg-dim)' }}>{idChars.slice(0, shown)}{shown < idChars.length ? '▏' : ''}</span></div>
        <div className="pl-kv" style={{ ...rise(p, 0.30), alignItems: 'flex-start' }}><span className="pl-k">resolves</span><span className="pl-v" style={{ fontSize: 11.5, color: 'var(--fg-dim)', lineHeight: 1.45 }}>YES if IMF Portwatch 7-day MA of transit calls ≥ 60 on any date by 2026-07-31</span></div>
        <div className="pl-chips">
          <Pill on={rise(p, 0.55)} style={{ flex: 1, justifyContent: 'space-between', borderColor: 'var(--accent)', color: 'var(--accent)' }}><span>YES</span><span className="pl-tag">outcome</span></Pill>
          <Pill on={rise(p, 0.70)} style={{ flex: 1, justifyContent: 'space-between', borderColor: 'rgba(232,163,92,0.4)', color: 'var(--no)' }}><span>NO</span><span className="pl-tag">outcome</span></Pill>
        </div>
      </Panel>
    );
  }

  /* 2 · RESEARCH MARKET */
  if (active === 1) {
    const bullets = [
      'U.S.-Iran MOU (June 14-15) broke the months-long stalemate; Iran issued 60-day Hormuz transit procedures.',
      'Vessel-tracking (AXS Marine) shows transits at a 2-month high · supertankers, Saudi tankers and Qatari LNG all moving.',
      '~80 uncleared mines remain; Lloyd\u2019s List / Xeneta analysts flag normalization risk before year-end.',
    ];
    const srcs = [
      'Energy secretary: oil traffic already back to normal · ABC News',
      'Hormuz transits at 2-month high, Iran issues passage instructions · Seatrade',
      'Shipping may resume only after strait cleared of mines · Jerusalem Post',
    ];
    const indexed = Math.round(outCubic(p / 0.9) * 14);
    const reads = (52 - 4 * outCubic((p - 0.5) / 0.4)).toFixed(0);
    const adapterOn = p > 0.55;
    return (
      <Panel label="MARKET RESEARCH">
        <div className="pl-note" style={{ ...rise(p, 0.02), marginBottom: 10 }}>indexing corpus · {indexed} / 14 sources</div>
        <div className="pl-bullets">
          {bullets.map((b, i) => (
            <div key={i} className="pl-bullet" style={rise(p, 0.08 + i * 0.16)}><span className="pl-dot">▪</span>{b}</div>
          ))}
        </div>
        <div className="pl-srcs">
          {srcs.map((s, i) => (
            <div key={i} className="pl-src" style={rise(p, 0.34 + i * 0.12)}><span className="pl-arr">↗</span>{s}</div>
          ))}
        </div>
        <div className="pl-adapter" style={{ ...rise(p, 0.6), borderColor: adapterOn ? 'var(--accent)' : 'var(--line)' }}>
          <span style={{ color: 'var(--fg)' }}>◇ live adapter · IMF Portwatch 7-day MA</span>
          <span style={{ color: 'var(--accent)' }}>reads {reads} calls/day</span>
        </div>
      </Panel>
    );
  }

  /* 3 · CAST ADVOCATES */
  if (active === 2) {
    const a = clamp01((p - 0.1) / 0.4), b = clamp01((p - 0.45) / 0.4);
    const row = (frac, label, desc, color, soft) => (
      <div className="pl-adv-row" style={{ borderColor: frac > 0.5 ? color : 'var(--line)', opacity: outCubic(frac), transform: REDUCED ? 'none' : `translateY(${(1 - outBack(frac)) * 6}px)` }}>
        <b>Advocate for {label}</b>
        <span className="pl-adv-desc">· strongest evidence-based case it resolves '{label}'</span>
        <span className="pl-tag" style={{ marginLeft: 'auto', color, background: soft, padding: '3px 7px', borderRadius: 5 }}>{frac < 0.999 ? <span className="pl-spin" style={{ display: 'inline-block', verticalAlign: '-2px' }} /> : `FOR ${label.toUpperCase()}`}</span>
      </div>
    );
    return (
      <Panel label="THE ADVOCATES">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {row(a, 'Yes', '', 'var(--accent)', 'var(--accent-soft)')}
          {row(b, 'No', '', 'var(--no)', 'var(--no-soft)')}
        </div>
        <div className="pl-note" style={{ ...rise(p, 0.82), marginTop: 14 }}>one advocate instantiated per outcome</div>
      </Panel>
    );
  }

  /* 4 · ADVOCATES RESEARCH */
  if (active === 3) {
    const a = outCubic(clamp01(p / 0.9)), b = outCubic(clamp01((p - 0.12) / 0.9));
    const dossier = (frac, label, exhibits, color) => (
      <div>
        <div className="pl-dossier-lab"><span style={{ color }}>{label}</span><span style={{ color: 'var(--fg-faint)' }}>{Math.round(frac * exhibits)} exhibits</span></div>
        <span className="pl-track"><span style={{ width: `${frac * 100}%`, background: color }} /></span>
      </div>
    );
    return (
      <Panel label="GATHERING EVIDENCE">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {dossier(a, 'YES dossier', 7, 'var(--accent)')}
          {dossier(b, 'NO dossier', 5, 'var(--no)')}
          <div className="pl-note" style={rise(p, 0.45)}>information asymmetry · each side digs its own evidence</div>
        </div>
      </Panel>
    );
  }

  /* 5 · DEBATE */
  if (active === 4) {
    const prob = 50 + 16 * outCubic(p);
    const div = (prob - 44).toFixed(1);
    const turns = Math.min(6, Math.floor(p * 6));
    const round = Math.min(3, Math.floor(p * 3) + 1);
    const speaker = turns % 2;
    const cross = (p * 6) % 1;
    const phases = ['OPENING', 'REBUTTAL 1', 'REBUTTAL 2'];
    const YES_CLAIMS = [['MOU + 60-day transit window', 'e3'], ['2-month transit high', 'e2'], ['threshold is single-day', 'e1']];
    const NO_CLAIMS  = [['~80 mines uncleared', 'e4'], ['7-day MA needs sustained vol', 'e5'], ['war-risk insurance gap', 'e6']];
    const yesShown = Math.ceil(turns / 2), noShown = Math.floor(turns / 2);
    return (
      <Panel label="THE FULL DEBATE">
        <div className="pl-deb-head">
          <span><span className="pl-square" />Yes</span>
          <span><b style={{ color: 'var(--accent)' }}>{prob.toFixed(1)}%</b> · market 44% · <b style={{ color: 'var(--accent)' }}>+{div} pp</b></span>
        </div>
        <div className="pl-deb-bar"><span style={{ width: `${prob}%` }} /></div>
        <div className="pl-debate-top">
          <div className={`pl-adv ${speaker === 0 ? 'live' : ''}`} style={{ borderColor: speaker === 0 ? 'var(--accent)' : 'var(--line)', boxShadow: speaker === 0 ? '0 0 0 3px var(--accent-soft)' : 'none' }}>YES</div>
          <div className="pl-gap"><span className="pl-pulse" style={{ left: `${(speaker === 0 ? cross : 1 - cross) * 100}%`, background: speaker === 0 ? 'var(--accent)' : 'var(--no)' }} /></div>
          <div className={`pl-adv ${speaker === 1 ? 'live' : ''}`} style={{ borderColor: speaker === 1 ? 'rgba(232,163,92,0.55)' : 'var(--line)', boxShadow: speaker === 1 ? '0 0 0 3px var(--no-soft)' : 'none' }}>NO</div>
        </div>
        <div className="pl-claims">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
            {YES_CLAIMS.slice(0, yesShown).map((c, i) => <div key={i} className="pl-claim"><span className="pl-tick" style={{ background: 'var(--accent)' }} />{c[0]}<span className="pl-cite">[{c[1]}]</span></div>)}
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
            {NO_CLAIMS.slice(0, noShown).map((c, i) => <div key={i} className="pl-claim"><span className="pl-tick" style={{ background: 'var(--no)' }} />{c[0]}<span className="pl-cite">[{c[1]}]</span></div>)}
          </div>
        </div>
        <div className="pl-phase">{phases[round - 1]} · round {String(round).padStart(2, '0')}/03 · <b>defense</b> / <i>offense</i> grounded in evidence</div>
      </Panel>
    );
  }

  /* 6 · JUDGE ENSEMBLE */
  if (active === 5) {
    const target = 66, seeds = [58, 71, 63];
    const settle = inOutCubic(clamp01((p - 0.1) / 0.7));
    const wobble = (1 - settle) * (REDUCED ? 0 : 1);
    const vals = seeds.map((s, i) => (s + (target - s) * settle) + wobble * Math.sin(p * 14 + i * 2.1) * 7);
    const converged = settle > 0.92;
    return (
      <Panel label="JUDGE'S DELIBERATION">
        <div className="pl-note" style={{ ...rise(p, 0.02), marginBottom: 13, lineHeight: 1.5, color: 'var(--fg-dim)', textTransform: 'none', letterSpacing: 0 }}>
          impartial judge · never sees the market price · sampled K=3 for self-consistency
        </div>
        <div className="pl-samples">
          <div className="pl-consensus" style={{ left: `calc(22px + 10px + (100% - 32px) * ${target / 100})`, opacity: converged ? 0.7 : 0 }} />
          {vals.map((v, i) => {
            const w = clamp01(v / 100) * 100;
            return (
              <div key={i} className="pl-sample">
                <span className="pl-sample-lab">s{i + 1}</span>
                <span className="pl-sample-track"><span className="pl-sample-fill" style={{ width: `${w}%` }} /><span className="pl-sample-knob" style={{ left: `${w}%` }} /></span>
              </div>
            );
          })}
        </div>
        <div className="pl-note" style={{ textAlign: 'center', marginTop: 14, color: converged ? 'var(--accent)' : 'var(--fg-faint)', transition: 'color .4s' }}>
          {converged ? 'self-consistency · converged → 66%' : 'sampling the judge K = 3 …'}
        </div>
      </Panel>
    );
  }

  /* 7 · RESULT */
  const reveal = outCubic(clamp01(p / 0.5));
  const yes = Math.round(66 * reveal), no = Math.round(34 * reveal);
  const markerOn = clamp01((p - 0.45) / 0.2);
  const tableOn = clamp01((p - 0.4) / 0.4);
  return (
    <Panel label="JUDGEMENT · RULING · 2 OUTCOMES">
      <div className="pl-res-top">
        <div className="pl-res-col"><div className="pl-stat-k" style={{ color: 'var(--accent)' }}>YES</div><div className="pl-big">{yes}<small>%</small></div></div>
        <div className="pl-res-col"><div className="pl-stat-k">MARKET</div><div className="pl-mkt">44%</div></div>
        <div style={{ marginLeft: 'auto', textAlign: 'right' }}><div className="pl-stat-k">MOST LIKELY</div><div className="pl-mkt" style={{ color: 'var(--accent)', fontSize: 14, marginTop: 6 }}>YES</div></div>
      </div>
      <div className="pl-stack">
        <span className="pl-stack-yes" style={{ width: `${66 * reveal}%` }} />
        <span className="pl-stack-no" style={{ width: `${34 * reveal}%` }} />
        <span className="pl-stack-mkt" style={{ left: '44%', opacity: markerOn }} />
      </div>
      <div className="pl-rtable" style={{ opacity: tableOn }}>
        <div className="pl-rrow head"><span>outcome</span><span style={{ textAlign: 'right' }}>NFA</span><span style={{ textAlign: 'right' }}>MARKET</span><span style={{ textAlign: 'right' }}>DIV.</span></div>
        <div className="pl-rrow"><span className="r-name"><span className="pl-square" style={{ margin: 0, background: 'var(--accent)' }} />Yes</span><span className="r-num">66%</span><span className="r-mkt">44%</span><span className="r-div" style={{ color: 'var(--accent)' }}>+22pp</span></div>
        <div className="pl-rrow"><span className="r-name"><span className="pl-square" style={{ margin: 0, background: 'var(--no)' }} />No</span><span className="r-num">34%</span><span className="r-mkt">56%</span><span className="r-div" style={{ color: '#e06666' }}>-22pp</span></div>
      </div>
      <div className="pl-prog" style={rise(p, 0.6)}>market <b>44%</b> → corpus-only <b>70%</b> → after debate <b className="a">66%</b> · the gap is the trade</div>
    </Panel>
  );
};

const Panel = ({ label, children }) => (
  <>
    <div className="pl-panel-head"><span className="status-dot live" />{label}</div>
    <div className="pl-panel-body">{children}</div>
  </>
);
const Pill = ({ children, on, style }) => <div className="pl-pill" style={{ ...on, ...style }}>{children}</div>;

window.PipelineDemo = PipelineDemo;
  