/* LOOP SEQUENCE - "Neural Sync Protocol" HUD over the second video.
   Frame loader / smoothed paint loop unchanged from prior version.
   The overlay is a 6-phase scroll-driven HUD: BOOT → SCAN → 3 STATEMENTS → CLIMAX. */
function LoopSequence() {
  const sectionRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  const framesRef = React.useRef([]);
  const [framesReady, setFramesReady] = React.useState(false);
  const [loadPct, setLoadPct] = React.useState(0);
  const progress = useSectionProgress(sectionRef);
  const progressRef = React.useRef(0);
  React.useEffect(() => { progressRef.current = progress; }, [progress]);
  const isMobile = useIsMobile();
  const isMobileInitial = React.useRef(isMobile);

  // ── Frame loader (mobile/desktop variant) ──────────────────────────
  React.useEffect(() => {
    let cancelled = false;
    const TOTAL_AVAILABLE = 301;
    const STEP = isMobileInitial.current ? 6 : 3;
    const MAX_W = isMobileInitial.current ? 600 : 960;
    const folder = isMobileInitial.current ? 'frames_v2_mobile' : 'frames_v2';
    const indices = [];
    for (let i = 1; i <= TOTAL_AVAILABLE; i += STEP) indices.push(i);

    (async () => {
      const frames = new Array(indices.length);
      let loaded = 0;
      const loadOne = (n, idx) => new Promise((resolve) => {
        const img = new Image();
        img.decoding = 'async';
        img.onload = () => {
          const scale = Math.min(1, MAX_W / img.naturalWidth);
          const W = Math.round(img.naturalWidth * scale);
          const H = Math.round(img.naturalHeight * scale);
          const c = document.createElement('canvas');
          c.width = W; c.height = H;
          c.getContext('2d').drawImage(img, 0, 0, W, H);
          frames[idx] = c;
          loaded++;
          if (!cancelled) setLoadPct(loaded / indices.length);
          resolve();
        };
        img.onerror = () => { loaded++; if (!cancelled) setLoadPct(loaded / indices.length); resolve(); };
        img.src = `${folder}/frame_${String(n).padStart(4, '0')}.jpg`;
      });
      const CONC = 8;
      let cur = 0;
      const workers = Array.from({ length: CONC }, async () => {
        while (cur < indices.length && !cancelled) {
          const i = cur++;
          await loadOne(indices[i], i);
        }
      });
      await Promise.all(workers);
      framesRef.current = frames.filter(Boolean);
      if (!cancelled) setFramesReady(true);
    })();
    return () => { cancelled = true; };
  }, []);

  // ── Smoothed paint loop (unchanged) ─────────────────────────────────
  const smoothedRef = React.useRef(0);
  React.useEffect(() => {
    if (!framesReady) return;
    const cv = canvasRef.current;
    if (!cv) return;
    const ctx = cv.getContext('2d');
    let raf = 0;
    let lastIdx = -1;
    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      cv.width = Math.round(window.innerWidth * dpr);
      cv.height = Math.round(window.innerHeight * dpr);
      cv.style.width = window.innerWidth + 'px';
      cv.style.height = window.innerHeight + 'px';
      lastIdx = -1;
    };
    const paint = () => {
      const total = framesRef.current.length;
      if (!total) return;
      const target = progressRef.current;
      const diff = target - smoothedRef.current;
      smoothedRef.current = Math.abs(diff) < 0.0002 ? target : smoothedRef.current + diff * 0.16;
      const p = smoothedRef.current;
      const idx = clamp(Math.round(p * (total - 1)), 0, total - 1);
      if (idx !== lastIdx) {
        const cw = cv.width, ch = cv.height;
        const fr = framesRef.current[idx];
        if (!fr) return;
        const scale = Math.max(cw / fr.width, ch / fr.height);
        const dw = fr.width * scale, dh = fr.height * scale;
        const dx = (cw - dw) / 2, dy = (ch - dh) / 2;
        ctx.globalCompositeOperation = 'copy';
        ctx.drawImage(fr, dx, dy, dw, dh);
        ctx.globalCompositeOperation = 'source-over';
        lastIdx = idx;
      }
    };
    const tick = () => { paint(); raf = requestAnimationFrame(tick); };
    resize();
    window.addEventListener('resize', resize);
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); };
  }, [framesReady]);

  // ── Phase windows ──────────────────────────────────────────────────
  const W = {
    boot:   { in0: 0.00, in1: 0.06, out0: 0.95, out1: 1.0  }, // HUD persists almost to end
    scan:   { in0: 0.06, in1: 0.12, out0: 0.20, out1: 0.24 },
    s1:     { in0: 0.22, in1: 0.28, out0: 0.36, out1: 0.42 },
    s2:     { in0: 0.42, in1: 0.48, out0: 0.56, out1: 0.62 },
    s3:     { in0: 0.62, in1: 0.68, out0: 0.76, out1: 0.82 },
    climax: { in0: 0.82, in1: 0.90, out0: 1.10, out1: 1.20 }, // never exits in-section
  };
  const vis = (w) => Math.min(smoothstep(w.in0, w.in1, progress), 1 - smoothstep(w.out0, w.out1, progress));

  const bootP   = smoothstep(0.00, 0.06, progress);
  const scanP   = smoothstep(0.08, 0.22, progress);
  const s1V     = vis(W.s1);
  const s2V     = vis(W.s2);
  const s3V     = vis(W.s3);
  const climaxP = smoothstep(0.82, 0.94, progress);

  // Active phase index (for indicator)
  let phaseIdx = 0;
  if (progress >= 0.06) phaseIdx = 1; // scan
  if (progress >= 0.22) phaseIdx = 2; // s1
  if (progress >= 0.42) phaseIdx = 3; // s2
  if (progress >= 0.62) phaseIdx = 4; // s3
  if (progress >= 0.82) phaseIdx = 5; // climax

  // ── Particles (seeded once) ────────────────────────────────────────
  const particleCount = isMobileInitial.current ? 20 : 48;
  const particles = React.useMemo(() => {
    const arr = [];
    for (let i = 0; i < particleCount; i++) {
      const angle = Math.random() * Math.PI * 2;
      const dist = 320 + Math.random() * 480;
      arr.push({
        ox: Math.cos(angle) * dist,
        oy: Math.sin(angle) * dist,
        size: 2 + Math.random() * 3,
        delay: Math.random() * 280,
      });
    }
    return arr;
  }, []);

  return (
    <section ref={sectionRef} style={{position:'relative', height: isMobile ? '560vh' : '460vh', background:'#0A0907'}}>
      <style>{`
        @keyframes nsp-spin    { from{transform:translate(-50%,-50%) rotate(0)} to{transform:translate(-50%,-50%) rotate(360deg)} }
        @keyframes nsp-spinR   { from{transform:rotate(0)} to{transform:rotate(-360deg)} }
        @keyframes nsp-blink   { 0%,49%{opacity:1} 50%,100%{opacity:0} }
        @keyframes nsp-pulse   { 0%,100%{transform:scale(1)} 50%{transform:scale(1.08)} }
        @keyframes nsp-glitch  {
          0%   { transform:translate(0,0); text-shadow:0 0 transparent; }
          12%  { transform:translate(-3px,1px) skewX(-2deg); text-shadow:3px 0 #ff3b6b,-3px 0 #2dd4f7; }
          24%  { transform:translate(3px,-1px) skewX(1deg);  text-shadow:-2px 0 #ff3b6b,2px 0 #2dd4f7; }
          38%  { transform:translate(-2px,2px); text-shadow:4px 0 #ff3b6b,-4px 0 #2dd4f7; }
          52%  { transform:translate(1px,-2px) skewX(-1deg); text-shadow:-1px 0 #ff3b6b,1px 0 #2dd4f7; }
          68%  { transform:translate(-1px,0); text-shadow:2px 0 #ff3b6b,-2px 0 #2dd4f7; }
          84%  { transform:translate(0,1px); text-shadow:1px 0 #ff3b6b,-1px 0 #2dd4f7; }
          100% { transform:translate(0,0); text-shadow:0 0 transparent; }
        }
        @keyframes nsp-ticker  { from{transform:translateX(0)} to{transform:translateX(-50%)} }
        @keyframes nsp-corner-pulse { 0%,100%{opacity:0.85} 50%{opacity:1} }
      `}</style>

      <div style={{position:'sticky', top:0, height:'100vh', overflow:'hidden'}}>
        {/* VIDEO CANVAS */}
        <canvas
          ref={canvasRef}
          style={{position:'absolute', inset:0, width:'100%', height:'100%', display:'block',
                  filter:'saturate(0.95) contrast(1.06)'}}
        />

        {/* LOADER */}
        {!framesReady && (
          <div style={{position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', gap:20, background:'#0A0907', zIndex:30}}>
            <div style={{fontSize:11, letterSpacing:'0.22em', textTransform:'uppercase', color:'#EEB332', fontFamily:'monospace'}}>SYNCING NEURAL CORE</div>
            <div style={{width:240, height:2, background:'rgba(245,242,237,0.08)', borderRadius:500, overflow:'hidden'}}>
              <div style={{height:'100%', width:`${loadPct*100}%`, background:'linear-gradient(90deg, #DD9933, #FFD777)', boxShadow:'0 0 12px #EEB332', transition:'width 120ms linear'}} />
            </div>
            <div style={{fontSize:12, color:'rgba(245,242,237,0.45)', fontFamily:'monospace'}}>{Math.round(loadPct*100)}%</div>
          </div>
        )}

        {/* DARKEN OVERLAY - keeps HUD readable */}
        <div style={{position:'absolute', inset:0, pointerEvents:'none',
          background:'radial-gradient(ellipse at 50% 50%, rgba(10,9,7,0.15) 0%, rgba(10,9,7,0.5) 80%)'}} />

        {/* HEX GRID - faint texture */}
        <div style={{position:'absolute', inset:0, pointerEvents:'none', opacity:0.06,
          backgroundImage:'linear-gradient(rgba(238,179,50,1) 1px, transparent 1px), linear-gradient(90deg, rgba(238,179,50,1) 1px, transparent 1px)',
          backgroundSize:'60px 60px',
          maskImage:'radial-gradient(ellipse at center, black 30%, transparent 75%)',
          WebkitMaskImage:'radial-gradient(ellipse at center, black 30%, transparent 75%)'}} />

        {/* HUD CORNERS - 4 L-shaped brackets */}
        <HUDCorners bootP={bootP} />

        {/* STATUS READOUT - top-left */}
        <StatusReadout progress={progress} phaseIdx={phaseIdx} bootP={bootP} />

        {/* PHASE LABEL - top-right */}
        <PhaseLabel phaseIdx={phaseIdx} bootP={bootP} />

        {/* SCAN SWEEP - horizontal bright line during SCAN phase */}
        <ScanSweep progress={progress} />

        {/* CROSSHAIR - center reticle */}
        <Crosshair progress={progress} />

        {/* AR LABELS - 3 staggered pins during SCAN */}
        <ARLabels progress={progress} />

        {/* STATEMENT 1 - particle convergence + chromatic headline */}
        <ParticleStatement
          visible={s1V}
          progress={progress}
          window={W.s1}
          particles={particles}
          headline="בלי לדעת לתכנת."
          subtitle="> ZERO.CODE.NEEDED"
        />

        {/* STATEMENT 2 - glitch headline */}
        <GlitchStatement
          visible={s2V}
          progress={progress}
          window={W.s2}
          headline="תבנה מערכות שלמות."
          subtitle="> SHIP.REAL.SYSTEMS"
        />

        {/* STATEMENT 3 - pinpoint expand + accent pulse on last word */}
        <PulseStatement
          visible={s3V}
          progress={progress}
          window={W.s3}
          headline="תרוויח כל חודש."
          subtitle="> MONTHLY.REVENUE"
        />

        {/* CLIMAX - arc reactor + headline + deploy */}
        <Climax climaxP={climaxP} />

        {/* RIGHT-EDGE PROGRESS NODES */}
        <ProgressNodes phaseIdx={phaseIdx} />

        {/* BOTTOM DATA TICKER */}
        <BottomTicker phaseIdx={phaseIdx} bootP={bootP} />
      </div>
    </section>
  );
}

/* ─────────────────────────────────────────────────────────────────────
   SUBCOMPONENTS
   ───────────────────────────────────────────────────────────────────── */

function HUDCorners({ bootP }) {
  const isMobile = useIsMobile();
  const stagger = [0, 0.08, 0.16, 0.24];
  const TOP = isMobile ? 60 : 80;
  const SIDE = isMobile ? 14 : 24;
  const SIZE = isMobile ? 40 : 56;
  const corners = [
    { top: TOP, left: SIDE,     borderTop: '1px solid #EEB332', borderLeft: '1px solid #EEB332' },
    { top: TOP, right: SIDE,    borderTop: '1px solid #EEB332', borderRight: '1px solid #EEB332' },
    { bottom: TOP, left: SIDE,  borderBottom: '1px solid #EEB332', borderLeft: '1px solid #EEB332' },
    { bottom: TOP, right: SIDE, borderBottom: '1px solid #EEB332', borderRight: '1px solid #EEB332' },
  ];
  return (
    <>
      {corners.map((c, i) => {
        const p = clamp((bootP - stagger[i]) / 0.15, 0, 1);
        return (
          <div key={i} style={{
            position:'absolute', width:SIZE, height:SIZE,
            ...c,
            opacity: p,
            transform: `scale(${lerp(0.4, 1, p)})`,
            boxShadow: '0 0 12px rgba(238,179,50,0.4)',
            pointerEvents:'none',
            transition:'opacity 200ms, transform 200ms cubic-bezier(0.22,1,0.36,1)',
            animation: p > 0.95 ? 'nsp-corner-pulse 4s ease-in-out infinite' : 'none',
          }} />
        );
      })}
    </>
  );
}

function StatusReadout({ progress, phaseIdx, bootP }) {
  const isMobile = useIsMobile();
  const bootLine = '[BOOT] CLAUDE.CORE v4.7 ▸ ONLINE';
  const persistentLine = isMobile ? 'CLAUDE.CORE v4.7 │ ONLINE' : 'CLAUDE.CORE v4.7 │ UPLINK STABLE │ LATENCY 12ms';
  const phaseTags = ['INITIALIZING', 'SCANNING ENVIRONMENT', 'NEURAL UPLINK', 'EXECUTING', 'SYNTHESIS', 'READY'];

  // Typewriter for boot line
  const bootChars = Math.floor(clamp(bootP * 1.4, 0, 1) * bootLine.length);
  const bootText = bootLine.slice(0, bootChars);
  const showPersistent = progress > 0.06;

  return (
    <div dir="ltr" style={{
      position:'absolute', top: isMobile ? 86 : 36, left: isMobile ? 12 : 36,
      fontFamily:'monospace', fontSize: isMobile ? 9 : 11, letterSpacing:'0.08em',
      color:'#EEB332', textShadow:'0 0 8px rgba(238,179,50,0.5)',
      pointerEvents:'none', zIndex:5, maxWidth: isMobile ? '70vw' : 'none',
    }}>
      <div style={{display:'flex', alignItems:'center', gap:8, marginBottom:6}}>
        <span style={{width:8, height:8, borderRadius:'50%', background:'#EEB332', boxShadow:'0 0 12px #EEB332', animation:'nsp-blink 1.2s steps(1) infinite'}} />
        <span>{showPersistent ? persistentLine : bootText}</span>
        {!showPersistent && bootChars < bootLine.length && (
          <span style={{display:'inline-block', width:7, height:12, background:'#EEB332', verticalAlign:'middle', animation:'nsp-blink 0.6s steps(1) infinite'}} />
        )}
      </div>
      <div style={{fontSize:10, color:'rgba(238,179,50,0.6)', letterSpacing:'0.18em'}}>
        ▸ {phaseTags[phaseIdx]}
      </div>
    </div>
  );
}

function PhaseLabel({ phaseIdx, bootP }) {
  const isMobile = useIsMobile();
  return (
    <div dir="ltr" style={{
      position:'absolute', top: isMobile ? 86 : 36, right: isMobile ? 12 : 36,
      fontFamily:'monospace', fontSize: isMobile ? 9 : 11, letterSpacing:'0.18em',
      color:'rgba(245,242,237,0.7)', textAlign:'right',
      opacity: bootP, pointerEvents:'none', zIndex:5,
    }}>
      <div>NEURAL SYNC</div>
      <div style={{fontSize: isMobile ? 8 : 9, color:'#EEB332', marginTop:4}}>PROTOCOL · {String(phaseIdx).padStart(2,'0')}/05</div>
    </div>
  );
}

function ScanSweep({ progress }) {
  const sweepP = smoothstep(0.06, 0.22, progress);
  const opacity = Math.sin(sweepP * Math.PI); // peaks mid-window
  return (
    <div style={{
      position:'absolute', left:0, right:0,
      top: `${lerp(-5, 105, sweepP)}%`,
      height:3,
      background:'linear-gradient(90deg, transparent, rgba(238,179,50,0.9), #FFD777, rgba(238,179,50,0.9), transparent)',
      boxShadow:'0 0 24px #EEB332, 0 0 60px rgba(238,179,50,0.6)',
      opacity: opacity * 0.95,
      pointerEvents:'none', zIndex:6,
    }} />
  );
}

function Crosshair({ progress }) {
  const isMobile = useIsMobile();
  const SIZE = isMobile ? 130 : 200;
  const INNER = isMobile ? 56 : 80;
  const v = Math.min(smoothstep(0.06, 0.14, progress), 1 - smoothstep(0.20, 0.26, progress));
  return (
    <div style={{
      position:'absolute', top:'50%', left:'50%',
      width:SIZE, height:SIZE,
      opacity: v, pointerEvents:'none', zIndex:5,
      transform:'translate(-50%, -50%)',
    }}>
      {/* rotating ring */}
      <div style={{
        position:'absolute', top:'50%', left:'50%',
        width:SIZE, height:SIZE, borderRadius:'50%',
        border:'1px dashed rgba(238,179,50,0.5)',
        animation:'nsp-spin 8s linear infinite',
      }} />
      {/* solid inner circle */}
      <div style={{
        position:'absolute', top:'50%', left:'50%',
        transform:'translate(-50%, -50%)',
        width:INNER, height:INNER, borderRadius:'50%',
        border:'1px solid rgba(238,179,50,0.8)',
        boxShadow:'0 0 16px rgba(238,179,50,0.5), inset 0 0 16px rgba(238,179,50,0.2)',
      }} />
      {/* center dot */}
      <div style={{
        position:'absolute', top:'50%', left:'50%',
        transform:'translate(-50%, -50%)',
        width:6, height:6, borderRadius:'50%', background:'#FFD777',
        boxShadow:'0 0 12px #EEB332',
      }} />
      {/* crosshair lines */}
      {[0, 90, 180, 270].map(deg => (
        <div key={deg} style={{
          position:'absolute', top:'50%', left:'50%',
          width:32, height:1, background:'rgba(238,179,50,0.7)',
          transformOrigin:'0 0',
          transform:`rotate(${deg}deg) translate(60px, 0)`,
        }} />
      ))}
    </div>
  );
}

function ARLabels({ progress }) {
  const isMobile = useIsMobile();
  const allLabels = [
    { text: 'OPERATOR ▸ HUMAN',   pos:{top:'24%', right:'12%'}, anchor:{top:'40%', right:'30%'}, in0:0.10, in1:0.14, out0:0.22, out1:0.26 },
    { text: 'INPUT ▸ INTENT',     pos:{top:'68%', left:'10%'},  anchor:{top:'55%', left:'34%'},  in0:0.13, in1:0.17, out0:0.22, out1:0.26 },
    { text: 'ROLE ▸ ARCHITECT',   pos:{top:'18%', left:'14%'},  anchor:{top:'34%', left:'36%'},  in0:0.16, in1:0.20, out0:0.22, out1:0.26 },
  ];
  // On mobile, drop the third label (overlaps with the headline area on narrow screens)
  const labels = isMobile ? allLabels.slice(0, 2) : allLabels;
  return (
    <>
      {labels.map((l, i) => {
        const v = Math.min(smoothstep(l.in0, l.in1, progress), 1 - smoothstep(l.out0, l.out1, progress));
        return (
          <div key={i} dir="ltr" style={{
            position:'absolute', ...l.pos,
            opacity: v, pointerEvents:'none', zIndex:5,
            transform:`translateY(${lerp(-8, 0, smoothstep(l.in0, l.in1, progress))}px)`,
            transition:'opacity 200ms, transform 240ms cubic-bezier(0.22,1,0.36,1)',
          }}>
            <div style={{
              display:'inline-flex', alignItems:'center', gap: isMobile ? 6 : 8,
              padding: isMobile ? '4px 9px' : '6px 12px',
              border:'1px solid rgba(238,179,50,0.55)',
              background:'rgba(10,9,7,0.6)',
              backdropFilter:'blur(8px)', WebkitBackdropFilter:'blur(8px)',
              fontFamily:'monospace', fontSize: isMobile ? 8 : 10, letterSpacing:'0.16em',
              color:'#EEB332', textShadow:'0 0 6px rgba(238,179,50,0.5)',
              boxShadow:'0 0 14px rgba(238,179,50,0.3)',
            }}>
              <span style={{width:5, height:5, background:'#EEB332', borderRadius:'50%', boxShadow:'0 0 8px #EEB332'}} />
              {l.text}
            </div>
          </div>
        );
      })}
    </>
  );
}

/* Per-character split. inline-block so each char can transform independently. */
function CharSplit({ text, perChar }) {
  const chars = Array.from(text);
  return (
    <>{chars.map((ch, i) => (
      <span key={i} style={{display:'inline-block', whiteSpace:'pre', ...(perChar ? perChar(ch, i, chars.length) : {})}}>
        {ch === ' ' ? ' ' : ch}
      </span>
    ))}</>
  );
}

function ParticleStatement({ visible, progress, window, particles, headline, subtitle }) {
  const isMobile = useIsMobile();
  const enterP = smoothstep(window.in0, window.in1, progress);
  const exitP  = 1 - smoothstep(window.out0, window.out1, progress);
  const headlineP = smoothstep(window.in0 + 0.02, window.in1 + 0.02, progress);
  const subP = smoothstep(window.in1, window.in1 + 0.06, progress);

  // Particles converge during enter, scatter during exit
  const convergeP = enterP * exitP;

  return (
    <div style={{
      position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
      flexDirection:'column', padding:'0 24px', textAlign:'center', pointerEvents:'none', zIndex:7,
      opacity: visible,
      transition:'opacity 200ms linear',
    }}>
      <div style={{position:'relative'}}>
        {/* PARTICLES - relative to headline center */}
        {particles.map((pt, i) => {
          const localProgress = clamp(((convergeP * 1000) - pt.delay) / 600, 0, 1);
          const x = lerp(pt.ox, 0, localProgress);
          const y = lerp(pt.oy, 0, localProgress);
          const op = Math.sin(localProgress * Math.PI) * 0.9;
          return (
            <span key={i} style={{
              position:'absolute', top:'50%', left:'50%',
              width: pt.size, height: pt.size, borderRadius:'50%',
              background:'#FFD777',
              boxShadow:'0 0 6px #EEB332',
              transform:`translate(${x}px, ${y}px)`,
              opacity: op,
              pointerEvents:'none',
            }} />
          );
        })}

        {/* HEADLINE - per-char fade, chromatic during reveal */}
        <h2 style={{
          fontFamily:'Open Sans', fontWeight:900, fontSize: isMobile ? 'clamp(34px, 9vw, 56px)' : 'clamp(56px, 9vw, 144px)',
          lineHeight:1.0, letterSpacing:'-0.025em', margin:0,
          color:'#F5F2ED',
          direction:'rtl', whiteSpace: 'normal',
        }}>
          <CharSplit text={headline} perChar={(ch, i, n) => {
            const start = window.in0 + 0.04 + (i / n) * 0.04;
            const charP = smoothstep(start, start + 0.04, progress);
            const settled = smoothstep(start + 0.04, start + 0.08, progress);
            const chromaAmt = (1 - settled) * 3;
            return {
              opacity: charP,
              textShadow: chromaAmt > 0.1
                ? `${chromaAmt}px 0 #ff3b6b, -${chromaAmt}px 0 #2dd4f7, 0 4px 40px rgba(0,0,0,0.7)`
                : '0 4px 40px rgba(0,0,0,0.7)',
              transition:'text-shadow 120ms linear',
            };
          }} />
        </h2>

        {/* SUBTITLE - monospace typewriter */}
        <div dir="ltr" style={{
          marginTop:24,
          fontFamily:'monospace', fontSize:'clamp(13px, 1.2vw, 17px)',
          letterSpacing:'0.18em',
          color:'#EEB332', textShadow:'0 0 8px rgba(238,179,50,0.4)',
          opacity: subP,
        }}>
          {subtitle.slice(0, Math.floor(subP * subtitle.length))}
          {subP > 0.05 && subP < 0.98 && (
            <span style={{display:'inline-block', width:8, height:14, background:'#EEB332', verticalAlign:'middle', marginLeft:2, animation:'nsp-blink 0.6s steps(1) infinite'}} />
          )}
        </div>
      </div>
    </div>
  );
}

function GlitchStatement({ visible, progress, window, headline, subtitle }) {
  const isMobile = useIsMobile();
  const enterP = smoothstep(window.in0, window.in1, progress);
  const exitP  = 1 - smoothstep(window.out0, window.out1, progress);
  // Exit: collapse toward pinpoint
  const collapseScale = lerp(1, 0.04, 1 - exitP);
  const collapseOp = exitP;
  // Glitch active during enter only
  const glitchOn = progress > window.in0 - 0.02 && progress < window.in1 + 0.05;
  const subP = smoothstep(window.in1, window.in1 + 0.06, progress) * exitP;

  return (
    <div style={{
      position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
      flexDirection:'column', padding:'0 24px', textAlign:'center', pointerEvents:'none', zIndex:7,
      opacity: visible,
      transform:`scale(${collapseScale})`,
      transition:'opacity 200ms linear, transform 280ms cubic-bezier(0.7,0,0.3,1)',
    }}>
      <h2 style={{
        fontFamily:'Open Sans', fontWeight:900, fontSize: isMobile ? 'clamp(34px, 9vw, 56px)' : 'clamp(56px, 9vw, 144px)',
        lineHeight:1.0, letterSpacing:'-0.025em', margin:0,
        color:'#F5F2ED', direction:'rtl', whiteSpace: 'normal',
      }}>
        <CharSplit text={headline} perChar={(ch, i, n) => {
          const start = window.in0 + (i / n) * 0.03;
          const charP = smoothstep(start, start + 0.03, progress);
          return {
            opacity: charP * collapseOp,
            animation: glitchOn ? `nsp-glitch 320ms cubic-bezier(0.22,1,0.36,1) ${i * 30}ms 1 both` : 'none',
            textShadow:'0 4px 40px rgba(0,0,0,0.7)',
          };
        }} />
      </h2>
      <div dir="ltr" style={{
        marginTop:24,
        fontFamily:'monospace', fontSize:'clamp(13px, 1.2vw, 17px)',
        letterSpacing:'0.18em',
        color:'#EEB332', textShadow:'0 0 8px rgba(238,179,50,0.4)',
        opacity: subP,
      }}>
        {subtitle.slice(0, Math.floor(subP * subtitle.length))}
      </div>
    </div>
  );
}

function PulseStatement({ visible, progress, window, headline, subtitle }) {
  const isMobile = useIsMobile();
  const enterP = smoothstep(window.in0, window.in1, progress);
  const exitP  = 1 - smoothstep(window.out0, window.out1, progress);
  // Expand from pinpoint
  const scale = lerp(0.04, 1, enterP);
  const subP = smoothstep(window.in1, window.in1 + 0.06, progress) * exitP;

  // Split headline at last space - pre = everything up to last word, accent = last word (gradient + pulse)
  const lastSpace = headline.lastIndexOf(' ');
  const before = lastSpace >= 0 ? headline.slice(0, lastSpace + 1) : '';
  const accent = lastSpace >= 0 ? headline.slice(lastSpace + 1) : headline;

  return (
    <div style={{
      position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
      flexDirection:'column', padding:'0 24px', textAlign:'center', pointerEvents:'none', zIndex:7,
      opacity: visible,
    }}>
      <h2 dir="rtl" style={{
        fontFamily:'Open Sans', fontWeight:900, fontSize: isMobile ? 'clamp(38px, 11vw, 64px)' : 'clamp(72px, 11vw, 180px)',
        lineHeight:1.0, letterSpacing:'-0.03em', margin:0,
        color:'#F5F2ED', whiteSpace: 'normal',
        transform:`scale(${scale})`,
        transition:'transform 200ms cubic-bezier(0.22,1,0.36,1)',
        textShadow:'0 4px 40px rgba(0,0,0,0.7)',
      }}>
        <span style={{display:'inline-block'}}>{before}</span>
        <span style={{
          display:'inline-block',
          background:'linear-gradient(180deg, #FFD777 0%, #EEB332 50%, #B27418 100%)',
          WebkitBackgroundClip:'text', WebkitTextFillColor:'transparent', backgroundClip:'text',
          filter:'drop-shadow(0 0 24px rgba(238,179,50,0.7))',
          animation: enterP > 0.6 ? 'nsp-pulse 1.6s ease-in-out infinite' : 'none',
        }}>{accent}</span>
      </h2>
      <div dir="ltr" style={{
        marginTop:32,
        fontFamily:'monospace', fontSize:'clamp(13px, 1.2vw, 17px)',
        letterSpacing:'0.18em',
        color:'#EEB332', textShadow:'0 0 8px rgba(238,179,50,0.4)',
        opacity: subP,
      }}>
        {subtitle.slice(0, Math.floor(subP * subtitle.length))}
      </div>
    </div>
  );
}

function Climax({ climaxP }) {
  const isMobile = useIsMobile();
  // Arc reactor sizes scale down on mobile
  const ARC = isMobile ? 220 : 340;
  const CENTER = ARC / 2;
  const r1 = isMobile ? 48 : 70;
  const r2 = isMobile ? 72 : 110;
  const r3 = isMobile ? 100 : 150;
  const coreR = isMobile ? 40 : 60;
  const c1 = 2 * Math.PI * r1;
  const c2 = 2 * Math.PI * r2;
  // CTA orbit dims
  const ctaW = isMobile ? 220 : 280;
  const ctaH = isMobile ? 64 : 80;

  return (
    <div style={{
      position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
      flexDirection:'column', padding:'0 16px', pointerEvents: climaxP > 0.5 ? 'auto' : 'none', zIndex:8,
      opacity: climaxP,
    }}>
      {/* ARC REACTOR */}
      <div style={{position:'relative', width:ARC, height:ARC, marginBottom: isMobile ? 22 : 32}}>
        <svg width={ARC} height={ARC} viewBox={`0 0 ${ARC} ${ARC}`} style={{position:'absolute', inset:0}}>
          <defs>
            <radialGradient id="coreGlow" cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="#FFD777" stopOpacity="0.95" />
              <stop offset="35%" stopColor="#EEB332" stopOpacity="0.5" />
              <stop offset="100%" stopColor="#EEB332" stopOpacity="0" />
            </radialGradient>
          </defs>
          {/* core blob */}
          <circle cx={CENTER} cy={CENTER} r={coreR} fill="url(#coreGlow)" />
          {/* ring 1 */}
          <circle cx={CENTER} cy={CENTER} r={r1}
            fill="none" stroke="#FFD777" strokeWidth="2"
            strokeDasharray={`${climaxP * c1} ${c1}`}
            transform={`rotate(-90 ${CENTER} ${CENTER})`}
            style={{filter:'drop-shadow(0 0 8px #EEB332)'}} />
          {/* ring 2 */}
          <circle cx={CENTER} cy={CENTER} r={r2}
            fill="none" stroke="#EEB332" strokeWidth="1.5"
            strokeDasharray={`${climaxP * c2 * 0.7} ${c2}`}
            transform={`rotate(90 ${CENTER} ${CENTER})`}
            style={{filter:'drop-shadow(0 0 6px #EEB332)'}} />
          {/* ring 3 - dashed */}
          <circle cx={CENTER} cy={CENTER} r={r3}
            fill="none" stroke="rgba(238,179,50,0.5)" strokeWidth="1"
            strokeDasharray="4 8" />
        </svg>
        {/* rotating spark */}
        <div style={{
          position:'absolute', top:'50%', left:'50%',
          width:r3 * 2, height:2,
          transform:'translate(-50%, -50%)',
          animation:'nsp-spinR 6s linear infinite',
          pointerEvents:'none',
        }}>
          <span style={{
            position:'absolute', right:0, top:'50%',
            transform:'translate(50%, -50%)',
            width:8, height:8, borderRadius:'50%', background:'#FFD777',
            boxShadow:'0 0 20px #EEB332, 0 0 40px #EEB332',
          }} />
        </div>
        {/* headline at center */}
        <div style={{
          position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          <h2 style={{
            fontFamily:'Open Sans', fontWeight:900, fontSize: isMobile ? 'clamp(22px, 6.5vw, 36px)' : 'clamp(28px, 3.4vw, 52px)',
            lineHeight:1, letterSpacing:'-0.025em', margin:0,
            color:'#F5F2ED', whiteSpace:'nowrap',
            textShadow:'0 0 30px rgba(238,179,50,0.7), 0 4px 20px rgba(0,0,0,0.8)',
          }}>תתחיל עכשיו</h2>
        </div>
      </div>

      {/* DEPLOY CTA */}
      <div style={{position:'relative', display:'inline-block', transform:`translateY(${lerp(20,0,climaxP)}px)`, transition:'transform 240ms'}}>
        {/* orbiting arc */}
        <svg width={ctaW} height={ctaH} viewBox={`0 0 ${ctaW} ${ctaH}`} style={{position:'absolute', top:'50%', left:'50%', transform:'translate(-50%, -50%)', pointerEvents:'none', animation:'nsp-spinR 4s linear infinite'}}>
          <ellipse cx={ctaW/2} cy={ctaH/2} rx={(ctaW/2) - 10} ry={(ctaH/2) - 6}
            fill="none" stroke="rgba(238,179,50,0.55)" strokeWidth="1"
            strokeDasharray="40 200" />
        </svg>
        <button onClick={() => scrollToSection('pricing')} style={{
          position:'relative', zIndex:1,
          background:'rgba(10,9,7,0.6)',
          color:'#EEB332',
          border:'2px solid #DD9933',
          borderRadius:500,
          padding: isMobile ? '12px 28px' : '16px 44px',
          fontSize: isMobile ? 13 : 16, fontFamily:'Open Sans, sans-serif', fontWeight:600, letterSpacing:'0.10em',
          cursor:'pointer', whiteSpace:'nowrap',
          boxShadow:'0 0 32px 4px rgba(238,179,50,0.45), inset 0 0 12px rgba(238,179,50,0.15)',
          backdropFilter:'blur(8px)', WebkitBackdropFilter:'blur(8px)',
        }}>הירשם לקורס ▸</button>
      </div>
    </div>
  );
}

function ProgressNodes({ phaseIdx }) {
  const isMobile = useIsMobile();
  if (isMobile) return null; // too cramped on phone, drop entirely
  const labels = ['BOOT', 'SCAN', 'STMT-1', 'STMT-2', 'STMT-3', 'CORE'];
  return (
    <div dir="ltr" style={{
      position:'absolute', top:'50%', right:36,
      transform:'translateY(-50%)',
      display:'flex', flexDirection:'column', gap:14,
      pointerEvents:'none', zIndex:5,
    }}>
      {labels.map((l, i) => {
        const active = i === phaseIdx;
        const passed = i < phaseIdx;
        return (
          <div key={l} style={{display:'flex', alignItems:'center', gap:10, justifyContent:'flex-end'}}>
            <span style={{
              fontFamily:'monospace', fontSize:9, letterSpacing:'0.16em',
              color: active ? '#EEB332' : passed ? 'rgba(238,179,50,0.45)' : 'rgba(245,242,237,0.25)',
              transition:'color 200ms',
            }}>{l}</span>
            <span style={{
              width: active ? 28 : 8, height:2, borderRadius:500,
              background: active ? '#EEB332' : passed ? 'rgba(238,179,50,0.45)' : 'rgba(245,242,237,0.15)',
              boxShadow: active ? '0 0 12px #EEB332' : 'none',
              transition:'all 240ms',
            }} />
          </div>
        );
      })}
    </div>
  );
}

function BottomTicker({ phaseIdx, bootP }) {
  const isMobile = useIsMobile();
  const messages = [
    '▸ DECOMPILING_INTENT [OK]',
    '▸ ROUTING_THOUGHT [OK]',
    '▸ SYNTHESIS [12ms]',
    '▸ TOKENS_IN 4128',
    '▸ TOKENS_OUT 8214',
    '▸ MCP.CHANNELS 6/6 ACTIVE',
    '▸ COMPILE [OK]',
    '▸ DEPLOY_HOOK READY',
  ];
  const climaxMessages = [
    '▸ NEURAL SYNC ▸ COMPLETE',
    '▸ ENTER ANYTIME',
    '▸ COURSE.LOCK [UNLOCKED]',
    '▸ COHORT FEB-2026 ▸ 7 SEATS LEFT',
  ];
  const stream = phaseIdx >= 5 ? climaxMessages : messages;
  const line = stream.join('   ');
  const doubled = line + '   ' + line + '   ' + line + '   ';

  return (
    <div dir="ltr" style={{
      position:'absolute', bottom: isMobile ? 14 : 24, left:0, right:0,
      overflow:'hidden',
      borderTop:'1px solid rgba(238,179,50,0.2)',
      borderBottom:'1px solid rgba(238,179,50,0.2)',
      background:'rgba(10,9,7,0.55)',
      backdropFilter:'blur(6px)', WebkitBackdropFilter:'blur(6px)',
      padding: isMobile ? '6px 0' : '8px 0',
      opacity: bootP,
      zIndex:5,
    }}>
      <div style={{
        whiteSpace:'nowrap',
        fontFamily:'monospace', fontSize: isMobile ? 9 : 11, letterSpacing:'0.14em',
        color: phaseIdx >= 5 ? '#FFD777' : 'rgba(238,179,50,0.85)',
        textShadow:'0 0 8px rgba(238,179,50,0.4)',
        animation:'nsp-ticker 28s linear infinite',
      }}>{doubled}</div>
    </div>
  );
}

window.LoopSequence = LoopSequence;
