/* 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 = '';
}