(() => { "use strict"; const root = document.documentElement; const header = document.querySelector("[data-site-header]"); const menuToggle = document.querySelector("[data-menu-toggle]"); const navigation = document.querySelector("[data-navigation]"); const themeToggle = document.querySelector("[data-theme-toggle]"); const themeColor = document.querySelector('meta[name="theme-color"]'); const systemTheme = window.matchMedia("(prefers-color-scheme: dark)"); const getSavedTheme = () => { try { const savedTheme = localStorage.getItem("goodbuddy-site-theme"); return savedTheme === "light" || savedTheme === "dark" ? savedTheme : null; } catch { return null; } }; const applyTheme = (theme, persist = false) => { root.dataset.theme = theme; themeToggle?.setAttribute( "aria-label", theme === "dark" ? "切换为浅色主题" : "切换为深色主题", ); themeColor?.setAttribute("content", theme === "dark" ? "#07101f" : "#f6f8fb"); if (persist) { try { localStorage.setItem("goodbuddy-site-theme", theme); } catch { // The selected theme still applies for the current page. } } }; const closeMenu = () => { header?.classList.remove("is-menu-open"); menuToggle?.setAttribute("aria-expanded", "false"); menuToggle?.setAttribute("aria-label", "打开导航"); }; const setHeaderState = () => { header?.classList.toggle("is-scrolled", window.scrollY > 12); }; applyTheme(getSavedTheme() ?? (systemTheme.matches ? "dark" : "light")); setHeaderState(); themeToggle?.addEventListener("click", () => { applyTheme(root.dataset.theme === "dark" ? "light" : "dark", true); }); systemTheme.addEventListener("change", (event) => { if (!getSavedTheme()) { applyTheme(event.matches ? "dark" : "light"); } }); menuToggle?.addEventListener("click", () => { const willOpen = !header?.classList.contains("is-menu-open"); header?.classList.toggle("is-menu-open", willOpen); menuToggle.setAttribute("aria-expanded", String(willOpen)); menuToggle.setAttribute("aria-label", willOpen ? "关闭导航" : "打开导航"); }); navigation?.addEventListener("click", (event) => { if (event.target instanceof HTMLAnchorElement) { closeMenu(); } }); document.addEventListener("keydown", (event) => { if (event.key === "Escape" && header?.classList.contains("is-menu-open")) { closeMenu(); menuToggle?.focus(); } }); document.addEventListener("click", (event) => { if ( header?.classList.contains("is-menu-open") && event.target instanceof Node && !header.contains(event.target) ) { closeMenu(); } }); window.addEventListener("scroll", setHeaderState, { passive: true }); const sections = [...document.querySelectorAll("main section[id]")]; const navLinks = [...document.querySelectorAll('.site-navigation a[href^="#"]')]; if ("IntersectionObserver" in window) { const observer = new IntersectionObserver( (entries) => { const visibleSection = entries .filter((entry) => entry.isIntersecting) .sort((left, right) => right.intersectionRatio - left.intersectionRatio)[0]; if (!visibleSection) { return; } navLinks.forEach((link) => { const isCurrent = link.getAttribute("href") === `#${visibleSection.target.id}`; if (isCurrent) { link.setAttribute("aria-current", "true"); } else { link.removeAttribute("aria-current"); } }); }, { rootMargin: "-25% 0px -55%", threshold: [0.05, 0.2, 0.5] }, ); sections.forEach((section) => observer.observe(section)); } const currentYear = document.querySelector("[data-current-year]"); if (currentYear) { currentYear.textContent = String(new Date().getFullYear()); } })();