// ============================================================
// Tribeca Lisboa — CONTENT STORE (bilingual EN/PT) + routing
// Single source for homepage lists + every event/news detail.
// Detail pages resolve by ?id=. Only the allowed pages link.
// ============================================================

// ---- routing helpers ----------------------------------------
const PAGES = {
  home:  'Tribeca Festival Lisboa - Responsive.html',
  about: 'Tribeca Festival Lisboa - About.html',
  event: 'Tribeca Festival Lisboa - Event Detail.html',
  news:  'Tribeca Festival Lisboa - News Article.html',
  news_list: 'Tribeca Festival Lisboa - News Listing.html',
  soon: 'Tribeca Festival Lisboa - Coming Soon.html',
  legal: 'Tribeca Festival Lisboa - Legal.html',
  landing: 'index.html',
  legal_landing: 'legal.html',
};
window.urlFor = (kind, id) => PAGES[kind] + (id ? ('?id=' + encodeURIComponent(id)) : '');
window.getParam = (k) => { try { return new URLSearchParams(location.search).get(k); } catch (e) { return null; } };

// ---- speakers (shared, referenced by events + news) ---------
const SPEAKERS = {
  esposito: { id:'esposito', name:'Giancarlo Esposito', img:'uploads/thumbnail_3.png' },
  deniro:   { id:'deniro',   name:'Robert De Niro',     img:'uploads/thumbnail_8.png' },
  whoopi:   { id:'whoopi',   name:'Whoopi Goldberg',    img:'uploads/thumbnail_5.png' },
  nuno:     { id:'nuno',     name:'Nuno Lopes',         img:'uploads/thumbnail.png' },
  branko:   { id:'branko',   name:'Branko',             img:'uploads/video_thumbnail.png' },
  barker:   { id:'barker',   name:'Nigel Barker',       img:'uploads/thumbnail_3.png' },
};
const sp = (key, role, roleEn) => ({ id: SPEAKERS[key].id, name: SPEAKERS[key].name, img: SPEAKERS[key].img, role, roleEn });

