/* HeroFX — hero-only atmosphere.
   • HeroConstellation: the node-network ("constellation") + traveling signal
     comet, scoped to the hero canvas only (NOT the rest of the site).
   • HeroSkyline: a cinematic night-city silhouette with lit windows, parallax
     and a couple of blinking rooftop beacons — the "silhouette" layer the
     call-signals ripple over. Pauses its rAF when the hero scrolls away. */

const HeroConstellation = () => {
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    let W = 0, H = 0;
    const resize = () => {
      const r = canvas.getBoundingClientRect();
      W = r.width || window.innerWidth;
      H = r.height || window.innerHeight;
      canvas.width = W * dpr; canvas.height = H * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener('resize', resize);

    const N = window.innerWidth < 760 ? 30 : 56;
    const nodes = Array.from({ length: N }, () => ({
      x: Math.random(), y: Math.random(),
      vx: (Math.random() - 0.5) * 0.00022,
      vy: (Math.random() - 0.5) * 0.00022,
      r: Math.random() * 1.6 + 0.5,
      ph: Math.random() * Math.PI * 2,
    }));
    const trail = [];

    // pause when the hero is off-screen
    let visible = true;
    const io = new IntersectionObserver((e) => { visible = e[0].isIntersecting; }, { threshold: 0 });
    io.observe(canvas);

    let raf, t0 = performance.now();
    const draw = (now) => {
      const dt = Math.min(40, now - t0); t0 = now;
      const t = now * 0.001;
      if (!visible) { raf = requestAnimationFrame(draw); return; }
      ctx.clearRect(0, 0, W, H);

      const pts = nodes.map(n => {
        if (!reduced) { n.x += n.vx * dt; n.y += n.vy * dt; }
        if (n.x < -0.05) n.x = 1.05; if (n.x > 1.05) n.x = -0.05;
        if (n.y < -0.05) n.y = 1.05; if (n.y > 1.05) n.y = -0.05;
        return { sx: n.x * W, sy: n.y * H, n };
      });

      const maxD = W < 760 ? 120 : 168;
      for (let i = 0; i < pts.length; i++) {
        for (let j = i + 1; j < pts.length; j++) {
          const dx = pts[i].sx - pts[j].sx, dy = pts[i].sy - pts[j].sy;
          const d = Math.hypot(dx, dy);
          if (d < maxD) {
            const a = (1 - d / maxD) * 0.16;
            ctx.beginPath();
            ctx.moveTo(pts[i].sx, pts[i].sy); ctx.lineTo(pts[j].sx, pts[j].sy);
            ctx.strokeStyle = `rgba(255,137,97,${a.toFixed(3)})`;
            ctx.lineWidth = 0.6; ctx.stroke();
          }
        }
      }
      for (const p of pts) {
        const tw = reduced ? 0.6 : 0.5 + Math.sin(t * 1.6 + p.n.ph) * 0.4;
        ctx.beginPath();
        ctx.arc(p.sx, p.sy, p.n.r, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(255,185,155,${(0.2 + tw * 0.28).toFixed(3)})`;
        ctx.fill();
      }

      if (!reduced) {
        const phase = (t * 0.07) % 1;
        const cx = phase * (W + 200) - 100;
        const cy = H * 0.34 + Math.sin(phase * Math.PI * 4) * (H * 0.18);
        trail.push({ x: cx, y: cy, life: 1 });
        if (trail.length > 42) trail.shift();
        for (let i = 0; i < trail.length; i++) {
          const tr = trail[i]; tr.life -= 0.024;
          const a = Math.max(0, tr.life) * 0.6;
          ctx.beginPath();
          ctx.arc(tr.x, tr.y, 1 + (i / trail.length) * 2.2, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(255,87,54,${a.toFixed(3)})`; ctx.fill();
        }
        const hg = ctx.createRadialGradient(cx, cy, 0, cx, cy, 16);
        hg.addColorStop(0, 'rgba(255,210,180,0.85)');
        hg.addColorStop(0.4, 'rgba(255,87,54,0.55)');
        hg.addColorStop(1, 'rgba(255,87,54,0)');
        ctx.fillStyle = hg; ctx.fillRect(cx - 16, cy - 16, 32, 32);
      }

      raf = requestAnimationFrame(draw);
    };
    raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); io.disconnect(); window.removeEventListener('resize', resize); };
  }, []);

  return <canvas ref={canvasRef} aria-hidden="true" className="absolute inset-0 w-full h-full pointer-events-none z-[1]" />;
};

