(() => { const input = document.getElementById('search-input'); const resultsBox = document.getElementById('search-results'); if (!input || !resultsBox) return; let index = []; let loaded = false; const render = (items) => { if (!items.length) { resultsBox.innerHTML = '

No matches.

'; resultsBox.classList.add('active'); return; } const list = items .slice(0, 12) .map(item => `
  • ${item.title}
    ${item.section}
    ${item.summary}
  • `).join(''); resultsBox.innerHTML = ``; resultsBox.classList.add('active'); }; const filter = (query) => { if (!query.trim()) { resultsBox.classList.remove('active'); return; } const q = query.toLowerCase(); const items = index.filter(item => { return ( item.title.toLowerCase().includes(q) || item.section.toLowerCase().includes(q) || item.summary.toLowerCase().includes(q) || item.tags.some(tag => tag.toLowerCase().includes(q)) ); }); render(items); }; const loadIndex = async () => { if (loaded) return index; try { const res = await fetch('/search-index.json'); index = await res.json(); loaded = true; } catch (err) { console.error('Search index failed to load', err); } return index; }; input.addEventListener('input', async (e) => { await loadIndex(); filter(e.target.value); }); document.addEventListener('click', (e) => { if (!resultsBox.contains(e.target) && e.target !== input) { resultsBox.classList.remove('active'); } }); })();