const navLinks = [...document.querySelectorAll(".nav-links a")]; const nav = document.querySelector(".nav"); const navToggle = document.querySelector(".nav-toggle"); const mobileCards = [...document.querySelectorAll(".mobile-collapsible")]; const imageLinks = [...document.querySelectorAll(".image-link")]; const lightbox = document.getElementById("image-lightbox"); const lightboxImage = document.getElementById("lightbox-image"); const lightboxCaption = document.getElementById("lightbox-caption"); const lightboxCloseButtons = [...document.querySelectorAll("[data-lightbox-close]")]; const sections = navLinks .map((link) => document.querySelector(link.getAttribute("href"))) .filter(Boolean); const observer = new IntersectionObserver( (entries) => { const visible = entries .filter((entry) => entry.isIntersecting) .sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0]; if (!visible) { return; } navLinks.forEach((link) => { const isCurrent = link.getAttribute("href") === `#${visible.target.id}`; if (isCurrent) { link.setAttribute("aria-current", "true"); } else { link.removeAttribute("aria-current"); } }); }, { rootMargin: "-25% 0px -55% 0px", threshold: [0.2, 0.45, 0.7] } ); sections.forEach((section) => observer.observe(section)); const mobileMedia = window.matchMedia("(max-width: 720px)"); const applyMobileCardState = () => { mobileCards.forEach((card) => { const toggle = card.querySelector(".card-toggle"); const collapsed = mobileMedia.matches && card.dataset.collapsedMobile === "true"; if (!toggle) { return; } card.dataset.collapsed = collapsed ? "true" : "false"; toggle.setAttribute("aria-expanded", collapsed ? "false" : "true"); }); }; if (nav && navToggle) { navToggle.addEventListener("click", () => { const expanded = navToggle.getAttribute("aria-expanded") === "true"; navToggle.setAttribute("aria-expanded", String(!expanded)); nav.dataset.open = expanded ? "false" : "true"; }); navLinks.forEach((link) => { link.addEventListener("click", () => { if (window.matchMedia("(max-width: 720px)").matches) { nav.dataset.open = "false"; navToggle.setAttribute("aria-expanded", "false"); } }); }); } mobileCards.forEach((card) => { const toggle = card.querySelector(".card-toggle"); if (!toggle) { return; } toggle.addEventListener("click", () => { if (!mobileMedia.matches) { return; } const collapsed = card.dataset.collapsed !== "true"; card.dataset.collapsed = collapsed ? "true" : "false"; toggle.setAttribute("aria-expanded", collapsed ? "false" : "true"); }); }); applyMobileCardState(); mobileMedia.addEventListener("change", applyMobileCardState); document.querySelectorAll("[data-copy-target]").forEach((button) => { button.addEventListener("click", async () => { const target = document.getElementById(button.dataset.copyTarget); if (!target) { return; } try { await navigator.clipboard.writeText(target.textContent); const original = button.textContent; button.textContent = "Copied"; window.setTimeout(() => { button.textContent = original; }, 1400); } catch { button.textContent = "Copy Failed"; window.setTimeout(() => { button.textContent = "Copy"; }, 1400); } }); }); if (lightbox && lightboxImage && lightboxCaption && imageLinks.length) { let activeImageLink = null; const closeLightbox = () => { lightbox.hidden = true; lightbox.setAttribute("aria-hidden", "true"); document.body.classList.remove("lightbox-open"); lightboxImage.removeAttribute("src"); lightboxImage.alt = ""; lightboxCaption.textContent = ""; if (activeImageLink) { activeImageLink.focus(); activeImageLink = null; } }; const openLightbox = (link) => { const preview = link.querySelector("img"); if (!preview) { return; } activeImageLink = link; lightboxImage.src = link.getAttribute("href") || preview.currentSrc || preview.src; lightboxImage.alt = preview.alt || ""; lightboxCaption.textContent = preview.closest("figure")?.querySelector("figcaption")?.textContent?.trim() || preview.alt || ""; lightbox.hidden = false; lightbox.setAttribute("aria-hidden", "false"); document.body.classList.add("lightbox-open"); }; imageLinks.forEach((link) => { link.addEventListener("click", (event) => { event.preventDefault(); openLightbox(link); }); }); lightboxCloseButtons.forEach((button) => { button.addEventListener("click", closeLightbox); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape" && !lightbox.hidden) { closeLightbox(); } }); }