/* ── Night-city skyline silhouette (procedural rectangles) ── */
const HeroSkyline = ({ progress = 0 }) => {
  // build a deterministic skyline so it doesn't reshuffle each render
  const { buildings, vbW, vbH } = React.useMemo(() => {
    const vbW = 1440, vbH = 360;
    const buildings = [];
    let x = -20;
    let seed = 7;
    const rnd = () => { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; };
    while (x < vbW + 20) {
      const w = 34 + Math.floor(rnd() * 62);
      const h = 70 + Math.floor(rnd() * 220);
      const wins = [];
      const cols = Math.max(2, Math.floor(w / 16));
      const rows = Math.max(3, Math.floor(h / 22));
      for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
          if (rnd() > 0.62) {
            wins.push({
              wx: 6 + c * ((w - 12) / cols),
              wy: 10 + r * ((h - 14) / rows),
              lit: rnd() > 0.55,
            });
          }
        }
      }
      const beacon = h > 230 && rnd() > 0.4;
      buildings.push({ x, w, h, wins, beacon });
      x += w + 4 + Math.floor(rnd() * 10);
    }
    return { buildings, vbW, vbH };
  }, []);

  return (
    <div
      aria-hidden="true"
      className="absolute left-0 right-0 bottom-0 z-[2] pointer-events-none"
      style={{ height: '54%', transform: `translateY(${progress * 26}px)` }}
    >
      {/* horizon backlight — makes the towers read as dark silhouettes */}
      <div className="absolute inset-x-0 bottom-[34%] h-[42%]" style={{
        background: 'radial-gradient(120% 130% at 50% 100%, rgba(255,120,70,0.28), rgba(255,87,54,0.08) 42%, transparent 70%)',
      }} />
      {/* warm ground glow rising behind the skyline */}
      <div className="absolute inset-x-0 bottom-0 h-2/3" style={{
        background: 'radial-gradient(80% 120% at 50% 100%, rgba(255,87,54,0.16), transparent 70%)',
      }} />
      <svg className="absolute bottom-0 left-0 w-full h-full" viewBox={`0 0 ${vbW} ${vbH}`} preserveAspectRatio="xMidYMax slice">
        <g>
          {buildings.map((b, i) => (
            <g key={i} transform={`translate(${b.x}, ${vbH - b.h})`}>
              <rect x="0" y="0" width={b.w} height={b.h} fill="#060607" />
              {/* warm rim on the rooftop + a cool left edge for separation */}
              <rect x="0" y="0" width={b.w} height="1.4" fill="rgba(255,120,80,0.5)" />
              <rect x="0" y="0" width="1" height={b.h} fill="rgba(255,255,255,0.05)" />
              {b.wins.map((win, wi) => (
                <rect key={wi} x={win.wx} y={win.wy} width="3.4" height="5"
                  fill={win.lit ? 'rgba(255,150,90,0.85)' : 'rgba(255,255,255,0.06)'} />
              ))}
              {b.beacon && <circle cx={b.w / 2} cy="-6" r="2.4" className="beacon" fill="#FF5736" />}
            </g>
          ))}
        </g>
      </svg>
      {/* base fade into page */}
      <div className="absolute inset-x-0 bottom-0 h-12 bg-gradient-to-b from-transparent to-ink" />
    </div>
  );
};

window.HeroConstellation = HeroConstellation;
window.HeroSkyline = HeroSkyline;
