/* Hooks compartidos del prototipo. */
(function () {
  const { useEffect, useRef, useState } = React;

  // Revela elementos .reveal al entrar en viewport (IntersectionObserver).
  // Llamar una vez a nivel de página; observa todos los .reveal:not(.in).
  function useRevealAll(deps = []) {
    useEffect(() => {
      const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      const els = Array.from(document.querySelectorAll(".reveal:not(.in)"));
      if (reduce) { els.forEach(e => e.classList.add("in")); return; }
      const io = new IntersectionObserver((entries) => {
        entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } });
      }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
      els.forEach(e => io.observe(e));
      return () => io.disconnect();
    }, deps);
  }

  // Parallax por movimiento de ratón. Devuelve ref al contenedor y posición normalizada (-1..1).
  function useMouseParallax() {
    const ref = useRef(null);
    const [p, setP] = useState({ x: 0, y: 0 });
    useEffect(() => {
      const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      if (reduce) return;
      const el = ref.current; if (!el) return;
      let raf = null;
      const onMove = (e) => {
        const r = el.getBoundingClientRect();
        const x = ((e.clientX - r.left) / r.width - 0.5) * 2;
        const y = ((e.clientY - r.top) / r.height - 0.5) * 2;
        if (raf) cancelAnimationFrame(raf);
        raf = requestAnimationFrame(() => setP({ x, y }));
      };
      const onLeave = () => setP({ x: 0, y: 0 });
      el.addEventListener("mousemove", onMove);
      el.addEventListener("mouseleave", onLeave);
      return () => { el.removeEventListener("mousemove", onMove); el.removeEventListener("mouseleave", onLeave); };
    }, []);
    return [ref, p];
  }

  window.useRevealAll = useRevealAll;
  window.useMouseParallax = useMouseParallax;
})();
