doctype html html.scroll-smooth(lang=head.lang) include src/components/Head body.m-0.p-0.bg-nls-white.text-nls-black(class="dark:bg-nls-black dark:text-white") main.flex.flex-col article(itemscope, itemtype="http://schema.org/Person") include src/components/Landingpage include src/components/Professional include src/components/Portfolio include src/components/Brands include src/components/Academia include src/components/Footer script. const footerEl = document.querySelector("#footer"); const footerObserver = new IntersectionObserver((payload) => { const hasScrolledTo = payload.pop().isIntersecting; if (hasScrolledTo && window.hasOwnProperty("umami")) { umami.track("scrolled to", {position: "footer", id: "footer", visitDuration: getVisitDuration()}); console.debug("scrolled to footer", {visitDuration: getVisitDuration()}); } }); footerObserver.observe(footerEl); const sections = document.querySelectorAll("section"); const sectionObserver = (id) => new IntersectionObserver((payload) => { const hasScrolledTo = payload.pop().isIntersecting; if (hasScrolledTo && window.hasOwnProperty("umami")) { umami.track("scrolled to", {position: "section", id, visitDuration: getVisitDuration()}); console.debug("scrolled to section with id", {id, visitDuation: getVisitDuration()}); } }); sections.forEach((section) => sectionObserver(section.id).observe(section)); // carousel.js - Just the essentials function carouselPrev(carouselId) { const track = document.querySelector(`#${carouselId} .carousel-track`); const slideWidth = track.querySelector(".carousel-slide").offsetWidth; track.scrollBy({left: -slideWidth, behavior: "smooth"}); updateCarouselDots(carouselId); } function carouselNext(carouselId) { const track = document.querySelector(`#${carouselId} .carousel-track`); const slideWidth = track.querySelector(".carousel-slide").offsetWidth; track.scrollBy({left: slideWidth, behavior: "smooth"}); updateCarouselDots(carouselId); } function carouselGoTo(carouselId, index) { const track = document.querySelector(`#${carouselId} .carousel-track`); const slideWidth = track.querySelector(".carousel-slide").offsetWidth; track.scrollTo({left: slideWidth * index, behavior: "smooth"}); updateCarouselDots(carouselId); } function updateCarouselDots(carouselId) { // Debounced dot state update clearTimeout(window.carouselDotTimeout); window.carouselDotTimeout = setTimeout(() => { const track = document.querySelector(`#${carouselId} .carousel-track`); const dots = document.querySelectorAll(`#${carouselId} .carousel-dot`); const slideWidth = track.querySelector(".carousel-slide").offsetWidth; const currentIndex = Math.round(track.scrollLeft / slideWidth); dots.forEach((dot, index) => { if (index === currentIndex) { dot.className = dot.className.replace(/bg-gray-\d+/, "bg-nls-orange"); } else { dot.className = dot.className.replace(/bg-nls-\w+/, "bg-gray-300 dark:bg-gray-600"); } }); }, 100); } // Auto-initialize all carousels document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll(".carousel-track").forEach((track) => { track.addEventListener( "scroll", () => { const carouselId = track.closest(".carousel-container").id; updateCarouselDots(carouselId); }, {passive: true}, ); }); });