// ====== Lucide Icons Init ====== function initIcons() { if (typeof lucide !== 'undefined') { lucide.createIcons(); } } initIcons(); // ====== Theme Toggle ====== (function () { const root = document.documentElement; const toggle = document.getElementById('theme-toggle'); const stored = localStorage.getItem('omniverse-theme'); // Determine initial theme: stored > system preference > dark const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const initialTheme = stored || (prefersDark ? 'dark' : 'dark'); // Default to dark for premium feel if (initialTheme === 'light') { root.classList.remove('dark'); } else { root.classList.add('dark'); } toggle?.addEventListener('click', () => { root.classList.toggle('dark'); const isDark = root.classList.contains('dark'); localStorage.setItem('omniverse-theme', isDark ? 'dark' : 'light'); initIcons(); }); })(); // ====== Navbar Scroll Effect ====== (function () { const navbar = document.getElementById('navbar'); let ticking = false; function updateNavbar() { if (window.scrollY > 20) { navbar.classList.add('scrolled'); } else { navbar.classList.remove('scrolled'); } ticking = false; } window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(updateNavbar); ticking = true; } }); })(); // ====== Mobile Menu ====== (function () { const toggle = document.getElementById('mobile-toggle'); const menu = document.getElementById('mobile-menu'); const menuIcon = document.getElementById('menu-icon'); let isOpen = false; function toggleMenu() { isOpen = !isOpen; if (isOpen) { menu.classList.remove('hidden'); menuIcon.setAttribute('data-lucide', 'x'); } else { menu.classList.add('hidden'); menuIcon.setAttribute('data-lucide', 'menu'); } initIcons(); } toggle?.addEventListener('click', toggleMenu); // Close on link click menu?.querySelectorAll('a').forEach((link) => { link.addEventListener('click', () => { if (isOpen) toggleMenu(); }); }); // Close on outside click document.addEventListener('click', (e) => { if (isOpen && !menu.contains(e.target) && !toggle.contains(e.target)) { toggleMenu(); } }); })(); // ====== Scroll Reveal Animation ====== (function () { const reveals = document.querySelectorAll('.reveal'); const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('revealed'); observer.unobserve(entry.target); } }); }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' } ); reveals.forEach((el) => observer.observe(el)); })(); // ====== FAQ Accordion ====== (function () { const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach((item) => { const trigger = item.querySelector('.faq-trigger'); trigger?.addEventListener('click', () => { const isActive = item.classList.contains('active'); // Close all faqItems.forEach((other) => { other.classList.remove('active'); const otherTrigger = other.querySelector('.faq-trigger'); if (otherTrigger) otherTrigger.setAttribute('aria-expanded', 'false'); }); // Open clicked if (!isActive) { item.classList.add('active'); trigger.setAttribute('aria-expanded', 'true'); } }); }); })(); // ====== Contact Form (WhatsApp) ====== (function () { const form = document.getElementById('contact-form'); form?.addEventListener('submit', (e) => { e.preventDefault(); const name = document.getElementById('name')?.value.trim() || ''; const clientType = document.getElementById('client-type')?.value || ''; const service = document.getElementById('service')?.value || ''; const notes = document.getElementById('notes')?.value.trim() || ''; if (!name) return; const message = [ `Halo Omniverse One,`, ``, `Nama: ${name}`, `Kategori Klien: ${clientType}`, `Layanan: ${service}`, notes ? `Catatan: ${notes}` : '', ] .filter(Boolean) .join('\n'); const encoded = encodeURIComponent(message); window.open(`https://wa.me/?text=${encoded}`, '_blank'); }); })(); // ====== Back to Top ====== (function () { const btn = document.getElementById('back-to-top'); let ticking = false; function updateBtn() { if (window.scrollY > 600) { btn?.classList.remove('hidden'); btn?.classList.add('flex'); } else { btn?.classList.add('hidden'); btn?.classList.remove('flex'); } ticking = false; } window.addEventListener('scroll', () => { if (!ticking) { requestAnimationFrame(updateBtn); ticking = true; } }); btn?.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); })(); // ====== Year ====== document.getElementById('year').textContent = new Date().getFullYear(); // ====== Active Nav Link Highlighting ====== (function () { const sections = document.querySelectorAll('section[id]'); const navLinks = document.querySelectorAll('.nav-link'); const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const id = entry.target.getAttribute('id'); navLinks.forEach((link) => { const href = link.getAttribute('href'); if (href === `#${id}`) { link.style.color = 'var(--foreground)'; } else { link.style.color = ''; } }); } }); }, { threshold: 0.3, rootMargin: '-80px 0px -50% 0px' } ); sections.forEach((sec) => observer.observe(sec)); })(); // ====== Smooth Anchor Scroll ====== document.querySelectorAll('a[href^="#"]').forEach((anchor) => { anchor.addEventListener('click', function (e) { const href = this.getAttribute('href'); if (href === '#') return; const target = document.querySelector(href); if (target) { e.preventDefault(); const offset = 80; const top = target.getBoundingClientRect().top + window.scrollY - offset; window.scrollTo({ top, behavior: 'smooth' }); } }); }); // Re-init icons after dynamic changes setTimeout(initIcons, 100);