import type { Action } from 'svelte/action'; import { syncopatedDelay } from './tokens'; // use:reveal={index} — révèle l'élément à l'entrée dans le viewport avec cascade gwoka. // L'état caché est posé en CSS uniquement sous html.has-js + prefers-reduced-motion: no-preference, // donc le contenu reste lisible sans JS et sans animation. export const reveal: Action = (node, index = 0) => { const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduce) { node.classList.add('is-visible'); return; } node.style.setProperty('--d', `${syncopatedDelay(index)}ms`); const io = new IntersectionObserver( (entries) => { for (const e of entries) { if (e.isIntersecting) { node.classList.add('is-visible'); io.unobserve(node); } } }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' } ); io.observe(node); return { destroy() { io.disconnect(); } }; };