(function () { const qs = (sel, ctx = document) => ctx.querySelector(sel); const qsa = (sel, ctx = document) => Array.from(ctx.querySelectorAll(sel)); // Mobile menu const menuToggle = qs('#menuToggle'); const mobileMenu = qs('#mobileMenu'); if (menuToggle && mobileMenu) { menuToggle.addEventListener('click', () => { const isHidden = mobileMenu.classList.contains('hidden'); mobileMenu.classList.toggle('hidden', !isHidden); menuToggle.setAttribute('aria-expanded', String(isHidden)); }); } // Expand/Collapse all curriculum modules const expandBtn = qs('#expandAll'); const modules = qsa('.module'); if (expandBtn && modules.length) { const toggleAll = () => { const shouldOpen = expandBtn.dataset.state !== 'open'; modules.forEach((mod) => { const content = qs('.module-content', mod); const icon = qs('.module-icon', mod); const summaryBtn = qs('.module-toggle', mod); if (shouldOpen) { openModule(mod, content, icon, summaryBtn, false); } else { closeModule(mod, content, icon, summaryBtn, false); } }); expandBtn.dataset.state = shouldOpen ? 'open' : 'closed'; const icon = qs('i', expandBtn); if (icon) { icon.setAttribute('data-feather', shouldOpen ? 'minus-square' : 'plus-square'); // Replace icon if (window.feather && typeof feather.replace === 'function') { feather.replace(); } } }; expandBtn.addEventListener('click', toggleAll); } // Individual module toggle function openModule(module, content, icon, summaryBtn, animate = true) { summaryBtn.setAttribute('aria-expanded', 'true'); content.classList.remove('hidden'); content.classList.add('open'); if (icon) icon.style.transform = 'rotate(180deg)'; if (animate) { // auto height animation content.style.maxHeight = '0px'; requestAnimationFrame(() => { content.style.maxHeight = content.scrollHeight + 'px'; }); const onEnd = (e) => { if (e.propertyName !== 'max-height') return; content.style.maxHeight = 'none'; content.removeEventListener('transitionend', onEnd); }; content.addEventListener('transitionend', onEnd); } else { content.style.maxHeight = 'none'; } } function closeModule(module, content, icon, summaryBtn, animate = true) { summaryBtn.setAttribute('aria-expanded', 'false'); if (animate) { // from current height to 0 content.style.maxHeight = content.scrollHeight + 'px'; requestAnimationFrame(() => { content.style.maxHeight = '0px'; }); const onEnd = (e) => { if (e.propertyName !== 'max-height') return; content.classList.remove('open'); content.classList.add('hidden'); content.style.maxHeight = ''; content.removeEventListener('transitionend', onEnd); }; content.addEventListener('transitionend', onEnd); } else { content.classList.remove('open'); content.classList.add('hidden'); content.style.maxHeight = ''; } if (icon) icon.style.transform = 'rotate(0deg)'; } modules.forEach((mod) => { const content = qs('.module-content', mod); const icon = qs('.module-icon', mod); const summaryBtn = qs('.module-toggle', mod); summaryBtn.addEventListener('click', (e) => { e.preventDefault(); const isOpen = summaryBtn.getAttribute('aria-expanded') === 'true'; if (isOpen) { closeModule(mod, content, icon, summaryBtn, true); } else { openModule(mod, content, icon, summaryBtn, true); } }); }); // FAQ accordion behavior: only one open at a time const faqs = qsa('#faq details'); if (faqs.length) { faqs.forEach((faq) => { faq.addEventListener('toggle', () => { if (faq.open) { faqs.forEach((other) => { if (other !== faq) other.removeAttribute('open'); }); } }); }); } // Smooth scroll offset for fixed header const offset = 16; // header height-ish qsa('a[href^="#"]').forEach((a) => { a.addEventListener('click', (e) => { const id = a.getAttribute('href'); if (!id || id === '#') return; const el = qs(id); if (!el) return; e.preventDefault(); const top = el.getBoundingClientRect().top + window.scrollY - offset; window.scrollTo({ top, behavior: 'smooth' }); history.pushState(null, '', id); }); }); // Footer year const yearEl = qs('#year'); if (yearEl) { yearEl.textContent = String(new Date().getFullYear()); } // Replace Feather icons if dynamically inserted if (window.feather && typeof feather.replace === 'function') { feather.replace(); } })();