/* AutoSimHero.jsx - auto-looping simulation hero (NOT scroll-tied)
   ============================================================
   The hero plays through 3 stages on its own ~24s loop:
     1. Build the audience  (0–8s)
     2. Watch them decide   (8–16s)
     3. Talk to any of them (16–24s)
   Page scrolls normally; hero occupies one viewport.
   ============================================================ */

const useLoopClock = (durationS = 24) => {
  const [t, setT] = React.useState(0);
  const startRef = React.useRef(null);
  React.useEffect(() => {
    let raf = 0;
    const tick = (now) => {
      if (startRef.current == null) startRef.current = now;
      const elapsed = ((now - startRef.current) / 1000) % durationS;
      setT(elapsed);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [durationS]);
  return { t, p: t / durationS };
};

/* ============================================================
   STAGE 1 - Build the audience
   Sub-phases:
     A. 0.00–0.35  Params fill in (age, income, height, skincare, brands…)
     B. 0.35–0.70  Agents generate (dots fly into a cloud)
     C. 0.70–1.00  Archetypes emerge (dots cluster into 5 colored groups)
   ============================================================ */

// Five archetype definitions - colors come from peacock + orange + neutrals
const ARCHETYPES = [
  { id: 'eco',     label: 'Eco Minimalist',   color: '#0F7A87', share: 0.22, cx: 0.22, cy: 0.40 },
  { id: 'value',   label: 'Value Hunter',     color: '#F26B2C', share: 0.28, cx: 0.50, cy: 0.30 },
  { id: 'social',  label: 'Social Maven',     color: '#7BC4CC', share: 0.18, cx: 0.78, cy: 0.42 },
  { id: 'loyal',   label: 'Brand Loyalist',   color: '#C24F18', share: 0.16, cx: 0.30, cy: 0.74 },
  { id: 'curious', label: 'Curious Sampler',  color: '#095964', share: 0.16, cx: 0.70, cy: 0.74 },
];

// Params shown filling in. Each has its own reveal timing inside phase A.
const PARAMS = [
  { key: 'Age',                value: '28 – 42',                     kind: 'range',  start: 0.02 },
  { key: 'Household income',   value: '$60k – $180k',                kind: 'range',  start: 0.06 },
  { key: 'Geography',          value: 'NYC · LA · Austin',           kind: 'tags',   start: 0.10 },
  { key: 'Height (avg)',       value: '5\u20194\u201d – 6\u20191\u201d',  kind: 'range', start: 0.13 },
  { key: 'Has skincare routine', value: '64% yes',                   kind: 'pct',    start: 0.16 },
  { key: 'Owns running shoes', value: '71% yes',                     kind: 'pct',    start: 0.19 },
  { key: 'Favorite brands',    value: 'Patagonia · On · Aesop · Trader Joe\u2019s', kind: 'tags', start: 0.22 },
  { key: 'Cooks at home',      value: '4–6× / week',                 kind: 'range',  start: 0.25 },
  { key: 'Eco concern',        value: 'High (μ 0.74)',               kind: 'tag',    start: 0.28 },
  { key: 'Posts on social',    value: 'Daily on IG · weekly on X',   kind: 'tags',   start: 0.30 },
];

const PopulationStage = ({ progress, fade }) => {
  // sub-phase progress
  const pA = clamp(invLerp(progress, 0.00, 0.35));
  const pB = clamp(invLerp(progress, 0.35, 0.70));
  const pC = clamp(invLerp(progress, 0.70, 1.00));

  // Phase headline morphs
  const phaseLabel = pC > 0.05 ? 'Archetypes emerging' : pB > 0.05 ? 'Generating agents' : 'Defining the audience';

  // Total agents & visible count by phase
  const TOTAL_AGENTS = 512;
  const generated = Math.floor(pB * TOTAL_AGENTS);
  const archetypesFound = Math.min(5, Math.floor(pC * 5.4));

  // Build a deterministic agent set ONCE: each gets an archetype + a random pos in cloud and a target pos in its cluster
  const agents = React.useMemo(() => {
    const arr = [];
    const cum = [];
    let s = 0;
    ARCHETYPES.forEach(a => { s += a.share; cum.push(s); });
    // simple LCG for determinism
    let seed = 1234567;
    const rand = () => {
      seed = (seed * 1664525 + 1013904223) % 4294967296;
      return seed / 4294967296;
    };
    for (let i = 0; i < TOTAL_AGENTS; i++) {
      const u = rand();
      let aIdx = 0;
      for (let k = 0; k < cum.length; k++) { if (u < cum[k]) { aIdx = k; break; } }
      const arch = ARCHETYPES[aIdx];
      // cloud position: gaussian-ish around center
      const cloudX = 0.5 + (rand() - 0.5) * 0.7;
      const cloudY = 0.5 + (rand() - 0.5) * 0.7;
      // cluster offset: small radius around archetype center
      const ang = rand() * Math.PI * 2;
      const rad = 0.04 + Math.sqrt(rand()) * 0.10;
      const clusterX = arch.cx + Math.cos(ang) * rad;
      const clusterY = arch.cy + Math.sin(ang) * rad * 0.85;
      arr.push({ archIdx: aIdx, cloudX, cloudY, clusterX, clusterY, birthOrder: i / TOTAL_AGENTS });
    }
    return arr;
  }, []);

  return (
    <div style={{
      position: 'absolute', inset: 0, padding: '28px 36px 48px',
      display: 'flex', flexDirection: 'column',
      opacity: fade, transition: 'opacity 280ms ease-out',
      pointerEvents: fade > 0.5 ? 'auto' : 'none',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 24, marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 700, color: 'var(--accent)', marginBottom: 6 }}>01 · Build the audience</div>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 24, lineHeight: 1.05, letterSpacing: '-0.02em', color: 'var(--fg-1)' }}>
            {phaseLabel}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 16, alignItems: 'flex-end', whiteSpace: 'nowrap' }}>
          <Stat label="Generated" value={generated.toLocaleString()} />
          <Stat label="Archetypes" value={archetypesFound} accent />
          <Stat label="Coverage" value={Math.round(pB * 96 + pC * 4) + '%'} mono />
        </div>
      </div>

      <div style={{
        flex: 1, position: 'relative',
        background: 'var(--bg-sunken)', border: '1px solid var(--border-1)',
        borderRadius: 12, overflow: 'hidden',
        display: 'grid', gridTemplateColumns: '230px 1fr', gap: 0,
      }}>
        {/* LEFT - params panel */}
        <div style={{
          borderRight: '1px solid var(--border-1)',
          background: 'var(--bg-elevated)',
          padding: '14px 14px 12px',
          display: 'flex', flexDirection: 'column', gap: 8,
          overflow: 'hidden',
        }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 2 }}>
            Audience parameters
          </div>
          {PARAMS.map((p, i) => {
            // each param fades in over a 0.05 window starting at p.start (phase-A scaled)
            const local = clamp((pA - p.start / 0.35) / (0.05 / 0.35));
            const filled = pA >= (p.start + 0.04) / 0.35 ? 1 : 0;
            return (
              <div key={i} style={{
                opacity: 0.2 + local * 0.8,
                transform: `translateY(${(1 - local) * 4}px)`,
                transition: 'opacity 200ms, transform 200ms',
              }}>
                <div style={{ fontSize: 10, color: 'var(--fg-3)', marginBottom: 2, letterSpacing: '0.02em' }}>{p.key}</div>
                <div style={{
                  fontFamily: p.kind === 'range' || p.kind === 'pct' ? 'var(--font-mono)' : 'inherit',
                  fontSize: 11, fontWeight: 600, color: 'var(--fg-1)',
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>
                  {filled ? p.value : (
                    <span style={{ display: 'inline-block', width: 70, height: 8, background: 'var(--border-1)', borderRadius: 2, animation: 'paramShimmer 1.2s ease-in-out infinite' }}></span>
                  )}
                </div>
              </div>
            );
          })}
          <div style={{ flex: 1 }}></div>
          <div style={{
            fontFamily: 'var(--font-mono)', fontSize: 9, color: 'var(--fg-3)',
            paddingTop: 8, borderTop: '1px dashed var(--border-1)',
          }}>
            + 23 more dimensions
          </div>
        </div>

        {/* RIGHT - agents canvas */}
        <div style={{ position: 'relative', overflow: 'hidden' }}>
          {/* prompt floater */}
          <div style={{
            position: 'absolute', top: 14, left: 14, right: 14,
            padding: '6px 10px', borderRadius: 8,
            background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
            boxShadow: 'var(--shadow-xs)',
            fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-2)',
            zIndex: 5,
          }}>
            <span style={{ color: 'var(--fg-3)' }}>prompt ·</span>{' '}
            <span style={{ color: 'var(--fg-1)' }}>“urban runners, 28–42, eco-aware, $80k+, NYC + LA”</span>
          </div>

          {/* agents - absolute positioned dots, animate from cloud → cluster */}
          <div style={{ position: 'absolute', inset: 48, top: 56 }}>
            {agents.map((a, i) => {
              const arch = ARCHETYPES[a.archIdx];
              // Visible only after birth in phase B
              const born = pB >= a.birthOrder * 0.92;
              if (!born && pC < 0.02) return null;

              // Position: lerp from cloud → cluster across phase C
              const x = lerp(a.cloudX, a.clusterX, pC);
              const y = lerp(a.cloudY, a.clusterY, pC);

              // Color: starts neutral, gains archetype color in phase C
              const colorMix = pC;
              const baseColor = '#7BC4CC';

              const size = 5 + pC * 1.5;
              return (
                <div key={i} style={{
                  position: 'absolute',
                  left: `${x * 100}%`,
                  top: `${y * 100}%`,
                  width: size, height: size, borderRadius: '50%',
                  background: colorMix > 0.4 ? arch.color : baseColor,
                  transform: `translate(-50%, -50%) scale(${born ? 1 : 0.2})`,
                  opacity: born ? (0.55 + pC * 0.4) : 0,
                  transition: 'background-color 600ms, transform 280ms ease-out, opacity 280ms',
                  boxShadow: pC > 0.6 ? `0 0 0 1px ${arch.color}33` : 'none',
                }} />
              );
            })}
          </div>

          {/* archetype labels - fade in during phase C, positioned at cluster centers */}
          {ARCHETYPES.map((a, i) => {
            const visible = pC > (i * 0.08);
            const local = clamp((pC - i * 0.08) / 0.12);
            // count of agents in this archetype
            const count = Math.round(TOTAL_AGENTS * a.share);
            return (
              <div key={a.id} style={{
                position: 'absolute',
                // place over the cluster, but inside the inset region
                left: `calc(${a.cx * 100}% - 0px)`,
                top: `calc(56px + ${a.cy} * (100% - 56px - 48px) + 56px)`,
                transform: 'translate(-50%, -50%)',
                opacity: visible ? local : 0,
                transition: 'opacity 320ms',
                pointerEvents: 'none',
              }}>
                <div style={{
                  padding: '4px 9px', borderRadius: 999,
                  background: 'var(--bg-elevated)',
                  border: `1px solid ${a.color}`,
                  fontSize: 10, fontWeight: 700, color: a.color,
                  whiteSpace: 'nowrap', boxShadow: 'var(--shadow-sm)',
                  display: 'inline-flex', alignItems: 'center', gap: 6,
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: '50%', background: a.color }}></span>
                  {a.label}
                  <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 600, color: 'var(--fg-3)', marginLeft: 2 }}>· {count}</span>
                </div>
              </div>
            );
          })}

          {/* generation counter ticker (visible in phase B) */}
          {pB > 0.02 && pC < 0.4 && (
            <div style={{
              position: 'absolute', bottom: 14, left: 14,
              padding: '5px 10px', borderRadius: 6,
              background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
              fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-2)',
              opacity: clamp(invLerp(pB, 0, 0.1)) * (1 - clamp(invLerp(pC, 0.2, 0.4))),
              transition: 'opacity 200ms',
            }}>
              <span style={{ color: 'var(--accent-2)', fontWeight: 700 }}>+{generated}</span>
              <span style={{ color: 'var(--fg-3)' }}> agents · </span>
              <span style={{ color: 'var(--fg-1)' }}>{Math.round(pB * 312)} ms / agent</span>
            </div>
          )}

          {/* archetype legend (phase C) */}
          {pC > 0.5 && (
            <div style={{
              position: 'absolute', bottom: 14, right: 14,
              padding: '6px 10px', borderRadius: 999,
              background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
              fontSize: 10, color: 'var(--fg-2)',
              display: 'flex', gap: 10,
              opacity: clamp(invLerp(pC, 0.5, 0.65)),
              transition: 'opacity 200ms',
            }}>
              <span style={{ color: 'var(--fg-3)', fontFamily: 'var(--font-mono)', letterSpacing: '0.06em' }}>5 archetypes</span>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

const lerp = (a, b, t) => a + (b - a) * t;

const LegendDot = ({ color, stroke, label }) => (
  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
    <span style={{
      width: 8, height: 8, borderRadius: '50%',
      background: color, border: stroke ? `1px solid ${stroke}` : 'none',
    }}></span>
    {label}
  </span>
);

/* STAGE 2 - Branching */
const BranchingStage = ({ progress, fade }) => {
  const STEPS = 8, COL_W = 92, X0 = 36;
  const VB_W = STEPS * COL_W, VB_H = 320;
  const LEVELS = [
    [{ p: -1, h: 0.5, kind: 'root' }],
    [{ p: 0, h: 0.32, kind: 'consider' }, { p: 0, h: 0.68, kind: 'consider' }],
    [{ p: 0, h: 0.18, kind: 'post' }, { p: 0, h: 0.42, kind: 'reject' }, { p: 1, h: 0.78, kind: 'post' }],
    [{ p: 0, h: 0.10, kind: 'buy' }, { p: 0, h: 0.26, kind: 'consider' }, { p: 1, h: 0.50, kind: 'post' }, { p: 2, h: 0.70, kind: 'buy' }, { p: 2, h: 0.88, kind: 'consider' }],
    [{ p: 0, h: 0.06, kind: 'buy' }, { p: 1, h: 0.20, kind: 'consider' }, { p: 1, h: 0.32, kind: 'reject' }, { p: 2, h: 0.46, kind: 'post' }, { p: 2, h: 0.58, kind: 'buy' }, { p: 3, h: 0.72, kind: 'buy' }, { p: 4, h: 0.92, kind: 'post' }],
    [{ p: 0, h: 0.04, kind: 'buy' }, { p: 1, h: 0.16, kind: 'reject' }, { p: 2, h: 0.28, kind: 'consider' }, { p: 3, h: 0.40, kind: 'post' }, { p: 3, h: 0.50, kind: 'buy' }, { p: 4, h: 0.60, kind: 'buy' }, { p: 5, h: 0.74, kind: 'post' }, { p: 5, h: 0.84, kind: 'buy' }, { p: 6, h: 0.94, kind: 'consider' }],
    [{ p: 0, h: 0.03, kind: 'buy' }, { p: 1, h: 0.12, kind: 'reject' }, { p: 2, h: 0.22, kind: 'buy' }, { p: 3, h: 0.32, kind: 'post' }, { p: 3, h: 0.42, kind: 'buy' }, { p: 4, h: 0.50, kind: 'buy' }, { p: 5, h: 0.60, kind: 'consider' }, { p: 6, h: 0.70, kind: 'buy' }, { p: 7, h: 0.82, kind: 'post' }, { p: 8, h: 0.92, kind: 'buy' }],
    [{ p: 0, h: 0.02, kind: 'buy' }, { p: 1, h: 0.10, kind: 'reject' }, { p: 2, h: 0.18, kind: 'buy' }, { p: 3, h: 0.28, kind: 'buy' }, { p: 4, h: 0.38, kind: 'buy' }, { p: 4, h: 0.46, kind: 'buy' }, { p: 5, h: 0.54, kind: 'buy' }, { p: 6, h: 0.62, kind: 'consider' }, { p: 7, h: 0.72, kind: 'buy' }, { p: 8, h: 0.82, kind: 'post' }, { p: 9, h: 0.92, kind: 'buy' }],
  ];
  const KIND_FILL = { root: 'var(--accent)', consider: 'var(--accent-soft)', post: 'var(--accent)', buy: 'var(--accent-2)', reject: 'var(--bg-elevated)' };
  const KIND_STROKE = { root: 'var(--accent)', consider: 'var(--accent)', post: 'var(--accent-deep)', buy: 'var(--accent-2)', reject: 'var(--border-2)' };

  const reveal = progress * STEPS;
  const totalNodes = LEVELS.reduce((acc, lvl, li) => acc + (li <= reveal ? lvl.length : 0), 0);
  const buyNodes = LEVELS.reduce((acc, lvl, li) => acc + (li <= reveal ? lvl.filter(n => n.kind === 'buy').length : 0), 0);
  const finalIntent = (28 + Math.min(1, progress) * 19.2).toFixed(1);

  return (
    <div style={{
      position: 'absolute', inset: 0, padding: '32px 40px 56px',
      display: 'flex', flexDirection: 'column',
      opacity: fade, transition: 'opacity 280ms ease-out',
      pointerEvents: fade > 0.5 ? 'auto' : 'none',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 24, marginBottom: 18 }}>
        <div>
          <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 700, color: 'var(--accent)', marginBottom: 6 }}>02 · Decide</div>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 26, lineHeight: 1.05, letterSpacing: '-0.02em', color: 'var(--fg-1)' }}>
            Watch them think it through, branch by branch
          </div>
        </div>
        <div style={{ display: 'flex', gap: 18, alignItems: 'flex-end' }}>
          <Stat label="Decisions" value={totalNodes.toLocaleString()} />
          <Stat label="Buy paths" value={buyNodes} accent />
          <Stat label="Final intent" value={finalIntent + '%'} mono />
        </div>
      </div>
      <div style={{
        flex: 1, position: 'relative', background: 'var(--bg-sunken)',
        border: '1px solid var(--border-1)', borderRadius: 12,
        padding: '18px 12px 14px', overflow: 'hidden',
      }}>
        <svg viewBox={`0 0 ${VB_W} ${VB_H}`} preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block' }}>
          {LEVELS.map((_, li) => (
            <line key={'g' + li} x1={X0 + li * COL_W} y1={20} x2={X0 + li * COL_W} y2={VB_H - 20}
              stroke="var(--border-1)" strokeWidth="1" strokeDasharray="2 4" opacity="0.7" />
          ))}
          {LEVELS.map((_, li) => (
            <text key={'t' + li} x={X0 + li * COL_W} y={12} textAnchor="middle"
              fill="var(--fg-3)" fontSize="9" fontFamily="var(--font-mono)" letterSpacing="0.08em">t{li}</text>
          ))}
          {LEVELS.map((level, li) => li === 0 ? null : level.map((node, ni) => {
            const parent = LEVELS[li - 1][node.p];
            const x1 = X0 + (li - 1) * COL_W, y1 = 20 + parent.h * (VB_H - 40);
            const x2 = X0 + li * COL_W, y2 = 20 + node.h * (VB_H - 40);
            const r = Math.max(0, Math.min(1, reveal - li + 0.5));
            const stroke = node.kind === 'reject' ? 'var(--border-2)' :
                           node.kind === 'buy' ? 'var(--accent-2)' :
                           node.kind === 'post' ? 'var(--accent-deep)' : 'var(--accent)';
            return (
              <path key={`e${li}-${ni}`}
                d={`M${x1} ${y1} C ${x1 + COL_W * 0.5} ${y1}, ${x2 - COL_W * 0.5} ${y2}, ${x2} ${y2}`}
                fill="none" stroke={stroke}
                strokeWidth={node.kind === 'buy' ? 1.6 : 1}
                strokeOpacity={node.kind === 'reject' ? 0.45 : 0.85}
                strokeDasharray="200" strokeDashoffset={200 * (1 - r)} />
            );
          }))}
          {LEVELS.map((level, li) => level.map((node, ni) => {
            const x = X0 + li * COL_W, y = 20 + node.h * (VB_H - 40);
            const r = Math.max(0, Math.min(1, reveal - li));
            if (r <= 0) return null;
            const radius = node.kind === 'root' ? 8 : node.kind === 'buy' ? 5 : 4;
            return (
              <g key={`n${li}-${ni}`} style={{ opacity: r }}>
                <circle cx={x} cy={y} r={radius}
                  fill={KIND_FILL[node.kind]}
                  stroke={node.kind === 'reject' ? KIND_STROKE.reject : 'none'}
                  strokeWidth="1" />
              </g>
            );
          }))}
          <text x={X0} y={VB_H - 4} textAnchor="middle" fill="var(--fg-2)" fontSize="9" fontFamily="var(--font-mono)" fontWeight="600">SEED</text>
        </svg>
        <div style={{
          position: 'absolute', bottom: 14, right: 16,
          display: 'flex', gap: 14, padding: '6px 12px', borderRadius: 999,
          background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
          fontSize: 11, color: 'var(--fg-2)',
        }}>
          <LegendDot color="var(--accent-2)" label="buy" />
          <LegendDot color="var(--accent)" label="post" />
          <LegendDot color="var(--accent-soft)" label="consider" />
          <LegendDot color="var(--bg-elevated)" stroke="var(--border-2)" label="reject" />
        </div>
        <div style={{
          position: 'absolute', top: 16, left: 16,
          padding: '6px 10px', borderRadius: 6,
          background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
          fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-3)', letterSpacing: '0.04em',
        }}>sim_8f3a · refillable shampoo · $24 · what-if branching</div>
      </div>
    </div>
  );
};