// ---- EVENTS (full detail, keyed by id) ----------------------
const EVENTS = [
  {
    id:'e1', cat:'film', img:'uploads/thumbnail_2.png',
    title:'The Last Reel', titleEn:'The Last Reel',
    date:'14/06 • 1h45', dayDate:'14 junho 2026', dayDateEn:'14 June 2026', time:'21:00', duration:'1h45',
    venue:'Cinema São Jorge', venueArea:'Avenida da Liberdade, Lisboa', status:'SOON',
    kicker:'Estreia europeia', kickerEn:'European premiere',
    availability:'Bilhetes limitados', availabilityEn:'Limited tickets',
    lead:'Uma sala de cinema prestes a fechar torna-se o último refúgio de uma comunidade que se recusa a desaparecer. The Last Reel abre a secção Film com uma estreia europeia seguida de conversa com a equipa.',
    leadEn:'A cinema about to close becomes the last refuge of a community that refuses to disappear. The Last Reel opens the Film strand with a European premiere followed by a conversation with the team.',
    body:'Filmado entre Lisboa e Nova Iorque ao longo de três anos, The Last Reel é um retrato sobre memória, projeção e a forma como as histórias nos mantêm vivos.',
    bodyEn:'Filmed between Lisbon and New York over three years, The Last Reel is a portrait of memory, projection and the way stories keep us alive.',
    program:[
      { time:'20:30', title:'Abertura de portas', titleEn:'Doors open', note:'Welcome drink no foyer', noteEn:'Welcome drink in the foyer' },
      { time:'21:15', title:'Projeção', titleEn:'Screening', note:'VO com legendas PT', noteEn:'OV with PT subtitles' },
      { time:'23:00', title:'Conversa com a equipa', titleEn:'In conversation', note:'Q&A com realizador e elenco', noteEn:'Q&A with director and cast' },
      { time:'23:30', title:'Encerramento', titleEn:'Closing', note:'Drinks no terraço', noteEn:'Drinks on the terrace' },
    ],
    guests:[ sp('deniro','Realizador','Director'), sp('whoopi','Atriz principal','Lead actress'), sp('barker','Diretor de fotografia','Cinematographer') ],
    related:['e4','e3','e5'],
  },
  {
    id:'e2', cat:'nightlive', img:'uploads/video_thumbnail.png',
    title:'Noite no Chiado', titleEn:'Night in Chiado',
    date:'14/06 • 4h00', dayDate:'14 junho 2026', dayDateEn:'14 June 2026', time:'23:30', duration:'4h00',
    venue:'LX Factory', venueArea:'Alcântara, Lisboa', status:'SOON',
    kicker:'Festa de abertura', kickerEn:'Opening party',
    availability:'À porta', availabilityEn:'At the door',
    lead:'A primeira noite do festival sai à rua. Entre projeções ao ar livre e sets ao vivo, o Chiado transforma-se num palco aberto até de madrugada.',
    leadEn:'The festival’s first night spills into the street. Between open-air screenings and live sets, Chiado becomes an open stage until dawn.',
    body:'Curadoria sonora de Branko, com convidados surpresa e uma pista que atravessa cinema, música e cidade.',
    bodyEn:'Sound curation by Branko, with surprise guests and a dancefloor that runs across cinema, music and city.',
    program:[
      { time:'23:30', title:'Abertura', titleEn:'Doors', note:'Boas-vindas e DJ set', noteEn:'Welcome & DJ set' },
      { time:'00:30', title:'Live set — Branko', titleEn:'Live set — Branko', note:'Palco principal', noteEn:'Main stage' },
      { time:'02:00', title:'After', titleEn:'After', note:'Convidados surpresa', noteEn:'Surprise guests' },
    ],
    guests:[ sp('branko','Live set','Live set'), sp('nuno','Anfitrião','Host') ],
    related:['e8','e6','e1'],
  },
  {
    id:'e3', cat:'talks', img:'uploads/thumbnail.png',
    title:'O futuro da história', titleEn:'The Future of Story',
    date:'16/06 • 1h30', dayDate:'16 junho 2026', dayDateEn:'16 June 2026', time:'17:30', duration:'1h30',
    venue:'Culturgest', venueArea:'Av. João XXI, Lisboa', status:'SOON',
    kicker:'Conversa', kickerEn:'In conversation',
    availability:'Bilhetes limitados', availabilityEn:'Limited tickets',
    lead:'Como muda o storytelling quando a tecnologia muda? Uma conversa sobre escrita, IA e o que continua profundamente humano em contar histórias.',
    leadEn:'How does storytelling change when technology changes? A conversation about writing, AI and what remains deeply human in telling stories.',
    body:'Giancarlo Esposito junta-se a criadores e investigadores para mapear o que vem a seguir — sem perder de vista o que nunca muda.',
    bodyEn:'Giancarlo Esposito joins creators and researchers to map what comes next — without losing sight of what never changes.',
    program:[
      { time:'17:30', title:'Abertura', titleEn:'Opening', note:'Apresentação', noteEn:'Introduction' },
      { time:'17:45', title:'Painel', titleEn:'Panel', note:'Storytelling & tecnologia', noteEn:'Storytelling & technology' },
      { time:'18:45', title:'Perguntas', titleEn:'Q&A', note:'Aberto ao público', noteEn:'Open to the audience' },
    ],
    guests:[ sp('esposito','Orador principal','Keynote'), sp('nuno','Moderação','Moderation') ],
    related:['e5','e1','e7'],
  },
  {
    id:'e4', cat:'film', img:'uploads/thumbnail_8.png',
    title:'Ruas de Nova Iorque', titleEn:'Streets of New York',
    date:'15/06 • 2h05', dayDate:'15 junho 2026', dayDateEn:'15 June 2026', time:'19:30', duration:'2h05',
    venue:'Cinema Ideal', venueArea:'Bairro Alto, Lisboa', status:'SOON',
    kicker:'Sessão especial', kickerEn:'Special screening',
    availability:'Bilhetes à venda', availabilityEn:'On sale',
    lead:'Um clássico restaurado sobre a cidade que inventou a Tribeca. Ruas, retratos e a energia de um lugar que nunca pára.',
    leadEn:'A restored classic about the city that invented Tribeca. Streets, portraits and the energy of a place that never stops.',
    body:'Apresentado por Robert De Niro numa sessão que liga as origens nova-iorquinas do festival ao seu presente em Lisboa.',
    bodyEn:'Presented by Robert De Niro in a session linking the festival’s New York origins to its present in Lisbon.',
    program:[
      { time:'19:30', title:'Introdução', titleEn:'Introduction', note:'Por Robert De Niro', noteEn:'By Robert De Niro' },
      { time:'19:45', title:'Projeção', titleEn:'Screening', note:'Cópia restaurada', noteEn:'Restored print' },
      { time:'21:50', title:'Conversa', titleEn:'Conversation', note:'Breve Q&A', noteEn:'Short Q&A' },
    ],
    guests:[ sp('deniro','Apresenta','Presents'), sp('barker','Convidado','Guest') ],
    related:['e1','e3','e9'],
  },
  {
    id:'e5', cat:'talks', img:'uploads/thumbnail_5.png',
    title:'Vozes que ficam', titleEn:'Voices That Stay',
    date:'17/06 • 1h15', dayDate:'17 junho 2026', dayDateEn:'17 June 2026', time:'18:00', duration:'1h15',
    venue:'Teatro Tivoli', venueArea:'Avenida da Liberdade, Lisboa', status:'SOON',
    kicker:'Em conversa', kickerEn:'In conversation',
    availability:'Bilhetes limitados', availabilityEn:'Limited tickets',
    lead:'Uma vida em palco e em ecrã. Whoopi Goldberg fala sobre voz, representação e as histórias que recusou deixar por contar.',
    leadEn:'A life on stage and on screen. Whoopi Goldberg talks voice, representation and the stories she refused to leave untold.',
    body:'Uma conversa íntima sobre humor, resistência e o poder de uma voz que se recusa a baixar o tom.',
    bodyEn:'An intimate conversation about humour, resistance and the power of a voice that refuses to lower its tone.',
    program:[
      { time:'18:00', title:'Abertura', titleEn:'Opening', note:'Apresentação', noteEn:'Introduction' },
      { time:'18:10', title:'Conversa', titleEn:'Conversation', note:'Moderada', noteEn:'Moderated' },
      { time:'19:00', title:'Perguntas', titleEn:'Q&A', note:'Aberto ao público', noteEn:'Open to the audience' },
    ],
    guests:[ sp('whoopi','Convidada','Guest'), sp('nuno','Moderação','Moderation') ],
    related:['e3','e1','e9'],
  },
  {
    id:'e6', cat:'vibes', img:'uploads/thumbnail_6.png',
    title:'Verão analógico', titleEn:'Analogue Summer',
    date:'18/06 • 3h00', dayDate:'18 junho 2026', dayDateEn:'18 June 2026', time:'16:00', duration:'3h00',
    venue:'Jardim da Estrela', venueArea:'Estrela, Lisboa', status:'SOON',
    kicker:'Ao ar livre', kickerEn:'Open air',
    availability:'Entrada livre', availabilityEn:'Free entry',
    lead:'Tarde de cinema em película, vinis e luz dourada no jardim. Uma celebração lenta do analógico em plena cidade.',
    leadEn:'An afternoon of film prints, vinyl and golden light in the garden. A slow celebration of the analogue in the heart of the city.',
    body:'Mantas, projeção em 16mm e uma seleção musical que pede para ficar até ao último raio de sol.',
    bodyEn:'Blankets, a 16mm projection and a musical selection that asks you to stay until the last ray of sun.',
    program:[
      { time:'16:00', title:'Abertura', titleEn:'Opening', note:'Vinis no jardim', noteEn:'Vinyl in the garden' },
      { time:'18:00', title:'Projeção 16mm', titleEn:'16mm screening', note:'Curtas', noteEn:'Shorts' },
      { time:'19:00', title:'Pôr do sol', titleEn:'Sunset', note:'Set final', noteEn:'Closing set' },
    ],
    guests:[ sp('branko','Seleção musical','Music selection') ],
    related:['e2','e8','e1'],
  },
  {
    id:'e7', cat:'industry', img:'uploads/thumbnail_3.png',
    title:'Mercado & mentes', titleEn:'Market & Minds',
    date:'19/06 • 2h30', dayDate:'19 junho 2026', dayDateEn:'19 June 2026', time:'10:00', duration:'2h30',
    venue:'Hub Beato', venueArea:'Beato, Lisboa', status:'SOON',
    kicker:'Indústria', kickerEn:'Industry',
    availability:'Acreditação', availabilityEn:'Accreditation',
    lead:'Onde criadores e indústria se encontram. Pitches, financiamento e o futuro do negócio das histórias.',
    leadEn:'Where creators and industry meet. Pitches, financing and the future of the story business.',
    body:'Uma manhã de trabalho com produtores, plataformas e talento emergente — a ponte prática entre Lisboa e o mundo.',
    bodyEn:'A working morning with producers, platforms and emerging talent — the practical bridge between Lisbon and the world.',
    program:[
      { time:'10:00', title:'Keynote', titleEn:'Keynote', note:'Abertura', noteEn:'Opening' },
      { time:'10:45', title:'Pitches', titleEn:'Pitches', note:'Projetos selecionados', noteEn:'Selected projects' },
      { time:'12:00', title:'Networking', titleEn:'Networking', note:'Café & contactos', noteEn:'Coffee & contacts' },
    ],
    guests:[ sp('barker','Mentor','Mentor'), sp('nuno','Anfitrião','Host') ],
    related:['e3','e9','e1'],
  },
  {
    id:'e8', cat:'nightlive', img:'uploads/thumbnail_4.png',
    title:'After Hours', titleEn:'After Hours',
    date:'20/06 • 5h00', dayDate:'20 junho 2026', dayDateEn:'20 June 2026', time:'00:30', duration:'5h00',
    venue:'Lux Frágil', venueArea:'Santa Apolónia, Lisboa', status:'SOON',
    kicker:'Clube', kickerEn:'Club night',
    availability:'À porta', availabilityEn:'At the door',
    lead:'Quando o festival fecha as salas, abre a pista. A noite mais longa da semana, no clube mais icónico da cidade.',
    leadEn:'When the festival closes the theatres, the dancefloor opens. The longest night of the week, at the city’s most iconic club.',
    body:'Line-up secreto, luz no Tejo e o nascer do sol incluído. After oficial do Tribeca Festival Lisboa.',
    bodyEn:'Secret line-up, light over the Tagus and sunrise included. The official Tribeca Festival Lisboa after.',
    program:[
      { time:'00:30', title:'Abertura', titleEn:'Doors', note:'Sala principal', noteEn:'Main room' },
      { time:'02:00', title:'Headliner', titleEn:'Headliner', note:'Set secreto', noteEn:'Secret set' },
      { time:'05:00', title:'Sunrise', titleEn:'Sunrise', note:'Encerramento', noteEn:'Closing' },
    ],
    guests:[ sp('branko','Line-up','Line-up') ],
    related:['e2','e6','e1'],
  },
  {
    id:'e9', cat:'awards', img:'uploads/thumbnail_7.png',
    title:'Gala de encerramento', titleEn:'Closing Gala',
    date:'21/06 • 2h00', dayDate:'21 junho 2026', dayDateEn:'21 June 2026', time:'20:00', duration:'2h00',
    venue:'CCB', venueArea:'Belém, Lisboa', status:'SOON',
    kicker:'Cerimónia', kickerEn:'Ceremony',
    availability:'Por convite', availabilityEn:'By invitation',
    lead:'A noite que fecha a edição e premeia as histórias do ano. Cinema, discursos e uma última festa antes de 2027.',
    leadEn:'The night that closes the edition and honours the year’s stories. Cinema, speeches and one last party before 2027.',
    body:'Os prémios do júri, atuações ao vivo e o anúncio dos primeiros nomes da próxima edição.',
    bodyEn:'The jury awards, live performances and the announcement of the first names of the next edition.',
    program:[
      { time:'20:00', title:'Receção', titleEn:'Reception', note:'Tapete vermelho', noteEn:'Red carpet' },
      { time:'20:45', title:'Cerimónia', titleEn:'Ceremony', note:'Entrega de prémios', noteEn:'Awards' },
      { time:'21:45', title:'Festa', titleEn:'Party', note:'Encerramento', noteEn:'Closing' },
    ],
    guests:[ sp('deniro','Anfitrião','Host'), sp('whoopi','Apresentadora','Presenter'), sp('esposito','Júri','Jury') ],
    related:['e1','e4','e5'],
  },
];
const EVENTS_BY_ID = Object.fromEntries(EVENTS.map(e => [e.id, e]));

