/* ============================================================ LAYOUT.JS — shared across all layout pages Handles: theme switching, layout switching, mobile menu, FAQ accordion, contact form, scroll animations ============================================================ */ (function () { const html = document.documentElement; // ── 1. Apply saved theme immediately (before paint) ────── const savedTheme = localStorage.getItem('demo-theme') || 'midnight'; html.setAttribute('data-theme', savedTheme); // ── 2. Apply saved layout pill active state ────────────── const savedLayout = localStorage.getItem('demo-layout') || 'a'; document.addEventListener('DOMContentLoaded', () => { // ── Theme switcher ────────────────────────────────────── const themePills = document.querySelectorAll('.theme-pill'); themePills.forEach(pill => { if (pill.dataset.t === savedTheme) pill.classList.add('active'); pill.addEventListener('click', () => applyTheme(pill.dataset.t)); }); function applyTheme(name) { html.setAttribute('data-theme', name); localStorage.setItem('demo-theme', name); themePills.forEach(p => p.classList.toggle('active', p.dataset.t === name)); } // ── Layout switcher ───────────────────────────────────── const layoutPills = document.querySelectorAll('.layout-pill'); const LAYOUT_PAGES = { a: 'index.html', b: 'layout-b.html', c: 'layout-c.html' }; layoutPills.forEach(pill => { if (pill.dataset.l === savedLayout) pill.classList.add('active'); pill.addEventListener('click', () => { const target = pill.dataset.l; if (target === savedLayout) return; // already on this layout localStorage.setItem('demo-layout', target); // Fade out, navigate document.body.style.transition = 'opacity 0.25s ease'; document.body.style.opacity = '0'; setTimeout(() => { window.location.href = LAYOUT_PAGES[target]; }, 240); }); }); // ── Mobile menu toggle ────────────────────────────────── const mobileToggle = document.getElementById('mobileToggle'); const mobileMenu = document.getElementById('mobileMenu'); if (mobileToggle) { mobileToggle.addEventListener('click', () => { mobileMenu.classList.toggle('is-open'); }); } // ── FAQ accordion ─────────────────────────────────────── document.querySelectorAll('.faq-question').forEach(btn => { btn.addEventListener('click', () => { const item = btn.closest('.faq-item'); const isOpen = item.classList.contains('is-open'); document.querySelectorAll('.faq-item').forEach(i => i.classList.remove('is-open')); if (!isOpen) item.classList.add('is-open'); }); }); // ── Contact form ──────────────────────────────────────── const contactForm = document.getElementById('contactForm'); const formSuccess = document.getElementById('formSuccess'); if (contactForm) { contactForm.addEventListener('submit', e => { e.preventDefault(); contactForm.style.display = 'none'; formSuccess.classList.add('is-visible'); }); } // ── Scroll-triggered feature cards ────────────────────── const featureCards = document.querySelectorAll('.feature-card'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; observer.unobserve(entry.target); } }); }, { threshold: 0.12 }); featureCards.forEach((card, i) => { card.style.opacity = '0'; card.style.transform = 'translateY(24px)'; card.style.transition = `opacity 0.5s ease ${i * 0.08}s, transform 0.5s ease ${i * 0.08}s, border-color 0.3s ease, box-shadow 0.3s ease`; observer.observe(card); }); // ── Fade in on load ───────────────────────────────────── document.body.style.opacity = '0'; document.body.style.transition = 'opacity 0.3s ease'; requestAnimationFrame(() => { requestAnimationFrame(() => { document.body.style.opacity = '1'; }); }); }); })();