/* STAGE 3 - Chat */
const ChatStage = ({ progress, fade }) => {
  const SCRIPT = [
    { who: 'you',     text: "Why didn't you buy it?" },
    { who: 'persona', text: "$24 felt steep without trying it. I'd want to smell it first or hear from someone whose hair is like mine." },
    { who: 'you',     text: "What would change your mind?" },
    { who: 'persona', text: "A 2-pack starter at $18, or a friend posting before/after. Reviews from strangers don't move me anymore." },
    { who: 'you',     text: "And if a friend posted about it?" },
    { who: 'persona', text: "Then I'd buy without thinking. That's how I tried the last three things in my bathroom, honestly." },
  ];
  const N = SCRIPT.length;
  const slot = 1 / (N + 0.5);
  const visibleCount = Math.min(N, Math.floor(progress / slot));
  const inSlot = (progress / slot) - visibleCount;
  const typing = visibleCount < N && inSlot > 0.15 && inSlot < 0.95;
  const visible = SCRIPT.slice(0, visibleCount);
  const nextSpeaker = visibleCount < N ? SCRIPT[visibleCount].who : null;

  return (
    <div style={{
      position: 'absolute', inset: 0, padding: '32px 40px 56px',
      display: 'flex', flexDirection: 'column',
      opacity: fade, transition: 'opacity 280ms ease-out',
      pointerEvents: fade > 0.5 ? 'auto' : 'none',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 24, marginBottom: 18 }}>
        <div>
          <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 700, color: 'var(--accent)', marginBottom: 6 }}>03 · Talk</div>
          <div style={{ fontFamily: 'var(--font-display)', fontSize: 26, lineHeight: 1.05, letterSpacing: '-0.02em', color: 'var(--fg-1)' }}>
            Pull any one aside and ask them why
          </div>
        </div>
        <div style={{ display: 'flex', gap: 18, alignItems: 'flex-end' }}>
          <Stat label="Persona" value="Maya R." />
          <Stat label="Match" value="87%" accent />
          <Stat label="Branch" value="t=4 · reject" mono />
        </div>
      </div>
      <div style={{
        flex: 1, position: 'relative', background: 'var(--bg-sunken)',
        border: '1px solid var(--border-1)', borderRadius: 12,
        display: 'grid', gridTemplateColumns: '1fr 260px', overflow: 'hidden',
      }}>
        <div style={{ padding: '18px 22px', overflow: 'hidden', display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, paddingBottom: 12, borderBottom: '1px solid var(--border-1)', flexShrink: 0 }}>
            <div style={{
              width: 36, height: 36, borderRadius: 10,
              background: 'var(--accent-soft-bg)', color: 'var(--accent-soft-fg)',
              display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 13,
            }}>MR</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-1)' }}>Maya R., 34 · Brooklyn</div>
              <div style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'var(--font-mono)' }}>Rejected at t=4 · eco_concern 84 · brand_loyalty 62</div>
            </div>
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '3px 9px', borderRadius: 999,
              background: 'var(--accent-2-soft-bg)', color: 'var(--accent-2-soft-fg)',
              fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
            }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: 'var(--accent-2)' }}></span>LIVE
            </span>
          </div>
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 10, overflow: 'hidden' }}>
            {visible.map((m, i) => <ChatBubble2 key={i} {...m} fresh={i === visible.length - 1} />)}
            {typing && nextSpeaker === 'persona' && <TypingDots />}
          </div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            background: 'var(--bg-elevated)', border: '1px solid var(--border-2)',
            borderRadius: 10, padding: '8px 10px', flexShrink: 0,
          }}>
            <span style={{ flex: 1, fontSize: 13, color: 'var(--fg-3)' }}>Ask Maya something…</span>
            <button style={{
              padding: '6px 14px', borderRadius: 6, border: 'none',
              background: 'var(--accent)', color: '#fff',
              fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
            }}>Send</button>
          </div>
        </div>
        <div style={{
          borderLeft: '1px solid var(--border-1)', background: 'var(--bg-elevated)',
          padding: '18px 16px', display: 'flex', flexDirection: 'column', gap: 14,
        }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 700, marginBottom: 8 }}>Beliefs</div>
            <BarRow2 label="Eco concern" value={84} color="var(--accent)" />
            <BarRow2 label="Brand loyalty" value={62} color="var(--accent)" />
            <BarRow2 label="Price sensitivity" value={73} color="var(--accent-2)" />
            <BarRow2 label="Social proof" value={71} color="var(--accent-2)" />
          </div>
          <div>
            <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 700, marginBottom: 8 }}>Recent context</div>
            <div style={{ fontSize: 12, color: 'var(--fg-2)', lineHeight: 1.5 }}>
              New apartment lease last month. Started training for a half-marathon. Switched grocery brand after a packaging change.
            </div>
          </div>
          <div style={{
            marginTop: 'auto', padding: 10, borderRadius: 8,
            background: 'var(--accent-wash)', border: '1px solid var(--accent-soft)',
            fontSize: 11, color: 'var(--accent-deep)', lineHeight: 1.4,
          }}>
            <strong>Why she rejected:</strong> price-anchor on drugstore baseline, no in-network social proof yet.
          </div>
        </div>
      </div>
    </div>
  );
};