// ---- NEWS (full articles, keyed by id) ----------------------
const NEWS = [
  {
    id:'n1', cat:'nightlive', img:'uploads/news_highlight.png',
    kicker:'Opening Night',
    title:'Giancarlo Esposito abre o festival com uma masterclass sobre o ofício de contar histórias',
    titleEn:'Giancarlo Esposito opens the festival with a masterclass on the craft of storytelling',
    excerpt:'A masterclass de abertura traz à Culturgest uma das vozes mais marcantes do storytelling contemporâneo.',
    excerptEn:'The opening masterclass brings one of the most distinctive voices in contemporary storytelling to Culturgest.',
    date:'29 maio 2026', dateEn:'29 May 2026', readTime:'5 min de leitura', readTimeEn:'5 min read',
    author:'por Redação Tribeca', authorEn:'by Tribeca Editorial',
    dek:'A noite de abertura da edição europeia traz à Culturgest uma das vozes mais marcantes do storytelling contemporâneo — e promete dar o tom para uma semana inteira de cultura.',
    dekEn:'The opening night of the European edition brings one of the most distinctive voices in contemporary storytelling to Culturgest — and promises to set the tone for a whole week of culture.',
    external:{ label:'Ler a cobertura no SIC Notícias', labelEn:'Read the coverage on SIC Notícias', href:'#' },
    body:[
      { t:'p', x:'Há atores que interpretam personagens e há atores que constroem mundos. Giancarlo Esposito pertence, sem hesitação, ao segundo grupo.', xEn:'There are actors who play characters and actors who build worlds. Giancarlo Esposito belongs, without hesitation, to the second group.' },
      { t:'h2', x:'O ofício como disciplina', xEn:'The craft as a discipline' },
      { t:'p', x:'Para Esposito, representar não começa no guião nem termina no take final. Começa muito antes, na observação obsessiva do mundo.', xEn:'For Esposito, acting does not begin with the script nor end with the final take. It starts much earlier, in the obsessive observation of the world.' },
      { t:'quote', x:'Uma personagem não é uma máscara que se veste. É uma verdade que se descobre, plano a plano.', xEn:'A character is not a mask you put on. It is a truth you uncover, shot by shot.' },
      { t:'p', x:'A masterclass insere-se no pilar Night Live, mas dialoga diretamente com as secções Film e Talks.', xEn:'The masterclass sits within the Night Live strand, but speaks directly to the Film and Talks sections.' },
    ],
    relatedEvents:['e3','e1','e5'], relatedSpeakers:['esposito','nuno','whoopi','deniro'],
  },
  {
    id:'n2', cat:'film', img:'uploads/thumbnail_2.png',
    kicker:'Programme',
    title:'Cinco estreias que não pode perder', titleEn:"Five premieres you can't miss",
    excerpt:'Do thriller intimista ao documentário de arquivo: as sessões que vão esgotar primeiro.',
    excerptEn:'From the intimate thriller to the archive documentary: the sessions that will sell out first.',
    date:'27 maio 2026', dateEn:'27 May 2026', readTime:'4 min de leitura', readTimeEn:'4 min read',
    author:'por Redação Tribeca', authorEn:'by Tribeca Editorial',
    dek:'O programa de cinema desta edição é o mais ambicioso de sempre. Selecionámos cinco estreias que definem o tom de 2026.',
    dekEn:'This edition’s film programme is the most ambitious yet. We picked five premieres that define the tone of 2026.',
    external:null,
    body:[
      { t:'p', x:'A secção Film abre com The Last Reel, uma estreia europeia que celebra o cinema como espaço coletivo.', xEn:'The Film strand opens with The Last Reel, a European premiere that celebrates cinema as a collective space.' },
      { t:'h2', x:'Da memória ao futuro', xEn:'From memory to the future' },
      { t:'p', x:'Entre clássicos restaurados e novas vozes, o programa atravessa gerações sem nunca perder o foco na história.', xEn:'Between restored classics and new voices, the programme spans generations without ever losing focus on story.' },
    ],
    relatedEvents:['e1','e4','e9'], relatedSpeakers:['deniro','barker'],
  },
  {
    id:'n3', cat:'talks', img:'uploads/thumbnail.png',
    kicker:'On Stage',
    title:'A conversa que parou Lisboa', titleEn:'The talk that stopped Lisbon',
    excerpt:'Uma hora sobre voz e representação que deixou a plateia de pé.',
    excerptEn:'An hour on voice and representation that left the audience on its feet.',
    date:'25 maio 2026', dateEn:'25 May 2026', readTime:'3 min de leitura', readTimeEn:'3 min read',
    author:'por Redação Tribeca', authorEn:'by Tribeca Editorial',
    dek:'Whoopi Goldberg sobe ao Tivoli para uma conversa sobre humor, resistência e as histórias que recusou deixar por contar.',
    dekEn:'Whoopi Goldberg takes the Tivoli stage for a conversation on humour, resistance and the stories she refused to leave untold.',
    external:null,
    body:[
      { t:'p', x:'Poucas vozes atravessaram tantas formas — teatro, cinema, televisão — sem nunca baixar o tom.', xEn:'Few voices have crossed so many forms — theatre, cinema, television — without ever lowering their tone.' },
      { t:'p', x:'Em Vozes que ficam, a conversa torna-se um manifesto sobre quem tem direito a contar histórias.', xEn:'In Voices That Stay, the conversation becomes a manifesto on who gets to tell stories.' },
    ],
    relatedEvents:['e5','e3','e1'], relatedSpeakers:['whoopi','nuno'],
  },
  {
    id:'n4', cat:'awards', img:'uploads/thumbnail_7.png',
    kicker:'Awards',
    title:'Os nomes do júri 2026', titleEn:'The 2026 jury names',
    excerpt:'Realizadores, criadores e uma lenda: quem vai decidir os prémios deste ano.',
    excerptEn:'Directors, creators and a legend: who will decide this year’s awards.',
    date:'22 maio 2026', dateEn:'22 May 2026', readTime:'2 min de leitura', readTimeEn:'2 min read',
    author:'por Redação Tribeca', authorEn:'by Tribeca Editorial',
    dek:'O júri da edição de 2026 reúne nomes que atravessam cinema, indústria e cultura — com Robert De Niro à cabeça.',
    dekEn:'The 2026 jury brings together names spanning cinema, industry and culture — led by Robert De Niro.',
    external:null,
    body:[
      { t:'p', x:'A Gala de encerramento, no CCB, revela os vencedores escolhidos por um júri de exceção.', xEn:'The Closing Gala, at the CCB, reveals the winners chosen by an exceptional jury.' },
      { t:'p', x:'Mais do que premiar, o júri assinala as histórias que vão definir a próxima década.', xEn:'More than awarding, the jury signals the stories that will define the next decade.' },
    ],
    relatedEvents:['e9','e1','e4'], relatedSpeakers:['deniro','esposito','whoopi'],
  },
];
const NEWS_BY_ID = Object.fromEntries(NEWS.map(n => [n.id, n]));

