/* ABM - APERTURE renderer. A spiral chord-iris: N straight lines, each a chord
   of the outer circle offset by a twist angle, so their envelope forms a dark
   aperture at the centre. 'lighter' blending builds the bright caustic rim; a
   slowly drifting brightness sweep gives the moving crescent. Everything moves
   slowly. Babel script. Exports window.ApertureCanvas. Static first paint. */
const { useRef, useEffect } = React;

function ApertureCanvas({ size = 600, lines = 122, tint = [216, 248, 248], style, className }) {
  const ref = useRef(null);
  useEffect(() => {
    const cv = ref.current; if (!cv) return;
    const ctx = cv.getContext("2d");
    const DPR = Math.min(2, window.devicePixelRatio || 1);
    cv.width = size * DPR; cv.height = size * DPR;
    ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    const cx = size / 2, cy = size / 2;
    const R = size / 2 * 0.97;
    const lw = Math.max(0.7, size / 720);
    const [tr, tg, tb] = tint;

    let raf = null, t0 = null, mounted = true;

    function draw(t) {
      ctx.clearRect(0, 0, size, size);
      // slow breathing twist → aperture opens/closes; slow overall rotation
      const phi = 2.14 + 0.18 * Math.sin(t * 0.055);
      const rot = t * 0.032;
      const sweep = t * 0.10; // drifting bright crescent
      ctx.globalCompositeOperation = "lighter";
      ctx.lineWidth = lw;
      for (let i = 0; i < lines; i++) {
        const a = (i / lines) * Math.PI * 2 + rot;
        const x1 = cx + Math.cos(a) * R;
        const y1 = cy + Math.sin(a) * R;
        const x2 = cx + Math.cos(a + phi) * R;
        const y2 = cy + Math.sin(a + phi) * R;
        // brightness: base rim + drifting crescent emphasis
        const mid = a + phi / 2;
        const crescent = 0.5 + 0.5 * Math.cos(mid - sweep);
        const alpha = 0.10 + 0.32 * crescent * crescent;
        ctx.strokeStyle = "rgba(" + tr + "," + tg + "," + tb + "," + alpha.toFixed(3) + ")";
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
      }
      ctx.globalCompositeOperation = "source-over";
    }
    function loop(t) {
      if (t0 == null) t0 = t;
      draw((t - t0) / 1000);
      if (mounted) raf = requestAnimationFrame(loop);
    }
    draw(0); // static first paint
    raf = requestAnimationFrame(loop);
    return () => { mounted = false; if (raf) cancelAnimationFrame(raf); };
  }, [size, lines]);

  return <canvas ref={ref} className={className} style={{ width: size, height: size, display: "block", ...style }} />;
}

window.ApertureCanvas = ApertureCanvas;
