(() => { const $ = (s, r=document) => r.querySelector(s); const $$ = (s, r=document) => [...r.querySelectorAll(s)]; // theme toggle (Bootstrap 5.3 data-bs-theme) (function themeBoot(){ const saved = localStorage.getItem('nnai-theme'); if(saved) document.documentElement.setAttribute('data-bs-theme', saved); })(); $('#themeToggle')?.addEventListener('click', ()=>{ const root = document.documentElement; const cur = root.getAttribute('data-bs-theme') || 'light'; const next = cur === 'light' ? 'dark' : 'light'; root.setAttribute('data-bs-theme', next); localStorage.setItem('nnai-theme', next); }); // navbar scrolled shadow const nav = document.querySelector('.navbar'); const toggle = () => nav?.classList.toggle('scrolled', window.scrollY > 50); toggle(); window.addEventListener('scroll', toggle, {passive:true}); // portfolio filter + lightbox (on portfolio page) const grid = $('#portfolioGrid') || document; const buttons = $$('[data-filter]'); const items = $$('.portfolio-item'); buttons.forEach(btn=>{ btn.addEventListener('click', ()=>{ const f = btn.dataset.filter; items.forEach(card=>{ const show = f==='*' || card.dataset.category===f; card.style.display = show ? '' : 'none'; if(show) card.classList.add('animate-fade-in-up'); }); }); }); const modal = $('#portfolioModal'); const imgEl = $('#modalImage'); if(modal && imgEl){ modal.addEventListener('show.bs.modal', e=>{ const trigger = e.relatedTarget; const src = trigger?.getAttribute('data-full') || trigger?.getAttribute('src') || ''; imgEl.src = src; }); modal.addEventListener('hidden.bs.modal', ()=> imgEl.src = ''); } // form validation (contact page) const form = $('#contactForm'); const msg = $('#formMsg'); form?.addEventListener('submit', e=>{ e.preventDefault(); e.stopPropagation(); if(form.checkValidity()){ msg.textContent='Thanks! We’ll reply soon.'; msg.className='small text-success'; form.reset(); form.classList.remove('was-validated'); } else { msg.textContent='Please fix the errors above.'; msg.className='small text-danger'; } form.classList.add('was-validated'); }); })();