// HpInteractions.jsx — foreground interactive motion. // 1) CursorBlob — soft coral spotlight that follows the mouse (with easing lag) // 2) Magnet — .hp-btn / .hp-magnet subtly pull toward cursor within 100px // 3) Tilt — .hp-tilt cards rotate 8° in 3D, coral highlight sweeps at cursor // // All effects disabled on touch devices and when prefers-reduced-motion is set. const _hpFineHover = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(hover: hover) and (pointer: fine)").matches; const _hpReducedMotion = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches; const _hpInteractive = _hpFineHover && !_hpReducedMotion; // ───────────────────────────────────────────────────────── // CursorBlob — soft coral spotlight + tiny inner dot // ───────────────────────────────────────────────────────── function CursorBlob() { const dotRef = React.useRef(null); const blobRef = React.useRef(null); const target = React.useRef({ x: -200, y: -200 }); const smooth = React.useRef({ x: -200, y: -200 }); const [visible, setVisible] = React.useState(false); React.useEffect(() => { if (!_hpInteractive) return; const onMove = (e) => { target.current.x = e.clientX; target.current.y = e.clientY; if (!visible) setVisible(true); }; const onLeave = () => setVisible(false); window.addEventListener("mousemove", onMove, { passive: true }); document.addEventListener("mouseleave", onLeave); let rafId; const tick = () => { // Ease the blob toward the pointer for the lag effect smooth.current.x += (target.current.x - smooth.current.x) * 0.16; smooth.current.y += (target.current.y - smooth.current.y) * 0.16; if (dotRef.current) { dotRef.current.style.transform = "translate3d(" + target.current.x + "px, " + target.current.y + "px, 0) translate(-50%, -50%)"; } if (blobRef.current) { blobRef.current.style.transform = "translate3d(" + smooth.current.x + "px, " + smooth.current.y + "px, 0) translate(-50%, -50%)"; } rafId = requestAnimationFrame(tick); }; rafId = requestAnimationFrame(tick); return () => { window.removeEventListener("mousemove", onMove); document.removeEventListener("mouseleave", onLeave); cancelAnimationFrame(rafId); }; }, [visible]); if (!_hpInteractive) return null; return ( <>