// ---- TRIBECA OPEN AIR (open-air film series, modelled on EVENTS) ----
// All cards cat:'film' (pink FILM badge). Real PT film one-sheets in uploads/.
// Card line = `line` lead + greyed `lineTail` (guests). `rows` feeds the
// detail modal (Tema / Moderação / Convidados / …). Ticket URLs simulated ('#').
const OPEN_AIR = [
  {
    id:'oa1', cat:'film', img:'uploads/eleanor.jpg', modalImg:'uploads/eleanor-wide.jpg',
    title:'Eleanor the Great', dir:'Scarlett Johansson',
    kicker:'Sessão de Inauguração', kickerEn:'Opening Night',
    venue:'Loulé', date:'10 Ago 2026', dateEn:'10 Aug 2026',
    line:'Como se conta uma história?', lineEn:'How do you tell a story?',
    lineTail:'· com Margarida Vila Nova, Cláudia Vieira e Ricardo Costa',
    lineTailEn:'· with Margarida Vila Nova, Cláudia Vieira and Ricardo Costa',
    ticketUrl:'#',
    rows:[
      { k:'Tema', kEn:'Theme',
        v:'Como se conta uma história? Do jornalismo à ficção, e o combate à desinformação.',
        vEn:'How do you tell a story? From journalism to fiction, and the fight against disinformation.' },
      { k:'Moderação', kEn:'Moderation', v:'Clara de Sousa / Cristiana Reis (SIC)' },
      { k:'Convidados Storymakers', kEn:'Storymakers guests', v:'Margarida Vila Nova, Cláudia Vieira, Ricardo Costa' },
      { k:'Boas-vindas do circuito', kEn:'Circuit welcome',
        v:'Mónica Serrano (Diretora de Marketing, Grupo Impresa)',
        vEn:'Mónica Serrano (Marketing Director, Grupo Impresa)' },
    ],
  },
  {
    id:'oa2', cat:'film', img:'uploads/nuremberg.jpg', modalImg:'uploads/nuremberg-wide.jpg',
    title:'Nuremberga', titleEn:'Nuremberg', dir:'James Vanderbilt',
    kicker:'Sessão de Inauguração', kickerEn:'Opening Night',
    venue:'Sintra', date:'24 Ago 2026', dateEn:'24 Aug 2026',
    line:'Histórias que se repetem e o que aprendemos com elas', lineEn:'Stories that repeat and what we learn from them',
    lineTail:'· Podcast: Lei da Paridade', lineTailEn:'· Podcast: Lei da Paridade',
    ticketUrl:'#',
    rows:[
      { k:'Tema', kEn:'Theme',
        v:'Histórias que se repetem e o que aprendemos com elas.',
        vEn:'Stories that repeat and what we learn from them.' },
      { k:'Podcast', kEn:'Podcast', v:'Lei da Paridade — Adriana, Maria, Leonor (30–45 min)' },
    ],
  },
  {
    id:'oa3', cat:'film', img:'uploads/bugonia.jpg', modalImg:'uploads/bugonia-wide.jpg',
    title:'Bugonia', dir:'Yorgos Lanthimos',
    venue:'Maia', date:'Set · data a confirmar', dateEn:'Sep · TBD',
    line:'Portugal como palco para o cinema internacional', lineEn:'Portugal as a stage for international cinema',
    lineTail:'· com José Condessa e Maria de Medeiros', lineTailEn:'· with José Condessa and Maria de Medeiros',
    ticketUrl:'#',
    rows:[
      { k:'Tema', kEn:'Theme',
        v:'Portugal como palco para o cinema internacional.',
        vEn:'Portugal as a stage for international cinema.' },
      { k:'Moderação', kEn:'Moderation', v:'Graça Costa Pereira' },
      { k:'Convidados Storymakers', kEn:'Storymakers guests', v:'José Condessa, Maria de Medeiros' },
    ],
  },
  {
    id:'oa4', cat:'film', img:'uploads/eleanor.jpg', modalImg:'uploads/eleanor-wide.jpg',
    title:'Eleanor the Great', dir:'Scarlett Johansson',
    venue:'Barcelos', date:'Set · data a confirmar', dateEn:'Sep · TBD',
    line:'O poder das histórias que atravessam gerações', lineEn:'The power of stories that cross generations',
    lineTail:'· convidados a anunciar', lineTailEn:'· guests to be announced',
    ticketUrl:'#',
    rows:[
      { k:'Tema', kEn:'Theme',
        v:'O poder das histórias que atravessam gerações.',
        vEn:'The power of stories that cross generations.' },
      { k:'Convidados', kEn:'Guests', v:'A anunciar', vEn:'To be announced' },
      { k:'Nota', kEn:'Note', v:'Programação simulada — a confirmar.', vEn:'Simulated programming — to be confirmed.' },
    ],
  },
];

