// App.jsx — assemble la page d'accueil. La modale de réservation vit dans // BookingModal.jsx (partagée avec les pages de détail des offres). const App = () => { const [bookingOpen, setBookingOpen] = React.useState(false); const [activeSection, setActiveSection] = React.useState('top'); const [showTop, setShowTop] = React.useState(false); const [cookieBannerVisible, setCookieBannerVisible] = React.useState(false); // Surlignage du lien actif (offset = hauteur réelle du nav sticky) + bouton retour-haut (D6) React.useEffect(() => { const ids = ['offres', 'preuves', 'methode', 'studio-digital', 'faq']; const onScroll = () => { const y = window.scrollY + 80; let cur = 'top'; for (const id of ids) { const el = document.getElementById(id); if (el && el.offsetTop <= y) cur = id; } setActiveSection(cur); setShowTop(window.scrollY > 600); }; window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); // Scroll vers la section ciblée par le hash au premier rendu (D6) — nécessaire // car le contenu est monté par React après le chargement de la page : le // saut d'ancre natif du navigateur arrive trop tôt et rate sa cible quand on // clique un lien de nav depuis une page satellite (ex. offres/support.html). React.useEffect(() => { const hash = window.location.hash.slice(1); if (!hash) return; const el = document.getElementById(hash); if (el) { requestAnimationFrame(() => window.scrollTo({ top: el.offsetTop - 80 })); } }, []); // Reveal au scroll (A1/A2) — IntersectionObserver, respecte reduced-motion via CSS React.useEffect(() => { const els = document.querySelectorAll('.b2a-reveal'); if (!('IntersectionObserver' in window)) { els.forEach((el) => el.classList.add('b2a-reveal-in')); return; } const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('b2a-reveal-in'); io.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' }); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); const open = () => setBookingOpen(true); const toTop = () => window.scrollTo({ top: 0, behavior: 'smooth' }); return ( <>