/* Hero canvas: particle network + circuit lines */
function HeroCanvas({ accent, strength = 1 }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let w, h, dpr;
    let particles = [];
    let raf;
    let mouse = { x: -9999, y: -9999 };

    function resize() {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = canvas.clientWidth;
      h = canvas.clientHeight;
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const count = Math.floor((w * h) / 14000) * Math.max(0.4, strength);
      particles = [];
      for (let i = 0; i < count; i++) {
        particles.push({
          x: Math.random() * w,
          y: Math.random() * h,
          vx: (Math.random() - 0.5) * 0.3,
          vy: (Math.random() - 0.5) * 0.3,
          r: Math.random() * 1.5 + 0.5,
          c: Math.random() < 0.15 ? 'accent' : (Math.random() < 0.3 ? 'lime' : 'blue'),
        });
      }
    }

    const colors = {
      accent: () => accent,
      lime: () => '#b5f800',
      blue: () => '#0036ff',
    };

    function step() {
      ctx.clearRect(0, 0, w, h);
      // soft radial gradient bg
      const g = ctx.createRadialGradient(w*0.7, h*0.4, 50, w*0.5, h*0.5, Math.max(w, h));
      g.addColorStop(0, 'rgba(255,131,14,0.06)');
      g.addColorStop(0.4, 'rgba(0,54,255,0.05)');
      g.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = g;
      ctx.fillRect(0, 0, w, h);

      // update
      for (const p of particles) {
        p.x += p.vx; p.y += p.vy;
        if (p.x < 0) p.x = w; if (p.x > w) p.x = 0;
        if (p.y < 0) p.y = h; if (p.y > h) p.y = 0;

        const dx = p.x - mouse.x, dy = p.y - mouse.y;
        const d2 = dx*dx + dy*dy;
        if (d2 < 14400) {
          const f = (1 - d2/14400) * 0.6;
          p.x += (dx / Math.sqrt(d2 + 0.001)) * f;
          p.y += (dy / Math.sqrt(d2 + 0.001)) * f;
        }
      }

      // links
      ctx.lineWidth = 0.5;
      for (let i = 0; i < particles.length; i++) {
        for (let j = i+1; j < particles.length; j++) {
          const a = particles[i], b = particles[j];
          const dx = a.x-b.x, dy = a.y-b.y;
          const d2 = dx*dx + dy*dy;
          if (d2 < 14000) {
            const alpha = (1 - d2/14000) * 0.35;
            ctx.strokeStyle = `rgba(237,241,245,${alpha})`;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      // particles
      for (const p of particles) {
        ctx.fillStyle = colors[p.c]();
        ctx.shadowBlur = 8;
        ctx.shadowColor = colors[p.c]();
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI*2);
        ctx.fill();
      }
      ctx.shadowBlur = 0;

      raf = requestAnimationFrame(step);
    }

    function onMove(e) {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left;
      mouse.y = e.clientY - rect.top;
    }
    function onLeave() { mouse.x = -9999; mouse.y = -9999; }

    resize();
    step();
    window.addEventListener('resize', resize);
    canvas.addEventListener('mousemove', onMove);
    canvas.addEventListener('mouseleave', onLeave);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', resize);
      canvas.removeEventListener('mousemove', onMove);
      canvas.removeEventListener('mouseleave', onLeave);
    };
  }, [accent, strength]);

  return <canvas ref={ref} className="hero-canvas" />;
}

