// ============================================================ // Tribeca Lisboa — EVENT DETAIL sections (responsive) // Reuses Primitives (CAT, R, IconPin, Reveal) + the homepage // event card REventCard (from ResponsiveSections.jsx) for Related. // ============================================================ const { useState: useStateE, useEffect: useEffectE, useRef: useRefE } = React; // ---- icons (1px line, match grotesque tone; X = real logo) --- function EIcon({ name, style }) { const stroke = { back: , share: <>, cal: <>, ticket: <>, arrow: , check: , close: , link: <>, ig: <>, wa: , }[name]; // X (Twitter) is a solid-glyph logo, not a line icon if (name === 'xlogo') { return ( ); } return ( {stroke} ); } // ---- reveal-on-scroll (full-page / window) ----------------- function useReveal(rootRef) { useEffectE(() => { const root = rootRef.current; if (!root) return; const els = root.querySelectorAll('.ed-rev'); if (window.PREFERS_REDUCED) { els.forEach(e => e.classList.add('in')); return; } const vh = () => window.innerHeight || document.documentElement.clientHeight; const check = () => els.forEach(el => { if (el.classList.contains('in')) return; const r = el.getBoundingClientRect(); if (r.top < vh() - 30 && r.bottom > 0) el.classList.add('in'); }); let frames = 0, raf, alive = true; const burst = () => { if (!alive) return; check(); if (frames++ < 16) raf = requestAnimationFrame(burst); }; const onScroll = () => check(); window.addEventListener('scroll', onScroll, { passive: true }); window.addEventListener('resize', onScroll); burst(); const t1 = setTimeout(check, 300), t2 = setTimeout(check, 800); return () => { alive = false; cancelAnimationFrame(raf); clearTimeout(t1); clearTimeout(t2); window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); }; }, []); } // ---- Hero --------------------------------------------------- function EdHero() { const lang = React.useContext(LangContext); const c = CAT[EVENT.cat]; return (
{EVENT.title}
{c.label} {EVENT.status}
{tt(lang, EVENT.kickerEn, EVENT.kicker)}

{EVENT.title}

); } // ---- Info strip + secondary actions ------------------------- function EdInfo({ onCalendar, onShare }) { const lang = React.useContext(LangContext); return (
{tt(lang, 'Date', 'Data')}
{tt(lang, EVENT.dateEn, EVENT.date)}
{tt(lang, 'Time · Duration', 'Hora · Duração')}
{EVENT.time} · {EVENT.duration}
{tt(lang, 'Venue', 'Local')}
{EVENT.venueName} · {EVENT.venueArea}
); } // ---- Description -------------------------------------------- function EdDescription() { const lang = React.useContext(LangContext); return (
{tt(lang, 'About the event', 'Sobre o evento')}

{tt(lang, EVENT.leadEn, EVENT.lead)}

{tt(lang, EVENT.bodyEn, EVENT.body)}

); } // ---- Program ------------------------------------------------ function EdProgram() { const lang = React.useContext(LangContext); return (
{tt(lang, 'The night, in detail', 'A noite, ao detalhe')}

{tt(lang, 'Programme', 'Programa')}

{PROGRAM.map((p, i) => (
{p.time}
{tt(lang, p.titleEn, p.title)}
{tt(lang, p.noteEn, p.note)}
))}
); } // ---- Guest / speaker card (shared component — reused by the // News Article page for Related speakers; do not fork) --------- function EdGuestCard({ g }) { const lang = React.useContext(LangContext); const linked = window.isConfirmedGuest ? isConfirmedGuest(g.id) : true; // only confirmed guests open a Talent page const inner = (<>
{g.name} {linked &&
}
{tt(lang, g.roleEn || g.role, g.role)}
{g.name}
); if (!linked) { return
{inner}
; } return {inner}; } // ---- Guests (editorial rail — no feature card) -------------- function EdGuests() { const lang = React.useContext(LangContext); return (
{tt(lang, 'Who you’ll meet', 'Quem vais encontrar')}

{tt(lang, 'Guests', 'Convidados')}

{GUESTS.map(g => )}
); } // ---- Related (events only — homepage event card) ------------ function EdRelated() { const lang = React.useContext(LangContext); return (
{tt(lang, 'Related content', 'Conteúdo relacionado')}

{tt(lang, 'Recommended', 'Recomendados')}

{RELATED.map(ev => )}
); } Object.assign(window, { EIcon, useReveal, EdHero, EdInfo, EdDescription, EdProgram, EdGuests, EdGuestCard, EdRelated });