const ChatBubble2 = ({ who, text, fresh }) => {
  const isPersona = who === 'persona';
  return (
    <div style={{
      display: 'flex', justifyContent: isPersona ? 'flex-start' : 'flex-end',
      animation: fresh ? 'fadeInUp 0.32s ease-out' : 'none',
    }}>
      <div style={{
        maxWidth: '84%', padding: '8px 12px',
        borderRadius: isPersona ? '12px 12px 12px 3px' : '12px 12px 3px 12px',
        background: isPersona ? 'var(--bg-elevated)' : 'var(--accent)',
        color: isPersona ? 'var(--fg-1)' : '#fff',
        border: isPersona ? '1px solid var(--border-1)' : 'none',
        fontSize: 13, lineHeight: 1.45,
        boxShadow: isPersona ? 'var(--shadow-xs)' : 'none',
      }}>{text}</div>
    </div>
  );
};

const TypingDots = () => (
  <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
    <div style={{
      padding: '10px 14px', borderRadius: '12px 12px 12px 3px',
      background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
      display: 'inline-flex', gap: 4,
    }}>
      {[0, 1, 2].map(i => (
        <span key={i} style={{
          width: 6, height: 6, borderRadius: '50%', background: 'var(--fg-3)',
          animation: `typingPulse 1.2s ease-in-out ${i * 0.16}s infinite`,
        }} />
      ))}
    </div>
  </div>
);

