/* ============================================================ J. Scott Branson — main.js ============================================================ */ (function () { 'use strict'; /* ── Sticky header shadow ── */ const masthead = document.querySelector('.masthead'); if (masthead) { window.addEventListener('scroll', () => { masthead.classList.toggle('scrolled', window.scrollY > 12); }, { passive: true }); } /* ── Scroll-reveal (IntersectionObserver) ── */ const revealEls = document.querySelectorAll('.reveal'); if ('IntersectionObserver' in window && revealEls.length) { const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { threshold: 0.09, rootMargin: '0px 0px -28px 0px' }); revealEls.forEach((el, i) => { // Stagger siblings within the same parent const siblings = el.parentElement ? [...el.parentElement.querySelectorAll('.reveal')] : []; const idx = siblings.indexOf(el); if (idx > 0) el.style.transitionDelay = `${idx * 75}ms`; io.observe(el); }); } else { revealEls.forEach((el) => el.classList.add('in')); } /* ── Active nav link on scroll ── */ const anchors = document.querySelectorAll('[id]'); const navLinks = document.querySelectorAll('nav a[href^="#"]'); function syncNav() { let current = ''; anchors.forEach((el) => { if (el.getBoundingClientRect().top < window.innerHeight * 0.42) { current = el.id; } }); navLinks.forEach((a) => { a.classList.toggle('active', a.getAttribute('href') === `#${current}`); }); } window.addEventListener('scroll', syncNav, { passive: true }); syncNav(); /* ── Smooth-scroll all hash links ── */ document.querySelectorAll('a[href^="#"]').forEach((a) => { a.addEventListener('click', (e) => { const target = document.querySelector(a.getAttribute('href')); if (target) { e.preventDefault(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); })();