/* ───────── js/common.js ───────── */ (() => { function injectFragment(id, url) { const el = document.getElementById(id); if (!el) return; fetch(url) .then(r => r.text()) .then(html => { el.outerHTML = html; }) .catch(console.error); } document.addEventListener('DOMContentLoaded', () => { // Inject shared fragments if placeholders present injectFragment('nav-placeholder', 'fragments/nav.html'); injectFragment('socials-placeholder', 'fragments/socials.html'); // Smooth scroll for same-page anchors document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', e => { const targetId = anchor.getAttribute('href').slice(1); const target = document.getElementById(targetId); if (target) { e.preventDefault(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Lazy-load images & iframes document.querySelectorAll('img, iframe').forEach(el => { if (!el.hasAttribute('loading')) el.setAttribute('loading', 'lazy'); }); // Ensure nav links have aria-labels document.querySelectorAll('header.nav nav a').forEach(link => { if (!link.hasAttribute('aria-label')) { link.setAttribute('aria-label', link.textContent.trim()); } }); }); })();