const BarRow2 = ({ label, value, color }) => (
  <div style={{ marginBottom: 8 }}>
    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 3 }}>
      <span style={{ color: 'var(--fg-2)' }}>{label}</span>
      <span style={{ fontFamily: 'var(--font-mono)', color: 'var(--fg-3)' }}>{value}</span>
    </div>
    <div style={{ height: 4, background: 'var(--bg-sunken)', borderRadius: 2 }}>
      <div style={{ width: `${value}%`, height: '100%', background: color, borderRadius: 2 }}></div>
    </div>
  </div>
);

const Stat = ({ label, value, accent, mono }) => (
  <div style={{ textAlign: 'right' }}>
    <div style={{ fontSize: 9, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 700, marginBottom: 2 }}>{label}</div>
    <div style={{
      fontFamily: mono ? 'var(--font-mono)' : 'var(--font-display)',
      fontSize: mono ? 16 : 24, lineHeight: 1,
      letterSpacing: mono ? 0 : '-0.02em',
      color: accent ? 'var(--accent-2)' : 'var(--fg-1)',
      fontVariantNumeric: 'tabular-nums', fontWeight: mono ? 600 : 400,
    }}>{value}</div>
  </div>
);

/* ============================================================
   The hero - auto-loop, single viewport, NOT scroll-tied
   ============================================================ */
