(function initPartyBuildingPage(global) { function initPartyBuildingReveal() { const revealNodes = Array.from(document.querySelectorAll("[data-party-reveal]")); if (!revealNodes.length) return; const prefersReducedMotion = global.matchMedia && global.matchMedia("(prefers-reduced-motion: reduce)").matches; revealNodes.forEach((node) => { const delay = Number(node.dataset.partyRevealDelay); if (Number.isFinite(delay) && delay >= 0) { node.style.setProperty("--party-reveal-delay", `${delay}ms`); } }); if (prefersReducedMotion || !("IntersectionObserver" in global)) { revealNodes.forEach((node) => node.classList.add("is-visible")); return; } const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) { return; } entry.target.classList.add("is-visible"); observer.unobserve(entry.target); }); }, { rootMargin: "0px 0px -10% 0px", threshold: 0.2, }); global.requestAnimationFrame(() => { global.requestAnimationFrame(() => { revealNodes.forEach((node) => observer.observe(node)); }); }); } function initPartyBuildingFeatureCarousel() { const carouselEl = document.querySelector("[data-party-feature-carousel]"); if (!carouselEl) return; const slides = Array.from(carouselEl.querySelectorAll("[data-party-feature-slide]")); const dotsEl = carouselEl.querySelector("[data-party-feature-dots]"); if (!slides.length) return; const reducedMotionQuery = typeof global.matchMedia === "function" ? global.matchMedia("(prefers-reduced-motion: reduce)") : null; const autoplayDelay = 4800; let activeIndex = slides.findIndex((slide) => slide.classList.contains("is-active")); let autoplayTimer = 0; let dotButtons = []; let touchStartX = 0; let touchDeltaX = 0; if (activeIndex < 0) { activeIndex = 0; } slides.forEach((slide, index) => { if (!slide.id) { slide.id = `party-feature-slide-${index + 1}`; } slide.setAttribute("aria-label", `${index + 1} / ${slides.length}`); }); const stopAutoplay = () => { if (!autoplayTimer) return; global.clearTimeout(autoplayTimer); autoplayTimer = 0; }; const scheduleAutoplay = () => { stopAutoplay(); if (slides.length <= 1 || (reducedMotionQuery && reducedMotionQuery.matches)) { return; } autoplayTimer = global.setTimeout(() => { goToSlide(activeIndex + 1, { restartAutoplay: false }); scheduleAutoplay(); }, autoplayDelay); }; const syncActiveSlide = () => { slides.forEach((slide, index) => { const isActive = index === activeIndex; slide.classList.toggle("is-active", isActive); slide.setAttribute("aria-hidden", String(!isActive)); }); dotButtons.forEach((dotBtn, index) => { const isActive = index === activeIndex; dotBtn.classList.toggle("is-active", isActive); dotBtn.setAttribute("aria-current", isActive ? "true" : "false"); }); }; const goToSlide = (nextIndex, options = {}) => { if (!slides.length) return; const normalizedIndex = (nextIndex + slides.length) % slides.length; activeIndex = normalizedIndex; syncActiveSlide(); if (options.restartAutoplay !== false) { scheduleAutoplay(); } }; if (dotsEl) { slides.forEach((slide, index) => { const dotBtn = document.createElement("button"); dotBtn.type = "button"; dotBtn.className = "party-building-feature-dot"; dotBtn.setAttribute("aria-label", `\u5207\u6362\u5230\u7b2c${index + 1}\u5f20\u4e13\u9898\u56fe\u7247`); dotBtn.setAttribute("aria-controls", slide.id); dotBtn.addEventListener("click", () => { goToSlide(index); }); dotsEl.appendChild(dotBtn); dotButtons.push(dotBtn); }); } if (dotsEl) { dotsEl.hidden = slides.length <= 1; } carouselEl.addEventListener("keydown", (event) => { if (event.key === "ArrowLeft") { event.preventDefault(); goToSlide(activeIndex - 1); } if (event.key === "ArrowRight") { event.preventDefault(); goToSlide(activeIndex + 1); } }); carouselEl.addEventListener("mouseenter", stopAutoplay); carouselEl.addEventListener("mouseleave", scheduleAutoplay); carouselEl.addEventListener("focusin", stopAutoplay); carouselEl.addEventListener("focusout", (event) => { if (event.relatedTarget && carouselEl.contains(event.relatedTarget)) { return; } scheduleAutoplay(); }); carouselEl.addEventListener("touchstart", (event) => { if (!event.touches.length) return; touchStartX = event.touches[0].clientX; touchDeltaX = 0; stopAutoplay(); }, { passive: true }); carouselEl.addEventListener("touchmove", (event) => { if (!event.touches.length) return; touchDeltaX = event.touches[0].clientX - touchStartX; }, { passive: true }); carouselEl.addEventListener("touchend", () => { if (Math.abs(touchDeltaX) > 40) { goToSlide(touchDeltaX > 0 ? activeIndex - 1 : activeIndex + 1, { restartAutoplay: false }); } touchStartX = 0; touchDeltaX = 0; scheduleAutoplay(); }); carouselEl.addEventListener("touchcancel", () => { touchStartX = 0; touchDeltaX = 0; scheduleAutoplay(); }); document.addEventListener("visibilitychange", () => { if (document.hidden) { stopAutoplay(); return; } scheduleAutoplay(); }); if (reducedMotionQuery) { const handleMotionChange = () => { scheduleAutoplay(); }; if (typeof reducedMotionQuery.addEventListener === "function") { reducedMotionQuery.addEventListener("change", handleMotionChange); } else if (typeof reducedMotionQuery.addListener === "function") { reducedMotionQuery.addListener(handleMotionChange); } } syncActiveSlide(); scheduleAutoplay(); } function initPartyBuildingAnchors() { const headerEl = document.querySelector(".site-header"); const getScrollOffset = () => { const headerHeight = headerEl ? headerEl.getBoundingClientRect().height : 0; return headerHeight + 20; }; const scrollToHashTarget = (hash, options = {}) => { if (!hash || hash.charAt(0) !== "#") return false; const targetId = decodeURIComponent(hash.slice(1)); const targetEl = targetId ? document.getElementById(targetId) : null; if (!targetEl) return false; const nextTop = targetEl.getBoundingClientRect().top + global.pageYOffset - getScrollOffset(); global.scrollTo({ top: Math.max(nextTop, 0), behavior: options.behavior || "smooth", }); return true; }; document.querySelectorAll('a[href*="party-building.html#"], a[href^="#party-"]').forEach((link) => { link.addEventListener("click", (event) => { const rawHref = link.getAttribute("href"); if (!rawHref) return; const resolvedUrl = new URL(rawHref, global.location.href); if (!resolvedUrl.hash || resolvedUrl.pathname !== global.location.pathname) { return; } event.preventDefault(); if (global.location.hash !== resolvedUrl.hash && global.history && typeof global.history.pushState === "function") { global.history.pushState(null, "", resolvedUrl.hash); } scrollToHashTarget(resolvedUrl.hash); }); }); if (global.location.hash) { global.requestAnimationFrame(() => { global.requestAnimationFrame(() => { scrollToHashTarget(global.location.hash, { behavior: "auto" }); }); }); } global.addEventListener("hashchange", () => { scrollToHashTarget(global.location.hash); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => { initPartyBuildingReveal(); initPartyBuildingFeatureCarousel(); initPartyBuildingAnchors(); }, { once: true }); } else { initPartyBuildingReveal(); initPartyBuildingFeatureCarousel(); initPartyBuildingAnchors(); } })(window);