// folio/App.jsx function useFolioCursor() { React.useEffect(() => { const fine = window.matchMedia("(pointer: fine)").matches; if (!fine) return; const el = document.createElement("div"); el.className = "folio-cursor"; document.body.appendChild(el); let raf, tx = 0, ty = 0, x = 0, y = 0; const tick = () => { tx += (x - tx) * 0.22; ty += (y - ty) * 0.22; el.style.transform = `translate(${tx}px, ${ty}px) translate(-50%, -50%)`; raf = requestAnimationFrame(tick); }; const onMove = (e) => { x = e.clientX; y = e.clientY; el.classList.add("show"); const tile = e.target.closest && e.target.closest(".folio-tile"); el.classList.toggle("hover-tile", !!tile); }; const onLeave = () => el.classList.remove("show"); window.addEventListener("mousemove", onMove); window.addEventListener("mouseleave", onLeave); raf = requestAnimationFrame(tick); return () => { cancelAnimationFrame(raf); window.removeEventListener("mousemove", onMove); window.removeEventListener("mouseleave", onLeave); el.remove(); }; }, []); } function FolioApp() { const [lbIndex, setLbIndex] = React.useState(null); const [showAll, setShowAll] = React.useState(false); useFolioCursor(); const open = (i) => setLbIndex(i); const close = () => setLbIndex(null); return ( <>