/* SVG Gear that spins on scroll */
function ScrollGear({ size = 400, color = '#ff830e', teeth = 12, direction = 1, opacity = 0.1, className = '' }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    function onScroll() {
      if (!ref.current) return;
      const y = window.scrollY;
      ref.current.style.transform = `rotate(${y * 0.15 * direction}deg)`;
    }
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [direction]);

  // build gear path
  const cx = 100, cy = 100;
  const outer = 88, inner = 70, hub = 28, hole = 14;
  const path = [];
  for (let i = 0; i < teeth; i++) {
    const a0 = (i / teeth) * Math.PI * 2;
    const a1 = ((i + 0.4) / teeth) * Math.PI * 2;
    const a2 = ((i + 0.6) / teeth) * Math.PI * 2;
    const a3 = ((i + 1) / teeth) * Math.PI * 2;
    if (i === 0) path.push(`M ${cx + Math.cos(a0)*inner} ${cy + Math.sin(a0)*inner}`);
    path.push(`L ${cx + Math.cos(a0)*outer} ${cy + Math.sin(a0)*outer}`);
    path.push(`L ${cx + Math.cos(a1)*outer} ${cy + Math.sin(a1)*outer}`);
    path.push(`L ${cx + Math.cos(a2)*inner} ${cy + Math.sin(a2)*inner}`);
    path.push(`L ${cx + Math.cos(a3)*inner} ${cy + Math.sin(a3)*inner}`);
  }
  path.push('Z');

  return (
    <svg
      ref={ref}
      className={className}
      width={size}
      height={size}
      viewBox="0 0 200 200"
      style={{ opacity, transition: 'transform 0.05s linear' }}
    >
      <path d={path.join(' ')} fill="none" stroke={color} strokeWidth="2" />
      <circle cx={cx} cy={cy} r={hub} fill="none" stroke={color} strokeWidth="2" />
      <circle cx={cx} cy={cy} r={hole} fill="none" stroke={color} strokeWidth="2" />
      {[0, 60, 120, 180, 240, 300].map(a => {
        const r1 = hub - 2, r2 = inner - 4;
        const x1 = cx + Math.cos(a*Math.PI/180)*r1;
        const y1 = cy + Math.sin(a*Math.PI/180)*r1;
        const x2 = cx + Math.cos(a*Math.PI/180)*r2;
        const y2 = cy + Math.sin(a*Math.PI/180)*r2;
        return <line key={a} x1={x1} y1={y1} x2={x2} y2={y2} stroke={color} strokeWidth="1.5" />;
      })}
    </svg>
  );
}

/* Reveal on scroll */
function Reveal({ children, delay = 0, as: Tag = 'div', className = '', ...rest }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          setTimeout(() => setShown(true), delay);
          io.disconnect();
        }
      });
    }, { threshold: 0.15 });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return (
    <Tag ref={ref} className={`reveal ${shown ? 'in' : ''} ${className}`} {...rest}>
      {children}
    </Tag>
  );
}

window.HeroCanvas = HeroCanvas;
window.ScrollGear = ScrollGear;
window.Reveal = Reveal;

/* Typewriter — types out an array of strings (each = a line) when scrolled into view */
function Typewriter({ lines, speed = 55, startDelay = 200, className = '', renderLine }) {
  const ref = React.useRef(null);
  const [armed, setArmed] = React.useState(false);
  const [out, setOut] = React.useState(() => lines.map(() => ''));
  const [activeLine, setActiveLine] = React.useState(0);
  const [done, setDone] = React.useState(false);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          setTimeout(() => setArmed(true), startDelay);
          io.disconnect();
        }
      });
    }, { threshold: 0.4 });
    io.observe(el);
    return () => io.disconnect();
  }, [startDelay]);

  React.useEffect(() => {
    if (!armed) return;
    let cancelled = false;
    let li = 0, ci = 0;
    function step() {
      if (cancelled) return;
      if (li >= lines.length) { setDone(true); return; }
      const target = lines[li].text ?? lines[li];
      if (ci < target.length) {
        ci++;
        setOut(prev => {
          const next = [...prev];
          next[li] = target.slice(0, ci);
          return next;
        });
        setActiveLine(li);
        setTimeout(step, speed + (Math.random() * 30 - 15));
      } else {
        li++; ci = 0;
        setTimeout(step, 240); // pause between lines
      }
    }
    step();
    return () => { cancelled = true; };
  }, [armed, lines, speed]);

  return (
    <div ref={ref} className={className}>
      {lines.map((l, i) => {
        const isActive = !done && i === activeLine;
        const text = out[i];
        const node = renderLine ? renderLine(text, i, l) : text;
        return (
          <React.Fragment key={i}>
            {node}
            {isActive && <span className="tw-caret" aria-hidden="true"></span>}
            {i < lines.length - 1 && <br />}
          </React.Fragment>
        );
      })}
      {done && <span className="tw-caret tw-caret-end" aria-hidden="true"></span>}
    </div>
  );
}

window.Typewriter = Typewriter;
