/* VoxTek EN - Public Access Hub (client-side only) - No files are hosted. This is an index UI. - Edit the `CHANNELS` object to add or remove external links. */ const CHANNELS = { cinema: [ { title: "Noir Classic", year: "1955", tags: ["b&w","noir"], link: "https://example.com", note: "External broadcast" }, { title: "Sci‑Fi Reel", year: "1978", tags: ["retro","space"], link: "https://example.com", note: "External broadcast" } ], music: [ { title: "Analog Dreams Vol.1", year: "—", tags: ["synth","loop"], link: "https://example.com", note: "External stream" }, { title: "City FM Session", year: "—", tags: ["radio"], link: "https://example.com", note: "External station" } ], interactive: [ { title: "Voxel Arcade", year: "v0.9", tags: ["webgame","arcade"], link: "https://example.com", note: "External site" }, { title: "Open Runner", year: "v1.2", tags: ["platformer"], link: "https://example.com", note: "External site" } ], print: [ { title: "Pulp Serial Issue #1", year: "1940", tags: ["serial","pulp"], link: "https://example.com", note: "External archive" }, { title: "Manual: Retro CRT", year: "—", tags: ["guide"], link: "https://example.com", note: "External doc" } ] }; // Build cards function makeCard(item){ const li = document.createElement('li'); li.className = 'card'; li.innerHTML = `

${item.title}

${item.year ? item.year + " • " : ""}${(item.tags||[]).join(", ")}
Tune In ${item.note ? `${item.note}` : ""}
`; return li; } function render(channel, gridId){ const grid = document.getElementById(gridId); grid.innerHTML = ""; CHANNELS[channel].forEach(item => grid.appendChild(makeCard(item))); } render('cinema', 'grid-cinema'); render('music', 'grid-music'); render('interactive', 'grid-interactive'); render('print', 'grid-print'); // Tabs document.querySelectorAll('.tab-btn').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); btn.classList.add('active'); const chan = btn.dataset.channel; document.querySelectorAll('.panel').forEach(p => p.classList.remove('active')); document.getElementById('panel-' + chan).classList.add('active'); flashStatic(); }); }); // Search filter across current panel const searchBox = document.getElementById('searchBox'); searchBox.addEventListener('input', () => { const query = searchBox.value.trim().toLowerCase(); const active = document.querySelector('.panel.active ul.card-grid'); if(!active) return; active.querySelectorAll('.card').forEach(card => { const text = card.textContent.toLowerCase(); card.style.display = text.includes(query) ? '' : 'none'; }); }); // Glitch toggle (reduces overlays/animations) const toggle = document.getElementById('toggleTheme'); toggle.addEventListener('click', () => { document.body.classList.toggle('calm'); const on = !document.body.classList.contains('calm'); document.getElementById('statusText').textContent = on ? 'ON AIR' : 'STANDBY'; }); // Calm mode styles injected const calmStyle = document.createElement('style'); calmStyle.innerHTML = ` .calm .crt-overlay, .calm .static { display:none !important; } `; document.head.appendChild(calmStyle); // Export links as JSON document.getElementById('exportBtn').addEventListener('click', (e) => { const blob = new Blob([JSON.stringify(CHANNELS, null, 2)], {type: 'application/json'}); const url = URL.createObjectURL(blob); e.target.href = url; }); // Static flash when switching tabs function flashStatic(){ const s = document.querySelector('.static'); s.style.animation = 'none'; void s.offsetHeight; // reflow s.style.animation = ''; }