/* Brand mark: a halftone speech-bubble built from dots that ripple outward
   like an audio field, with an open ring at center. Lavender/purple palette.
   Reads theme vars for graceful theming; static fallback for reduced motion. */

(function () {
  const { useRef, useEffect } = React;

  function BrandMark({ size = 30 }) {
    const canvasRef = useRef(null);

    useEffect(() => {
      const canvas = canvasRef.current;
      const ctx = canvas.getContext("2d");
      const dpr = Math.min(window.devicePixelRatio || 1, 2.5);
      const W = Math.round(size * dpr);
      canvas.width = W;
      canvas.height = W;
      canvas.style.width = size + "px";
      canvas.style.height = size + "px";

      // ---- geometry (device px) ----
      const cx = W * 0.47;
      const cy = W * 0.45;
      const bodyR = W * 0.40;

      const bubble = new Path2D();
      bubble.arc(cx, cy, bodyR, 0, Math.PI * 2);
      bubble.moveTo(cx - bodyR * 0.52, cy + bodyR * 0.40);
      bubble.lineTo(cx - bodyR * 1.02, cy + bodyR * 1.18);
      bubble.lineTo(cx + bodyR * 0.02, cy + bodyR * 0.80);
      bubble.closePath();

      const spacing = W * 0.097;
      const maxR = spacing * 0.46;
      const ringR = bodyR * 0.40;
      const holeR = ringR + spacing * 0.32;

      // precompute grid points inside the bubble (outside the ring)
      const pts = [];
      for (let y = spacing * 0.5; y < W; y += spacing) {
        for (let x = spacing * 0.5; x < W; x += spacing) {
          if (!ctx.isPointInPath(bubble, x, y)) continue;
          const dc = Math.hypot(x - cx, y - cy);
          if (dc < holeR) continue;
          pts.push({ x, y, dc });
        }
      }

      // lavender / purple palette
      const dotColor = "rgb(150, 128, 224)";   // lavender
      const ringColor = "rgb(124, 100, 214)";  // deeper purple

      const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      let raf = 0;
      const start = performance.now();

      function draw(now) {
        const t = (now - start) / 1000;
        ctx.clearRect(0, 0, W, W);

        // dots
        ctx.fillStyle = dotColor;
        for (let i = 0; i < pts.length; i++) {
          const p = pts[i];
          let edge = 1 - p.dc / bodyR;
          edge = edge < 0 ? 0 : edge > 1 ? 1 : edge;
          const ripple = reduce ? 0.7 : 0.5 + 0.5 * Math.sin(t * 2.6 - (p.dc / W) * 13.0);
          const r = maxR * (0.34 + 0.66 * edge) * (0.5 + 0.5 * ripple);
          if (r <= 0.15) continue;
          ctx.globalAlpha = 0.45 + 0.55 * edge * (0.6 + 0.4 * ripple);
          ctx.beginPath();
          ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
          ctx.fill();
        }

        // open ring — gently breathing
        ctx.globalAlpha = 1;
        const breathe = reduce ? 1 : 0.5 + 0.5 * Math.sin(t * 1.8);
        ctx.strokeStyle = ringColor;
        ctx.lineWidth = Math.max(1, W * 0.032);
        ctx.beginPath();
        ctx.arc(cx, cy, ringR, 0, Math.PI * 2);
        ctx.stroke();
        if (!reduce) {
          ctx.globalAlpha = 0.16 + 0.20 * breathe;
          ctx.lineWidth = Math.max(1, W * 0.05);
          ctx.beginPath();
          ctx.arc(cx, cy, ringR, 0, Math.PI * 2);
          ctx.stroke();
          ctx.globalAlpha = 1;
        }

        if (!reduce) raf = requestAnimationFrame(draw);
      }

      raf = requestAnimationFrame(draw);
      draw(performance.now());
      return () => cancelAnimationFrame(raf);
    }, [size]);

    return <canvas ref={canvasRef} className="brandmark" role="img" aria-label="Audia" />;
  }

  Object.assign(window, { BrandMark });
})();
