'use client'; import { useEffect } from 'react'; import { usePathname } from 'next/navigation'; const targets = '.reference-service-card, .reference-about-intro, .reference-about-values, .reference-faq, .reference-contact > div, .section-heading, .service-row, .service-detail, .about-band-grid, .contact-cta, .about-intro, .values-grid > div, .faq-section, .contact-info > div, .offices-grid > article, .contact-form, .portfolio-grid > article, .portfolio-detail'; export default function PageMotion() { const pathname = usePathname(); useEffect(() => { const main = document.getElementById('main'); if (!main || !('IntersectionObserver' in window)) return; const preference = window.matchMedia('(prefers-reduced-motion: reduce)'); const seen = new WeakSet(); const prepared = new Set(); const observer = new IntersectionObserver(entries => { for (const entry of entries) { if (!entry.isIntersecting) continue; observer.unobserve(entry.target); entry.target.dataset.scrollReveal = 'visible'; } }, { threshold: 0, rootMargin: '0px 0px 48px 0px' }); const prepare = element => { if (seen.has(element)) return; seen.add(element); // Never hide already-visible content, restored scroll positions, or filtered cards. if (preference.matches || element.getBoundingClientRect().top < window.innerHeight) return; element.dataset.scrollReveal = 'pending'; prepared.add(element); observer.observe(element); }; main.querySelectorAll(targets).forEach(prepare); // Inspect added subtrees only; do not rescan the page on every Swiper update. const mutations = new MutationObserver(records => { for (const record of records) { for (const node of record.addedNodes) { if (!(node instanceof Element)) continue; if (node.matches(targets)) prepare(node); node.querySelectorAll(targets).forEach(prepare); } } for (const element of prepared) { if (!element.isConnected) { observer.unobserve(element); prepared.delete(element); } } }); mutations.observe(main, { childList: true, subtree: true }); const revealAll = () => { observer.disconnect(); prepared.forEach(element => element.removeAttribute('data-scroll-reveal')); prepared.clear(); }; const onPreferenceChange = () => { if (preference.matches) revealAll(); }; preference.addEventListener('change', onPreferenceChange); return () => { mutations.disconnect(); revealAll(); preference.removeEventListener('change', onPreferenceChange); }; }, [pathname]); return null; }