Spaces:
Running
Running
| (() => { | |
| 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'); | |
| }); | |
| })(); | |