// ---- homepage-derived lists ---------------------------------
const NEWS_HIGHLIGHT = NEWS[0];
const SCHEDULE = [
  { time:'21:00', id:'e1', title:'The Last Reel',   titleEn:'The Last Reel',   venue:'Cinema São Jorge', status:'LIVE', color:'var(--pink)' },
  { time:'23:30', id:'e2', title:'Noite no Chiado', titleEn:'Night in Chiado', venue:'LX Factory',       status:'SOON', color:'var(--purple)' },
  { time:'00:30', id:'e8', title:'After Hours',     titleEn:'After Hours',     venue:'Lux Frágil',       status:'SOON', color:'var(--purple)' },
];
const FEED = [
  'uploads/thumbnail_4.png','uploads/thumbnail_6.png','uploads/thumbnail.png',
  'uploads/thumbnail_5.png','uploads/thumbnail_3.png','uploads/thumbnail_7.png',
];

window.STORE = { EVENTS, EVENTS_BY_ID, NEWS, NEWS_BY_ID, OPEN_AIR, SPEAKERS };
Object.assign(window, { EVENTS, EVENTS_BY_ID, NEWS, NEWS_BY_ID, OPEN_AIR, NEWS_HIGHLIGHT, SCHEDULE, FEED, SPEAKERS });
