// Reusable components for Midsummer Festival site const { useState, useEffect, useRef } = React; // ----- Icons ----- function Icon({ name, size = 24 }) { const stroke = "currentColor"; const sw = 1.5; const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke, strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round" }; switch (name) { case "train": return ; case "bus": return ; case "shuttle": return ; case "car": return ; case "plane": return ; case "bike": return ; case "arrow": return ; case "plus": return ; case "play": return ; case "chevronLeft": return ; case "chevronRight": return ; default: return null; } } // ----- Sticky Nav ----- function Nav({ lang, setLang, copy, activeSection }) { const [scrolled, setScrolled] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 60); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); const items = [ { id: 'info', label: copy.nav.info }, { id: 'tickets', label: copy.nav.tickets }, { id: 'impressions', label: copy.nav.impressions }, { id: 'travel', label: copy.nav.travel }, { id: 'faq', label: copy.nav.faq }, ]; return ( ); } // ----- Countdown ----- function Countdown({ labels }) { const target = new Date('2026-06-20T12:00:00+02:00').getTime(); const calc = () => { const diff = Math.max(0, target - Date.now()); const d = Math.floor(diff / 86400000); const h = Math.floor((diff % 86400000) / 3600000); const m = Math.floor((diff % 3600000) / 60000); const s = Math.floor((diff % 60000) / 1000); return { d, h, m, s }; }; const [t, setT] = useState(calc()); useEffect(() => { const i = setInterval(() => setT(calc()), 1000); return () => clearInterval(i); }, []); const pad = (n) => String(n).padStart(2, '0'); return (