// BowCursor.jsx — a cute ribbon bow that follows the pointer with a soft trail.
// Replaces the native cursor on fine-pointer devices; grows over clickable things.
(function () {
  // A delicate lace bow — ivory openwork, fine gold-taupe thread, picot edges.
  function Bow({ size = 40, pressed, hot }) {
    const thread = "#b39a78";
    const fill = "#fdf8f1";
    // openwork eyelets + picot dots for one loop (left half, mirrored for right)
    const eyelets = [[12, 13], [8.6, 17], [13, 18.5], [16.5, 14.5], [10, 21.5]];
    const picots = [[16, 6.4], [10.5, 7.8], [6, 10.4], [3.9, 14.6], [4.4, 19.4], [7, 23.6], [12, 26.6], [18, 27]];
    const Loop = () => (
      <g>
        <path d="M24 18 C 16 5.5, 4 8, 3.4 16 C 3 24, 15 29.5, 24 18 Z"
          fill={fill} fillOpacity="0.5" stroke={thread} strokeWidth="0.9" />
        <path d="M20.5 9 C 13 9.5, 7.5 13, 6.6 19" fill="none" stroke={thread} strokeWidth="0.7" opacity="0.7" />
        <path d="M21.5 12.5 C 15.5 12.5, 11 15, 10 20.5" fill="none" stroke={thread} strokeWidth="0.6" opacity="0.55" />
        {eyelets.map(([x, y], i) => (
          <circle key={"e" + i} cx={x} cy={y} r="1.05" fill="none" stroke={thread} strokeWidth="0.7" />
        ))}
        {picots.map(([x, y], i) => (
          <circle key={"p" + i} cx={x} cy={y} r="0.85" fill={fill} stroke={thread} strokeWidth="0.55" />
        ))}
      </g>
    );
    const Tail = () => (
      <g>
        <path d="M23.4 22.5 C 21 27, 18.5 30, 15.2 33 C 17.6 33, 19.6 32, 21.4 30.5 C 22.6 27.6, 23.6 25, 24 22.8 Z"
          fill={fill} fillOpacity="0.5" stroke={thread} strokeWidth="0.85" />
        <circle cx="20.6" cy="27" r="0.95" fill="none" stroke={thread} strokeWidth="0.65" />
        <circle cx="18.4" cy="30.4" r="0.85" fill="none" stroke={thread} strokeWidth="0.6" />
        {[15.2, 17.5, 19.6].map((x, i) => (
          <circle key={i} cx={x} cy={33 - (x - 15.2) * 0.7} r="0.7" fill={fill} stroke={thread} strokeWidth="0.5" />
        ))}
      </g>
    );
    return (
      <svg width={size} height={size * 0.82} viewBox="0 0 48 36" fill="none"
        style={{ display: "block", filter: "drop-shadow(0 1px 1.5px rgba(120,90,60,0.3))" }}>
        <Tail />
        <g transform="translate(48,0) scale(-1,1)"><Tail /></g>
        <Loop />
        <g transform="translate(48,0) scale(-1,1)"><Loop /></g>
        {/* center knot */}
        <path d="M21 12.5 C 19.8 14, 19.8 22, 21 23.5 C 23.5 22.8, 24.5 22.8, 27 23.5 C 28.2 22, 28.2 14, 27 12.5 C 24.5 13.2, 23.5 13.2, 21 12.5 Z"
          fill={fill} fillOpacity="0.62" stroke={thread} strokeWidth="0.9" />
        <path d="M22.5 13.4 L 22.5 22.6 M24 13.4 L 24 22.8 M25.5 13.4 L 25.5 22.6"
          stroke={thread} strokeWidth="0.55" opacity="0.7" />
      </svg>
    );
  }

  function BowCursor() {
    const ref = React.useRef(null);
    const [enabled, setEnabled] = React.useState(false);
    const [pressed, setPressed] = React.useState(false);
    const [hot, setHot] = React.useState(false);
    const state = React.useRef({ tx: -100, ty: -100, x: -100, y: -100, rot: 0, px: -100 });

    React.useEffect(() => {
      if (!window.matchMedia || !window.matchMedia("(pointer: fine)").matches) return;
      setEnabled(true);
      const style = document.createElement("style");
      style.textContent = `* { cursor: none !important; }`;
      document.head.appendChild(style);

      function onMove(e) {
        const s = state.current;
        s.tx = e.clientX; s.ty = e.clientY;
        const el = e.target;
        const interactive = el && (el.closest && el.closest('a,button,figure,input,[role="button"]'));
        setHot(!!interactive);
      }
      function onDown() { setPressed(true); }
      function onUp() { setPressed(false); }
      window.addEventListener("mousemove", onMove, { passive: true });
      window.addEventListener("mousedown", onDown);
      window.addEventListener("mouseup", onUp);

      let raf;
      function tick() {
        const s = state.current;
        s.px = s.x;
        s.x += (s.tx - s.x) * 0.22;
        s.y += (s.ty - s.y) * 0.22;
        const vel = s.x - s.px;
        s.rot += ((Math.max(-22, Math.min(22, vel * 1.4)) - s.rot)) * 0.18;
        if (ref.current) {
          ref.current.style.transform =
            `translate(${s.x}px, ${s.y}px) translate(-50%, -52%) rotate(${s.rot}deg)`;
        }
        raf = requestAnimationFrame(tick);
      }
      raf = requestAnimationFrame(tick);

      return () => {
        cancelAnimationFrame(raf);
        window.removeEventListener("mousemove", onMove);
        window.removeEventListener("mousedown", onDown);
        window.removeEventListener("mouseup", onUp);
        style.remove();
      };
    }, []);

    if (!enabled) return null;
    return (
      <div ref={ref} aria-hidden="true"
        style={{
          position: "fixed", top: 0, left: 0, zIndex: 9999,
          pointerEvents: "none", willChange: "transform",
        }}>
        <div style={{
          transform: `scale(${pressed ? 0.82 : hot ? 1.28 : 1})`,
          transition: "transform 0.16s cubic-bezier(0.4,0,0.2,1)",
          transformOrigin: "center",
        }}>
          <Bow />
        </div>
      </div>
    );
  }

  window.BowCursor = BowCursor;
})();
