Últimas publicações
Cobertura recente organizada para leitura rápida, sem perder contexto editorial.
Arquivo editorial
Todas as matérias disponíveis no portal.
Busca
${tr('noSearch')}
${tr('trySearch')}
`; } else { empty.classList.add('hidden'); } markNav(''); activatePage('search'); updateMetaStatic('search'); } // ── Navigation helpers ───────────────────────────────────────────────────── function activatePage(page) { currentPage = page; document.querySelectorAll('.page').forEach(el => el.classList.remove('active')); const map = { home:'pageHome', article:'pageArticle', archive:'pageArchive', about:'pageAbout', standards:'pageStandards', search:'pageSearch' }; const el = document.getElementById(map[page]); if (el) el.classList.add('active'); window.scrollTo({ top: 0, behavior: 'smooth' }); } function markNav(which) { ['navHome','navArchive','navAbout','navStandards'].forEach(id => document.getElementById(id).classList.remove('on')); const map = { home:'navHome', archive:'navArchive', about:'navAbout', standards:'navStandards' }; if (map[which]) document.getElementById(map[which]).classList.add('on'); } function setCategory(category, btn) { currentCategory = category || 'all'; if (btn) syncCategoryButtons(btn); if (currentPage === 'archive') renderArchive(); else renderHome(); } function syncCategoryButtons(activeBtn) { document.querySelectorAll('.cat-pill').forEach(btn => btn.classList.remove('on')); if (activeBtn) { activeBtn.classList.add('on'); return; } const target = document.querySelector(`.cat-pill[data-cat="${CSS.escape(currentCategory)}"]`) || document.querySelector('.cat-pill[data-cat="all"]'); if (target) target.classList.add('on'); } function safeReplaceState(url) { try { history.replaceState({}, '', url); } catch (err) { console.warn('History replaceState falhou:', err); } } function safePushState(url) { try { history.pushState({}, '', url); } catch (err) { console.warn('History pushState falhou:', err); } } function openPage(page) { if (page === 'archive') { safeReplaceState(pageUrl('archive')); renderArchive(); } else if (page === 'about') { safeReplaceState(pageUrl('about')); renderAbout(); } else if (page === 'standards') { safeReplaceState(pageUrl('standards')); renderStandards(); } else goHome(); } function goHome() { safeReplaceState(pageUrl('home')); renderHome(); } function openArticle(slug) { const post = DB.find(item => item.slug === slug); if (post) safePushState(getURLForArticle(post)); renderArticle(slug); } function handleSearchInput(value) { clearTimeout(searchTimer); if (!value.trim()) { if (currentPage === 'search') goHome(); return; } searchTimer = setTimeout(() => renderSearch(value.trim()), 220); } function syncCurrentRouteUrl() { if (currentPage === 'search') return; if (currentPage === 'article' && currentArticleSlug) { const post = DB.find(item => item.slug === currentArticleSlug); if (post) { safeReplaceState(getURLForArticle(post)); return; } } if (currentPage === 'archive') { safeReplaceState(pageUrl('archive')); return; } if (currentPage === 'about') { safeReplaceState(pageUrl('about')); return; } if (currentPage === 'standards') { safeReplaceState(pageUrl('standards')); return; } safeReplaceState(pageUrl('home')); } function setLanguage(lang) { currentLang = lang === 'en' ? 'en' : 'pt'; localStorage.setItem('cw_lang', currentLang); applyUIStrings(); rerenderCurrentView(); syncCurrentRouteUrl(); } function applyUIStrings() { document.documentElement.lang = currentLang === 'en' ? 'en-US' : 'pt-BR'; const ids = { logoSub:'logoSub', navHome:'home', navArchive:'archive', navAbout:'about', navStandards:'standards', methodBtn:'methodology', adsBtn:'advertise', updateBtnLabel:'update', tickerBadge:'ticker', latestSectionTitle:'latestTitle', latestSectionKicker:'latestKicker', archiveLinkTop:'archiveLink', trendingWidgetTitle:'trending', latestUpdatesTitle:'latestUpdatesTitle', sourceMixTitle:'sourceMixTitle', quickLinksTitle:'quickLinksTitle', archivePicksTitle:'archivePicksTitle', archiveTitle:'archiveTitle', archiveKicker:'archiveKicker', searchTitle:'searchTitle', footerDescription:'footerDescription', footerNavTitle:'footerNavTitle', footerAdvertise:'advertise', footerMediaKit:'mediaKit', footerSourcesTitle:'footerSourcesTitle', footerFeed:'footerFeed', footerPrivacy:'privacy', footerTerms:'terms', footerSitemap:'footerSitemap', footerCorrections:'footerCorrections', footerBottomLeft:'footerBottomLeft', footerBottomCenter:'footerBottomCenter', newsletterTitle:'newsletterTitle', newsletterDescription:'newsletterDescription', newsletterButton:'newsletterButton', newsletterNote:'newsletterNote', newsletterButton:'newsletterButton' }; for (const [id, key] of Object.entries(ids)) { const el = document.getElementById(id); if (el) el.textContent = tr(key); } document.getElementById('topbarCopy').innerHTML = tr('topbarCopy'); const si = document.getElementById('searchInput'); if (si) si.placeholder = tr('searchPlaceholder'); const nl = document.getElementById('newsletterLabel'); if (nl) nl.textContent = tr('newsletterLabel'); const ne = document.getElementById('newsletterEmail'); if (ne) ne.placeholder = tr('newsletterPlaceholder'); syncAuxiliaryLinks(); const cookieTitle = document.getElementById('cookieTitle'); if (cookieTitle) cookieTitle.textContent = tr('cookieTitle'); const cookieLink = document.getElementById('cookiePolicyLink'); if (cookieLink) cookieLink.textContent = tr('cookiePolicy'); const cookieText = document.getElementById('cookieText'); if (cookieText) { const linkHref = auxiliaryPageHref('privacy'); cookieText.innerHTML = `${tr('cookieText').replace(tr('cookiePolicy'), `${tr('cookiePolicy')}`)}`; } const cookieBanner = document.getElementById('cookieBanner'); if (cookieBanner) cookieBanner.setAttribute('aria-label', tr('cookieAria')); const denyBtn = document.getElementById('cookieDenyBtn'); if (denyBtn) denyBtn.textContent = tr('cookieDeny'); const analyticsBtn = document.getElementById('cookieAnalyticsBtn'); if (analyticsBtn) analyticsBtn.textContent = tr('cookieAnalytics'); const acceptBtn = document.getElementById('cookieAcceptBtn'); if (acceptBtn) acceptBtn.textContent = tr('cookieAccept'); document.querySelectorAll('.cat-pill').forEach(btn => { const cat = btn.dataset.cat; btn.textContent = cat === 'all' ? tr('allCategories') : prettyCategory(cat); }); document.getElementById('langPt').classList.toggle('on', currentLang==='pt'); document.getElementById('langEn').classList.toggle('on', currentLang==='en'); updateRigSyncBannerLanguage(); updateLastUpdatedLabel(); } const FLOAT_AD_CONFIG = { enabled: false, dismissKey: 'cw_floating_ad_dismissed', href: '#', target: '_blank', rel: 'noopener sponsored', pt: { eyebrow: 'Espaço patrocinado', title: 'Sua marca aqui', text: 'Este espaço está pronto para receber o link e a mensagem de um patrocinador.', cta: 'Anunciar', close: 'Fechar anúncio', aria: 'Espaço patrocinado' }, en: { eyebrow: 'Sponsored slot', title: 'Your brand here', text: 'This slot is ready for a sponsor link and message whenever you want to activate it.', cta: 'Advertise', close: 'Close ad', aria: 'Sponsored slot' } }; function updateRigSyncBannerLanguage() { const config = FLOAT_AD_CONFIG; const copy = config[currentLang] || config.pt; const eyebrow = document.getElementById('rigsyncBannerEyebrow'); const title = document.getElementById('rigsyncBannerTitle'); const text = document.getElementById('rigsyncBannerText'); const cta = document.getElementById('rigsyncBannerCta'); const close = document.getElementById('rigsyncBannerClose'); const banner = document.getElementById('rigsyncBanner'); const logo = banner ? banner.querySelector('.rigsync-float__logo') : null; if (eyebrow) eyebrow.textContent = copy.eyebrow; if (title) title.textContent = copy.title; if (text) text.textContent = copy.text; if (cta) { cta.textContent = copy.cta; cta.href = config.href || '#'; cta.target = config.target || '_blank'; cta.rel = config.rel || 'noopener sponsored'; cta.setAttribute('aria-label', copy.cta); } if (logo) { logo.href = config.href || '#'; logo.target = config.target || '_blank'; logo.rel = config.rel || 'noopener sponsored'; logo.setAttribute('aria-label', copy.aria); } if (close) close.setAttribute('aria-label', copy.close); if (banner) banner.setAttribute('aria-label', copy.aria); } function syncRigSyncBannerOffset() { const banner = document.getElementById('rigsyncBanner'); if (!banner) return; const cookie = document.getElementById('cookieBanner'); const visible = cookie && cookie.classList.contains('show'); const base = window.innerWidth <= 780 ? 12 : 18; const extra = visible ? cookie.offsetHeight + 16 : 0; banner.style.bottom = `${base + extra}px`; } function initRigSyncBanner() { const banner = document.getElementById('rigsyncBanner'); const close = document.getElementById('rigsyncBannerClose'); const config = FLOAT_AD_CONFIG; if (!banner || !close) return; if (!config.enabled || !config.href || config.href === '#') { banner.remove(); return; } try { if (localStorage.getItem(config.dismissKey) === '1') { banner.remove(); return; } } catch (e) {} updateRigSyncBannerLanguage(); syncRigSyncBannerOffset(); close.addEventListener('click', () => { banner.classList.remove('show'); window.setTimeout(() => banner.remove(), 220); try { localStorage.setItem(config.dismissKey, '1'); } catch (e) {} }); window.addEventListener('resize', syncRigSyncBannerOffset, { passive: true }); const cookie = document.getElementById('cookieBanner'); if (cookie && typeof MutationObserver !== 'undefined') { const observer = new MutationObserver(syncRigSyncBannerOffset); observer.observe(cookie, { attributes: true, attributeFilter: ['class', 'style'] }); } window.setTimeout(() => banner.classList.add('show'), 850); } function updateLastUpdatedLabel() { const latest = DB[0]; const stamp = latest ? `${currentLang==='en'?(latest.date_en||latest.date):(latest.date_pt||latest.date)} · ${currentLang==='en'?(latest.time_en||latest.time):(latest.time_pt||latest.time)}` : tr('latestFeed'); const el = document.getElementById('lastUpdatedLabel'); if (el) el.textContent = `${tr('lastUpdatedPrefix')} ${stamp}`; } function showToast(message) { const toast = document.getElementById('toast'); toast.textContent = message; toast.classList.add('show'); clearTimeout(toastTimer); toastTimer = setTimeout(() => toast.classList.remove('show'), 3200); } function refreshFeed() { const btn = document.getElementById('updateBtn'); bumpHeroRotationSeed(); btn.classList.add('loading'); btn.disabled = true; fetch(`posts.js?cb=${Date.now()}`, { cache:'no-store' }) .then(resp => { if (!resp.ok) throw new Error('fetch failed'); return resp.text(); }) .then(js => { const sandboxWindow = {}; Function('window', js + '; return window.postsData;')(sandboxWindow); if (Array.isArray(sandboxWindow.postsData) && sandboxWindow.postsData.length) { DB = mergePostCollections(sandboxWindow.postsData, DB); frontLayoutCache.clear(); persistArchiveCache(); updateLastUpdatedLabel(); rerenderCurrentView(); showToast(tr('updateDone')); } else { rerenderCurrentView(); showToast(tr('updateDone')); } }) .catch(() => { rerenderCurrentView(); showToast(tr('updateFail')); }) .finally(() => { btn.classList.remove('loading'); btn.disabled = false; }); } function copyArticleLink() { const post = DB.find(item => item.slug === currentArticleSlug); const url = post ? getShareURLForArticle(post) : location.href; navigator.clipboard.writeText(url).then(() => showToast(tr('copied'))).catch(() => showToast(url)); } async function shareCurrentArticle() { const post = DB.find(item => item.slug === currentArticleSlug); const url = post ? getShareURLForArticle(post) : location.href; const title = post ? textFor(post, 'title') : document.title; const textBody = post ? stripHtml(textFor(post, 'excerpt') || textFor(post, 'sub') || '') : ''; const shareData = { title, text: textBody, url }; if (navigator.share) { try { await navigator.share(shareData); return; } catch (err) { if (err && err.name === 'AbortError') return; } } navigator.clipboard.writeText(url) .then(() => showToast(tr('shareFallback'))) .catch(() => showToast(url)); } function handleNewsletterSubmit(event) { event.preventDefault(); const input = document.getElementById('newsletterEmail'); const email = input.value.trim(); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { showToast(tr('newsletterInvalid')); input.focus(); return; } localStorage.setItem('cw_newsletter_email', email); input.value = ''; showToast(tr('newsletterSuccess')); } function loadSavedNewsletterEmail() { const saved = localStorage.getItem('cw_newsletter_email'); if (saved) { const el = document.getElementById('newsletterEmail'); if (el) el.value = saved; } } const CONSENT_KEY = 'cw_cookie_consent'; /* Mapeia os 3 estados para os sinais do Consent Mode v2. 'full' → analytics + anúncios personalizados 'analytics' → só analytics, anúncios não-personalizados 'denied' → tudo desligado */ function _consentSignals(mode) { const full = mode === 'full'; const analytics = mode === 'full' || mode === 'analytics'; return { analytics_storage: analytics ? 'granted' : 'denied', ad_storage: full ? 'granted' : 'denied', ad_user_data: full ? 'granted' : 'denied', ad_personalization: full ? 'granted' : 'denied' }; } function setCookieConsent(mode) { // mode: 'full' | 'analytics' | 'denied' try { localStorage.setItem(CONSENT_KEY, mode); } catch (e) {} if (typeof gtag === 'function') gtag('consent', 'update', _consentSignals(mode)); const banner = document.getElementById('cookieBanner'); if (banner) banner.classList.remove('show'); } function initCookieBanner() { let saved = null; try { saved = localStorage.getItem(CONSENT_KEY); } catch (e) {} const banner = document.getElementById('cookieBanner'); if (!banner) return; const validStates = ['full', 'analytics', 'denied', 'granted']; // 'granted' = estado legado, tratar como 'analytics' if (validStates.includes(saved)) { const normalized = saved === 'granted' ? 'analytics' : saved; if (typeof gtag === 'function') gtag('consent', 'update', _consentSignals(normalized)); // Migra silenciosamente o valor legado if (saved === 'granted') { try { localStorage.setItem(CONSENT_KEY, 'analytics'); } catch (e) {} } banner.classList.remove('show'); return; } banner.classList.add('show'); } // ── SEO / Meta ───────────────────────────────────────────────────────────── function updateMetaHome() { const title = currentLang==='en' ? SITE.homeTitleEn : SITE.homeTitlePt; const description = currentLang==='en' ? SITE.homeDescriptionEn : SITE.homeDescriptionPt; updateMetaCommon(title, description, canonicalPageUrl('home'), IMG.pillars, null, { robots: 'index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1', newsKeywords: 'astronomia, astrofísica, cosmologia, ciência, espaço', alternatePt: withLanguageParam(SITE.canonicalBaseUrl, 'pt'), alternateEn: withLanguageParam(SITE.canonicalBaseUrl, 'en'), alternateDefault: withLanguageParam(SITE.canonicalBaseUrl, 'pt'), locale: currentLang === 'en' ? 'en_US' : 'pt_BR', localeAlternate: currentLang === 'en' ? 'pt_BR' : 'en_US', imageAlt: 'Cosmos Week', author: currentLang === 'en' ? 'Cosmos Week Editorial Desk' : 'Redação do Cosmos Week', ogType: 'website' }); } function updateMetaStatic(page) { const titles = { about: currentLang==='en'?'About Cosmos Week':'Sobre o Cosmos Week', archive: currentLang==='en'?'Editorial archive':'Arquivo editorial', standards: currentLang==='en'?'Editorial standards':'Padrões editoriais', search: currentLang==='en'?'Search':'Busca' }; const descriptions = { about: currentLang==='en'?'About the editorial ambition and scope of Cosmos Week.':'Sobre a ambição editorial e o escopo do Cosmos Week.', archive: currentLang==='en'?'The complete archive of stories currently available.':'O arquivo completo das matérias disponíveis.', standards: currentLang==='en'?'Methodology, source labeling and editorial safeguards.':'Metodologia, rotulagem de fonte e salvaguardas editoriais.', search: currentLang==='en'?'Search results inside Cosmos Week.':'Resultados de busca dentro do Cosmos Week.' }; updateMetaCommon(`${titles[page]} — ${SITE.title}`, descriptions[page], canonicalPageUrl(page), IMG.pillars, null, { robots: page === 'search' ? 'noindex,follow' : 'index,follow', newsKeywords: 'Notícias Científicas, astronomia, astrofísica, cosmologia', alternatePt: withLanguageParam(canonicalPageUrl(page), 'pt'), alternateEn: withLanguageParam(canonicalPageUrl(page), 'en'), alternateDefault: withLanguageParam(canonicalPageUrl(page), 'pt'), locale: currentLang === 'en' ? 'en_US' : 'pt_BR', localeAlternate: currentLang === 'en' ? 'pt_BR' : 'en_US', imageAlt: titles[page], author: currentLang === 'en' ? 'Cosmos Week Editorial Desk' : 'Redação do Cosmos Week', ogType: 'website' }); } function updateMetaArticle(post) { const title = `${textFor(post,'title')} — ${SITE.title}`; const description = textFor(post,'excerpt') || textFor(post,'sub') || textFor(post,'title'); const url = getCanonicalURLForArticle(post); const alternates = articleAlternateUrls(post); const keywords = keywordListFor(post); const langCode = currentLang === 'en' ? 'en-US' : 'pt-BR'; const authorName = currentLang === 'en' ? 'Cosmos Week Editorial Desk' : 'Redação do Cosmos Week'; const image = primaryImage(post); const jsonLd = [ { '@context':'https://schema.org','@type':'NewsMediaOrganization', '@id':`${SITE.canonicalBaseUrl}#organization`, name:SITE.title, url:SITE.canonicalBaseUrl, logo:{'@type':'ImageObject',url:IMG.pillars} }, { '@context':'https://schema.org','@type':'BreadcrumbList', itemListElement:[ {'@type':'ListItem',position:1,name:currentLang==='en'?'Home':'Início',item:withLanguageParam(SITE.canonicalBaseUrl, currentLang)}, {'@type':'ListItem',position:2,name:prettyCategory(post.cat),item:withLanguageParam(SITE.canonicalBaseUrl, currentLang)}, {'@type':'ListItem',position:3,name:textFor(post,'title'),item:url} ]}, { '@context':'https://schema.org','@type':'WebPage', '@id':url, url, name:title, description, inLanguage:langCode, isPartOf:{'@type':'WebSite',name:SITE.title,url:withLanguageParam(SITE.canonicalBaseUrl, currentLang)}, primaryImageOfPage:{'@type':'ImageObject',url:image}, hasPart:[{'@type':'WebPage',url:currentLang==='en'?alternates.pt:alternates.en,inLanguage:currentLang==='en'?'pt-BR':'en-US'}] }, { '@context':'https://schema.org','@type':'NewsArticle', headline:textFor(post,'title'), description, image:[image], thumbnailUrl:image, datePublished:post.publishedIso, dateModified:post.lastModifiedIso||post.publishedIso, inLanguage:langCode, isAccessibleForFree:true, articleSection:prettyCategory(post.cat), keywords, author:[{'@type':'Organization',name:authorName}], publisher:{'@type':'Organization',name:SITE.title,logo:{'@type':'ImageObject',url:IMG.pillars}}, mainEntityOfPage:{'@type':'WebPage','@id':url}, about:keywords.map(k => ({'@type':'Thing',name:k})), isBasedOn: post.srcUrl || undefined, citation: post.srcUrl ? [{'@type':'CreativeWork', name:post.source || post.srcUrl, url:post.srcUrl}] : undefined } ]; updateMetaCommon(title, description, url, image, jsonLd, { robots: 'index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1', newsKeywords: keywords.join(', '), published: post.publishedIso, modified: post.lastModifiedIso || post.publishedIso, alternatePt: alternates.pt, alternateEn: alternates.en, alternateDefault: alternates.xDefault, locale: currentLang === 'en' ? 'en_US' : 'pt_BR', localeAlternate: currentLang === 'en' ? 'pt_BR' : 'en_US', imageAlt: textFor(post,'title'), author: authorName, section: prettyCategory(post.cat), ogType: 'article' }); } function updateMetaCommon(title, description, url, image, articleJsonLd, options = {}) { document.title = title; document.querySelector('meta[name="description"]').setAttribute('content', description); document.querySelector('meta[property="og:title"]').setAttribute('content', title); document.querySelector('meta[property="og:description"]').setAttribute('content', description); document.querySelector('meta[property="og:type"]').setAttribute('content', options.ogType || 'website'); document.querySelector('meta[property="og:url"]').setAttribute('content', url); document.querySelector('meta[property="og:image"]').setAttribute('content', image); document.getElementById('ogImageAltMeta').setAttribute('content', options.imageAlt || title); document.getElementById('ogLocaleMeta').setAttribute('content', options.locale || 'pt_BR'); document.getElementById('ogLocaleAlternateMeta').setAttribute('content', options.localeAlternate || 'en_US'); document.querySelector('meta[name="twitter:title"]').setAttribute('content', title); document.querySelector('meta[name="twitter:description"]').setAttribute('content', description); document.querySelector('meta[name="twitter:image"]').setAttribute('content', image); document.getElementById('twitterImageAltMeta').setAttribute('content', options.imageAlt || title); document.getElementById('authorMeta').setAttribute('content', options.author || (currentLang === 'en' ? 'Cosmos Week Editorial Desk' : 'Redação do Cosmos Week')); document.getElementById('canonicalLink').setAttribute('href', url); document.getElementById('alternatePtLink').setAttribute('href', options.alternatePt || withLanguageParam(url, 'pt')); document.getElementById('alternateEnLink').setAttribute('href', options.alternateEn || withLanguageParam(url, 'en')); document.getElementById('alternateDefaultLink').setAttribute('href', options.alternateDefault || withLanguageParam(url, 'pt')); document.getElementById('robotsMeta').setAttribute('content', options.robots||'index,follow'); document.getElementById('newsKeywordsMeta').setAttribute('content', options.newsKeywords||'astronomia, ciência'); document.getElementById('articlePublishedMeta').setAttribute('content', options.published||''); document.getElementById('articleModifiedMeta').setAttribute('content', options.modified||options.published||''); document.getElementById('articleSectionMeta').setAttribute('content', options.section || ''); document.getElementById('siteJsonLd').textContent = JSON.stringify(articleJsonLd || { '@context':'https://schema.org','@type':'WebSite', name:SITE.title, url:withLanguageParam(SITE.canonicalBaseUrl, currentLang), description, inLanguage: currentLang === 'en' ? 'en-US' : 'pt-BR' }); } function rerenderCurrentView() { if (currentPage==='article' && currentArticleSlug) renderArticle(currentArticleSlug); else if (currentPage==='archive') renderArchive(); else if (currentPage==='about') renderAbout(); else if (currentPage==='standards') renderStandards(); else if (currentPage==='search') { const q = document.getElementById('searchInput').value.trim(); if (q) renderSearch(q); else renderHome(); } else renderHome(); } function parseRoute() { const params = new URLSearchParams(window.location.search); const article = params.get('article'); const page = params.get('page'); const path = window.location.pathname || ''; const pathMatchPt = path.match(/^\/noticia\/([^\/]+)\/?$/i); const pathMatchEn = path.match(/^\/en\/news\/([^\/]+)\/?$/i); const articleFromPath = pathMatchEn ? decodeURIComponent(pathMatchEn[1]) : (pathMatchPt ? decodeURIComponent(pathMatchPt[1]) : ''); if ((params.get('lang') || '').toLowerCase() === 'en' || pathMatchEn) currentLang = 'en'; if ((params.get('lang') || '').toLowerCase() === 'pt' || pathMatchPt) currentLang = 'pt'; if (article) { renderArticle(article); return; } if (articleFromPath) { renderArticle(articleFromPath); return; } if (page==='arquivo') { renderArchive(); return; } if (page==='sobre') { renderAbout(); return; } if (page==='padroes') { renderStandards(); return; } renderHome(); } // Reading progress window.addEventListener('scroll', () => { const max = document.documentElement.scrollHeight - window.innerHeight; const ratio = max > 0 ? (window.scrollY / max) * 100 : 0; document.getElementById('readingProgress').style.width = `${ratio}%`; }, { passive: true }); window.addEventListener('popstate', parseRoute); document.addEventListener('DOMContentLoaded', () => { applyUIStrings(); loadSavedNewsletterEmail(); initCookieBanner(); initRigSyncBanner(); persistArchiveCache(); parseRoute(); });