document.addEventListener('DOMContentLoaded', () => { console.log('DOM fully loaded and parsed'); const FPS = 60; // Target frames per second for cursor tracking // -------- Video fixed BG ------------------------------ const reelEl = document.getElementById('reel'); if (!reelEl) return; const video = reelEl.tagName.toLowerCase() === 'video' ? reelEl : reelEl.querySelector('video'); if (!video) return; function tryPlay() { const playPromise = video.play(); if (playPromise !== undefined) { playPromise.catch(() => { // Autoplay bloqué : passer en muet et retenter video.muted = true; video.play().catch(() => { }); }); } } function handleVisibility(visible) { console.log('Visibility changed, playing:', visible); if (visible) { // make visible the video element video.style.visibility = 'visible'; tryPlay(); } else { video.style.visibility = 'hidden'; video.pause(); } } if ('IntersectionObserver' in window) { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { handleVisibility(entry.intersectionRatio >= 0.01); }); }, {threshold: [0, 0.01, 1]}); observer.observe(reelEl); } else { // Fallback simple : vérification sur scroll/resize let ticking = false; const check = () => { ticking = false; const rect = reelEl.getBoundingClientRect(); const vh = window.innerHeight || document.documentElement.clientHeight; // Visible si une partie quelconque est dans la fenêtre const visible = rect.bottom > 0 && rect.top < vh; handleVisibility(visible); }; const onScroll = () => { if (!ticking) { ticking = true; requestAnimationFrame(check); } }; onScroll(); window.addEventListener('scroll', onScroll, {passive: true}); window.addEventListener('resize', onScroll); } document.addEventListener('visibilitychange', () => { if (document.hidden) video.pause(); }); // Cursor tracking //track the cursor position and set CSS variables --cursor-x and --cursor-y on the body element let x = 0; let y = 0; document.addEventListener('mousemove', (e) => { x = Math.round(((e.clientX / window.innerWidth) * 2 - 1) * 10000) / 10000; y = Math.round(((e.clientY / window.innerHeight) * 2 - 1) * 10000) / 10000; }); let lastUpdate = 0; const FRAME_INTERVAL = 1000 / FPS; const updateTwist = (timestamp) => { if (!timestamp) timestamp = performance.now(); if (timestamp - lastUpdate >= FRAME_INTERVAL) { document.body.style.setProperty('--cursor-x', x); document.body.style.setProperty('--cursor-y', y); lastUpdate = timestamp; } requestAnimationFrame(updateTwist); } updateTwist(); // --------- Init Lenis smooth scroll ------------------------ // Initialize Lenis const lenis = new Lenis({ autoRaf: true, }); // Gallery interactions // On click on .photo element, toggle the 'full' class document.querySelectorAll('.photo').forEach(photoEl => { photoEl.addEventListener('click', () => { console.log('Photo clicked'); // get next photo-full element inside the parent div let fullPhoto = photoEl.parentElement.querySelector('.photo-full'); if (!fullPhoto) return; fullPhoto.style.display = 'block'; fullPhoto.addEventListener('click', () => { fullPhoto.style.display = 'none'; }) }); }); // Accordion functionality // Comportement "accordion" : quand un details s'ouvre, fermer les autres (function(){ const faqContainer = document.getElementById('faq'); if (!faqContainer) return; const items = faqContainer.querySelectorAll('details'); items.forEach(item => { // Mise à jour de l'attribut aria-expanded pour accessibilité item.addEventListener('toggle', () => { item.querySelector('summary')?.setAttribute('aria-expanded', item.open ? 'true' : 'false'); if (item.open) { items.forEach(other => { if (other !== item) other.removeAttribute('open'); }); } }); // Permet Enter / Espace pour déclencher l'ouverture quand summary a le focus const summary = item.querySelector('summary'); summary.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); summary.click(); } }); }); })(); // Link prefetching on hover (function(){ const prefetchLinks = new Set(); document.querySelectorAll('a[href]').forEach(link => { link.addEventListener('mouseenter', () => { const url = link.href; if (!prefetchLinks.has(url)) { const linkEl = document.createElement('link'); linkEl.rel = 'prefetch'; linkEl.href = url; document.head.appendChild(linkEl); prefetchLinks.add(url); } }); }); })(); // Navbar mobile // Get all "navbar-burger" elements const $navbarBurgers = document.querySelector('.navbar-burger'); console.log('$navbarBurgers:', $navbarBurgers); // Add a click event on each of them let el = $navbarBurgers; el.addEventListener('click', () => { console.log('Navbar burger clicked'); // Get the target from the "data-target" attribute const target = el.dataset.target; const $target = document.getElementById(target); // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu" el.classList.toggle('is-active'); $target.classList.toggle('is-active'); }); }, { once: true });