(function() { 'use strict'; function initHeader() { var header = document.querySelector('.gongxue-header'); if (!header) return; var update = function() { header.classList.toggle('scrolled', window.scrollY > 20); }; window.addEventListener('scroll', update, { passive: true }); update(); } function initHeaderFocusGuard() { var header = document.querySelector('.gongxue-header'); if (!header) return; var clearFocus = function(target) { if (target && typeof target.blur === 'function') { requestAnimationFrame(function() { target.blur(); }); } }; header.addEventListener('pointerdown', function(e) { clearFocus(e.target.closest('a,button')); }); header.addEventListener('click', function(e) { clearFocus(e.target.closest('a,button')); }); window.addEventListener('pageshow', function() { if (header.contains(document.activeElement)) { clearFocus(document.activeElement); } }); } function initMobileMenu() { var toggle = document.querySelector('.mobile-menu-toggle'); var menu = document.querySelector('.mobile-menu'); if (!toggle || !menu) return; toggle.addEventListener('click', function() { var open = menu.classList.contains('active'); menu.classList.toggle('active'); menu.classList.toggle('hidden'); document.body.style.overflow = open ? '' : 'hidden'; }); menu.querySelectorAll('a').forEach(function(link) { link.addEventListener('click', function() { menu.classList.remove('active'); menu.classList.add('hidden'); document.body.style.overflow = ''; }); }); } function initHeroVideo() { document.querySelectorAll('[data-gx-video]').forEach(function(box) { var video = box.querySelector('video'); var play = box.querySelector('[data-gx-play]'); var cover = box.querySelector('[data-gx-cover]'); if (!video || !play) return; play.addEventListener('click', function() { if (!video.src && video.dataset.src) video.src = video.dataset.src; video.controls = true; video.play(); video.classList.remove('opacity-0'); video.classList.add('opacity-100'); if (cover) cover.classList.add('hidden'); play.classList.add('hidden'); }); }); } function initModals() { document.querySelectorAll('[data-gx-modal-open]').forEach(function(button) { button.addEventListener('click', function() { var modal = document.querySelector(button.dataset.gxModalOpen); if (modal) modal.classList.add('active'); }); }); document.querySelectorAll('[data-gx-modal-close], .gx-modal-backdrop').forEach(function(button) { button.addEventListener('click', function() { var modal = button.closest('.gx-modal'); if (modal) modal.classList.remove('active'); }); }); } function initFloatingService() { var toggle = document.querySelector('.service-toggle'); var menu = document.querySelector('.service-menu'); if (!toggle || !menu) return; toggle.addEventListener('click', function() { menu.classList.toggle('closed'); toggle.classList.toggle('rotate-90'); }); document.addEventListener('click', function(e) { var service = document.querySelector('.floating-service'); if (service && !service.contains(e.target)) { menu.classList.add('closed'); toggle.classList.remove('rotate-90'); } }); } function initShare() { document.querySelectorAll('.gx-share').forEach(function(button) { button.addEventListener('click', function() { var url = button.dataset.url || location.href; var title = button.dataset.title || document.title; if (navigator.share) { navigator.share({ title: title, url: url }).catch(function() {}); } else if (navigator.clipboard) { navigator.clipboard.writeText(url); button.textContent = '链接已复制'; setTimeout(function() { button.textContent = '分享文章'; }, 1400); } }); }); } function initCounters() { var nodes = document.querySelectorAll('[data-count-end]'); if (!nodes.length || !('IntersectionObserver' in window)) return; var observer = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (!entry.isIntersecting || entry.target.dataset.done) return; entry.target.dataset.done = '1'; var el = entry.target; var end = parseFloat(el.dataset.countEnd) || 0; var suffix = el.dataset.countSuffix || ''; var start = performance.now(); function frame(now) { var t = Math.min((now - start) / 1800, 1); var value = end * (1 - Math.pow(1 - t, 4)); el.textContent = Math.round(value) + suffix; if (t < 1) requestAnimationFrame(frame); } requestAnimationFrame(frame); }); }, { threshold: 0.4 }); nodes.forEach(function(node) { observer.observe(node); }); } document.addEventListener('DOMContentLoaded', function() { initHeader(); initHeaderFocusGuard(); initMobileMenu(); initHeroVideo(); initModals(); initFloatingService(); initShare(); initCounters(); }); })();