ui polish pass: scroll-driven effects (card reveal, header shadow, reading progress), nav underline-grow, card meta icons, og:image svg fallback, apple-touch-icon+favicon, hero 472->180KB + preload, article cover CLS guard, ::selection, per-article lang, robots noindex (demo); article: db-cms comparison diagram, 6-year pros/cons, reuse section

This commit is contained in:
2026-07-28 20:57:51 +02:00
parent 54de9d3ee9
commit bbbb090cce
13 changed files with 236 additions and 15 deletions
+10 -3
View File
@@ -2,12 +2,14 @@
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 } = Astro.props;
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);
const ogImage = new URL(image || '/brand/og-card.jpg', 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).
@@ -24,7 +26,7 @@ const links = [
];
---
<!doctype html>
<html lang="en">
<html lang={lang}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -42,6 +44,11 @@ const links = [
<link rel="alternate" type="application/rss+xml" title="CTAO Science Portal — News" href={new URL('/rss.xml', site)} />
<link rel="sitemap" href="/sitemap.xml" />
<link rel="icon" href="/brand/CTAO_Logo_positive.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<meta name="theme-color" content="#00004a" />
{/* The home hero photo is a CSS background, which browsers discover late —
preloading it moves the page's LCP element to the front of the queue. */}
{path === '/' && <link rel="preload" as="image" href="/brand/hero.jpg" fetchpriority="high" />}
{/* Brand typography (BRAND D.3): Inter (body) + Space Grotesk (headlines),
self-hosted latin woff2 (variable) — @font-face lives in global.css. */}
{/* Both brand fonts ship inlined in the render-blocking stylesheet —