/** * reveal.js — apparition au scroll via IntersectionObserver. * * Budget de mouvement sobre : fade + translateY(12px), durée --dur-slow. * Sous prefers-reduced-motion: reduce, tout est visible immédiatement. * Progressif : sans JS, le CSS ne masque rien (garde html[data-js]). * * Usage : import { initReveal } from '@transformer/ui/reveal.js'; initReveal(); * (Reveal.astro l'appelle déjà pour ses instances.) */ let observer; export function initReveal(selector = "[data-reveal]") { document.documentElement.dataset.js = ""; const targets = document.querySelectorAll(selector); if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) { targets.forEach((el) => el.classList.add("is-visible")); return; } observer ??= new IntersectionObserver( (entries) => { for (const entry of entries) { if (entry.isIntersecting) { entry.target.classList.add("is-visible"); observer.unobserve(entry.target); } } }, // threshold 0 : un bloc plus haut que le viewport ne peut jamais // atteindre un ratio > viewport/bloc — le rootMargin -10% suffit // à éviter les déclenchements au ras du bord. { threshold: 0, rootMargin: "0px 0px -10% 0px" } ); targets.forEach((el) => { if (!el.classList.contains("is-visible")) observer.observe(el); }); }