const ScrollSimHero = () => {
  const { p } = useLoopClock(24);
  const liveSims = (typeof window !== 'undefined' && window.useLiveSims)
    ? window.useLiveSims()
    : 423;

  // Stage windows
  const s1 = clamp(invLerp(p, 0.00, 0.30));
  const s2 = clamp(invLerp(p, 0.33, 0.62));
  const s3 = clamp(invLerp(p, 0.66, 0.98));

  const fade1 = smoothstep(p, 0.02, 0.06) * (1 - smoothstep(p, 0.30, 0.34));
  const fade2 = smoothstep(p, 0.30, 0.34) * (1 - smoothstep(p, 0.62, 0.66));
  const fade3 = smoothstep(p, 0.62, 0.66);

  const activeStage = p < 0.33 ? 0 : p < 0.66 ? 1 : 2;
  const STAGES = [
    { num: '01', label: 'Build the audience' },
    { num: '02', label: 'Watch them decide' },
    { num: '03', label: 'Talk to any of them' },
  ];

  return (
    <section style={{
      position: 'relative', background: 'var(--bg)',
      padding: '48px 32px 80px',
    }}>
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'minmax(0, 1.05fr) minmax(0, 1.55fr)',
        alignItems: 'center', gap: 56,
        maxWidth: 1360, margin: '0 auto',
      }}>
        {/* LEFT - copy */}
        <div style={{ maxWidth: 520 }}>
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 8,
            padding: '5px 12px 5px 8px', borderRadius: 999,
            background: 'var(--bg-elevated)', border: '1px solid var(--border-1)',
            fontSize: 11, fontWeight: 600, color: 'var(--fg-2)', marginBottom: 24,
            boxShadow: 'var(--shadow-xs)',
          }}>
            <span style={{
              width: 6, height: 6, borderRadius: '50%',
              background: 'var(--accent-2)', boxShadow: '0 0 0 4px rgba(242,107,44,0.18)',
            }}></span>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.08em' }}>LIVE · {liveSims.toLocaleString()} SIMULATIONS RUNNING</span>
          </div>

          <h1 style={{
            fontFamily: 'var(--font-display)', fontWeight: 400,
            fontSize: 'clamp(46px, 5.4vw, 76px)',
            lineHeight: 0.98, letterSpacing: '-0.025em',
            color: 'var(--fg-1)', margin: '0 0 20px',
          }}>
            Focus groups take weeks.<br/>
            <em style={{ color: 'var(--accent)', fontStyle: 'italic' }}>Lokara</em> takes minutes.
          </h1>

          <p style={{
            fontSize: 17, lineHeight: 1.55, color: 'var(--fg-2)',
            margin: '0 0 28px', maxWidth: 460,
          }}>
            Build a thousand simulated customers. Watch them decide. Then talk to any one of them - like a real focus group, only faster, at any scale.
          </p>

          {/* Inline signup */}
          <form onSubmit={(e) => { e.preventDefault(); alert('Thanks - we\'ll be in touch.'); }} style={{
            display: 'flex', gap: 8, marginBottom: 14,
            background: 'var(--bg-elevated)',
            border: '1px solid var(--border-2)',
            borderRadius: 10, padding: 6,
            boxShadow: 'var(--shadow-sm)',
            maxWidth: 480,
          }}>
            <input
              type="email" required placeholder="you@company.com"
              style={{
                flex: 1, fontFamily: 'inherit', fontSize: 14,
                color: 'var(--fg-1)', background: 'transparent',
                border: 'none', outline: 'none', padding: '10px 12px',
              }} />
            <button type="submit" style={{
              padding: '10px 18px', borderRadius: 7, border: 'none',
              background: 'var(--accent-2)', color: '#fff',
              fontSize: 14, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
              whiteSpace: 'nowrap',
            }}>Sign up - it's free</button>
          </form>
          <div style={{ fontSize: 12, color: 'var(--fg-3)', marginBottom: 32 }}>
            Free during beta · No credit card · <a href="#demo" style={{ color: 'var(--accent)', textDecoration: 'none', fontWeight: 600 }}>or request a demo →</a>
          </div>

          {/* Stage progression rail (now reflects auto-loop, not scroll) */}
          <div style={{ borderTop: '1px solid var(--border-1)', paddingTop: 16 }}>
            <div style={{ fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--fg-3)', fontWeight: 700, marginBottom: 12 }}>
              How Lokara works - three steps
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {STAGES.map((st, i) => {
                const active = i === activeStage;
                const done = i < activeStage;
                const fillP = i === 0 ? s1 : i === 1 ? s2 : s3;
                return (
                  <div key={i} style={{
                    display: 'grid', gridTemplateColumns: '34px 1fr 60px',
                    alignItems: 'center', gap: 12, padding: '6px 0',
                  }}>
                    <span style={{
                      fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700,
                      color: active ? 'var(--accent-2)' : done ? 'var(--accent)' : 'var(--fg-4)',
                      letterSpacing: '0.06em',
                    }}>{st.num}</span>
                    <span style={{
                      fontSize: 14, fontWeight: 600,
                      color: active ? 'var(--fg-1)' : done ? 'var(--fg-2)' : 'var(--fg-4)',
                      transition: 'color 200ms',
                    }}>{st.label}</span>
                    <span style={{
                      height: 3, borderRadius: 2,
                      background: 'var(--bg-sunken)', overflow: 'hidden', position: 'relative',
                    }}>
                      <span style={{
                        position: 'absolute', inset: 0,
                        background: active ? 'var(--accent-2)' : 'var(--accent)',
                        transformOrigin: 'left',
                        transform: `scaleX(${done ? 1 : fillP})`,
                        transition: 'transform 80ms linear',
                      }}></span>
                    </span>
                  </div>
                );
              })}
            </div>
          </div>
        </div>

        {/* RIGHT - device frame, all 3 stages cross-fading on a loop */}
        <div style={{
          background: 'var(--bg-elevated)',
          border: '1px solid var(--border-1)',
          borderRadius: 18, boxShadow: 'var(--shadow-xl)', overflow: 'hidden',
          height: 'min(78vh, 640px)', minHeight: 520,
          display: 'flex', flexDirection: 'column', position: 'relative',
        }}>
          <div style={{
            height: 40, borderBottom: '1px solid var(--border-1)',
            background: 'var(--bg-sunken)',
            display: 'flex', alignItems: 'center', padding: '0 16px', gap: 10, flexShrink: 0,
          }}>
            <div style={{ display: 'flex', gap: 6 }}>
              <span style={{ width: 11, height: 11, borderRadius: '50%', background: '#E1685A' }}></span>
              <span style={{ width: 11, height: 11, borderRadius: '50%', background: '#E5C44E' }}></span>
              <span style={{ width: 11, height: 11, borderRadius: '50%', background: '#7BC97A' }}></span>
            </div>
            <span style={{
              fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 600,
              letterSpacing: '0.08em', color: 'var(--fg-3)',
              textTransform: 'uppercase', marginLeft: 6,
            }}>lokara · sim_8f3a · refillable shampoo</span>
            <span style={{ flex: 1 }}></span>
            <span style={{
              fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--accent-2)',
              fontWeight: 700, letterSpacing: '0.06em',
            }}>● LIVE</span>
          </div>
          <div style={{ flex: 1, position: 'relative', overflow: 'hidden' }}>
            <PopulationStage progress={s1} fade={fade1} />
            <BranchingStage progress={s2} fade={fade2} />
            <ChatStage progress={s3} fade={fade3} />
          </div>
        </div>
      </div>
    </section>
  );
};

const clamp = (v, a = 0, b = 1) => Math.max(a, Math.min(b, v));
const invLerp = (v, a, b) => (v - a) / (b - a);
const smoothstep = (v, a, b) => {
  const t = clamp(invLerp(v, a, b));
  return t * t * (3 - 2 * t);
};

window.ScrollSimHero = ScrollSimHero;
