/** * Home hero carousel — autoplay + dot navigation + mobile swipe */ (function () { var AUTOPLAY_MS = 5000; var SWIPE_THRESHOLD = 48; var MOBILE_MQ = '(max-width: 991.98px)'; function initHomeHeroCarousel(root) { if (root.getAttribute('data-carousel-ready') === 'true') return; root.setAttribute('data-carousel-ready', 'true'); var slides = root.querySelectorAll('[data-home-hero-slide]'); var dots = root.querySelectorAll('[data-home-hero-dot]'); var viewport = root.querySelector('.home-hero-carousel__viewport'); if (!slides.length) return; var index = 0; var timer = null; var touchStartX = 0; var touchStartY = 0; var touchTracking = false; function setSlide(nextIndex) { index = (nextIndex + slides.length) % slides.length; slides.forEach(function (slide, i) { var active = i === index; slide.classList.toggle('is-active', active); slide.setAttribute('aria-hidden', active ? 'false' : 'true'); }); dots.forEach(function (dot, i) { var active = i === index; dot.classList.toggle('is-active', active); dot.setAttribute('aria-selected', active ? 'true' : 'false'); }); } function startAutoplay() { stopAutoplay(); timer = window.setInterval(function () { setSlide(index + 1); }, AUTOPLAY_MS); } function stopAutoplay() { if (timer) { window.clearInterval(timer); timer = null; } } function isMobileSwipeEnabled() { return window.matchMedia(MOBILE_MQ).matches; } function bindTouchSwipe() { if (!viewport || viewport.getAttribute('data-swipe-ready') === 'true') return; viewport.setAttribute('data-swipe-ready', 'true'); viewport.addEventListener( 'touchstart', function (e) { if (!isMobileSwipeEnabled() || !e.touches.length) return; touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; touchTracking = true; stopAutoplay(); }, { passive: true } ); viewport.addEventListener( 'touchend', function (e) { if (!touchTracking) return; touchTracking = false; if (!isMobileSwipeEnabled()) { startAutoplay(); return; } var touch = e.changedTouches[0]; if (!touch) { startAutoplay(); return; } var dx = touch.clientX - touchStartX; var dy = touch.clientY - touchStartY; if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dx) <= Math.abs(dy)) { startAutoplay(); return; } if (dx < 0) { setSlide(index + 1); } else { setSlide(index - 1); } startAutoplay(); }, { passive: true } ); viewport.addEventListener( 'touchcancel', function () { touchTracking = false; startAutoplay(); }, { passive: true } ); } dots.forEach(function (dot) { dot.addEventListener('click', function () { var target = Number(dot.getAttribute('data-home-hero-dot')); if (Number.isNaN(target)) return; setSlide(target); startAutoplay(); }); }); root.addEventListener('mouseenter', stopAutoplay); root.addEventListener('mouseleave', startAutoplay); root.addEventListener('focusin', stopAutoplay); root.addEventListener('focusout', function (e) { if (!root.contains(e.relatedTarget)) startAutoplay(); }); bindTouchSwipe(); setSlide(0); startAutoplay(); } function boot() { document.querySelectorAll('[data-home-hero-carousel]').forEach(initHomeHeroCarousel); } window.AifoHomeHeroCarouselInit = initHomeHeroCarousel; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot); } else { boot(); } document.addEventListener('aifo:home-hero-carousel-reload', boot); })();