'use client'; import { useEffect } from 'react'; const REVEAL_SELECTOR = '[data-reveal]'; export const MotionController = () => { useEffect(() => { const elements = Array.from( document.querySelectorAll(REVEAL_SELECTOR), ); if (!elements.length) return; const reduceMotion = window.matchMedia( '(prefers-reduced-motion: reduce)', ).matches; document.querySelectorAll('[data-reveal-group]').forEach((group) => { group.querySelectorAll(REVEAL_SELECTOR).forEach((element, index) => { element.style.setProperty( '--reveal-delay', `${Math.min(index, 5) * 50}ms`, ); }); }); if (reduceMotion) { elements.forEach((element) => { element.dataset.visible = 'true'; }); document.documentElement.dataset.motionReady = 'true'; return () => { delete document.documentElement.dataset.motionReady; }; } const initialRevealBoundary = window.innerHeight * 0.92; elements.forEach((element) => { const bounds = element.getBoundingClientRect(); if (bounds.top <= initialRevealBoundary && bounds.bottom >= 0) { element.dataset.visible = 'true'; } }); document.documentElement.dataset.motionReady = 'true'; const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; const element = entry.target as HTMLElement; element.dataset.visible = 'true'; observer.unobserve(element); }); }, { rootMargin: '0px 0px -8% 0px', threshold: 0.12, }, ); elements.forEach((element) => { if (element.dataset.visible !== 'true') observer.observe(element); }); return () => { observer.disconnect(); delete document.documentElement.dataset.motionReady; }; }, []); return null; };