// interlude-visual.jsx — second generative 3D visual: a perspective wave
// field of points (evokes streaming data). Different form from the hero
// sphere. Follows --accent and pauses when data-motion=off. (-> window)
const { useRef: ivUseRef, useEffect: ivUseEffect } = React;

function InterludeVisual() {
  const canvasRef = ivUseRef(null);
  const wrapRef = ivUseRef(null);

  ivUseEffect(() => {
    const canvas = canvasRef.current;
    const wrap = wrapRef.current;
    if (!canvas || !wrap) return;
    const ctx = canvas.getContext("2d");
    let raf, W, H, dpr, frame = 0;

    // accent resolution (oklch -> rgba via probe)
    let accent = "#5b8def";
    const readAccent = () => {
      const v = getComputedStyle(document.documentElement).getPropertyValue("--accent").trim();
      if (v) accent = v;
    };
    readAccent();
    const probe = document.createElement("span");
    document.body.appendChild(probe);
    const rgba = (a) => {
      probe.style.color = accent;
      const m = getComputedStyle(probe).color.match(/\d+(\.\d+)?/g);
      return m ? `rgba(${m[0]},${m[1]},${m[2]},${a})` : `rgba(120,160,240,${a})`;
    };

    const COLS = 46, ROWS = 22;

    const resize = () => {
      dpr = Math.min(2, window.devicePixelRatio || 1);
      const rect = wrap.getBoundingClientRect();
      W = rect.width; H = rect.height;
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + "px"; canvas.style.height = H + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(wrap);

    let t = 0;
    // perspective projection of a tilted plane point (gx,gy in -1..1, z height)
    const tilt = 1.02; // radians, looking across the plane
    const cosT = Math.cos(tilt), sinT = Math.sin(tilt);

    const draw = () => {
      const motionOff = document.documentElement.getAttribute("data-motion") === "off";
      if (frame % 40 === 0) readAccent();
      frame++;
      if (!motionOff) t += 0.018;

      ctx.clearRect(0, 0, W, H);
      const cx = W / 2;
      const spanX = W * 0.62;
      const baseY = H * 0.34;
      const depthScale = H * 0.92;

      const project = (i, j) => {
        const gx = (i / (COLS - 1) - 0.5) * 2;     // -1..1
        const gy = (j / (ROWS - 1));                // 0..1 (near->far)
        const wave = Math.sin(gx * 3 + t) * 0.5 + Math.cos(gy * 5 - t * 1.2) * 0.5;
        const z = wave * 0.16;
        // tilt plane: far rows rise & compress
        const yPlane = gy;
        const yy = yPlane * cosT - z * sinT;
        const persp = 1 / (1 + yy * 1.05);
        const sx = cx + gx * spanX * persp;
        const sy = baseY + yy * depthScale * persp;
        return { x: sx, y: sy, p: persp, z };
      };

      // draw horizontal-ish links along columns (depth lines) + points
      for (let i = 0; i < COLS; i++) {
        let prev = null;
        for (let j = 0; j < ROWS; j++) {
          const pt = project(i, j);
          const depthA = Math.max(0, (1 - j / ROWS));
          if (prev) {
            ctx.strokeStyle = rgba(0.07 + depthA * 0.20);
            ctx.lineWidth = 1;
            ctx.beginPath(); ctx.moveTo(prev.x, prev.y); ctx.lineTo(pt.x, pt.y); ctx.stroke();
          }
          prev = pt;
        }
      }
      // points
      for (let j = 0; j < ROWS; j++) {
        const depthA = Math.max(0.06, 1 - j / ROWS);
        for (let i = 0; i < COLS; i++) {
          const pt = project(i, j);
          const r = (0.7 + pt.z * 6) * pt.p;
          if (r <= 0.2) continue;
          ctx.fillStyle = rgba(Math.min(0.85, 0.2 + depthA * 0.6 + pt.z * 1.4));
          ctx.beginPath(); ctx.arc(pt.x, pt.y, Math.max(0.4, r), 0, Math.PI * 2); ctx.fill();
        }
      }
      raf = requestAnimationFrame(draw);
    };
    draw();

    return () => {
      cancelAnimationFrame(raf);
      ro.disconnect();
      probe.remove();
    };
  }, []);

  return (
    <div className="interlude__viz" ref={wrapRef} aria-hidden="true">
      <canvas ref={canvasRef}></canvas>
    </div>
  );
}

Object.assign(window, { InterludeVisual });
