--- import '../styles/global.css'; // `ambient` opts a page into the whole-page drifting brand wash (home only — see DESIGN.md) // `type`/`image` feed the social meta: articles pass type="article" + their cover. const { title = 'CTAO Science Portal', description = 'CTAO Science Portal — demo', ambient = false, type = 'website', image, lang = 'en' } = Astro.props; // Absolute URLs for canonical/OG/RSS (head pattern from the official Astro blog // template). `site` is a placeholder domain until the portal has a real one. const site = Astro.site ?? new URL('https://portal.ctao.org'); const canonical = new URL(Astro.url.pathname, site); // SVG covers never reach og:image — link-preview crawlers (Slack/Teams/ // LinkedIn) don't render SVG, so those articles fall back to the brand card. const ogImage = new URL(image && !image.endsWith('.svg') ? image : '/brand/og-card.jpg', site); const path = Astro.url.pathname; const isActive = (href) => (href === '/' ? path === '/' : path.startsWith(href)); // Navigation = services from the Science Portal spec (REQUIREMENTS.md §2/§5). // Order: serial-position effect (NN/g) — News (universal entry) first, Support // (help convention) last; Data/Proposals by task frequency; Dashboard is the // personal area, placed late next to the Sign-in cluster. External systems // built by other teams are links out, clearly marked. const links = [ { href: '/news', label: 'News' }, { href: 'https://padc-ctao-data-explorer.obspm.fr/', label: 'Data', ext: true }, { href: '/proposals', label: 'Proposals' }, { href: '/dashboard', label: 'Dashboard' }, { href: '/support', label: 'Support' }, ]; ---