em dashes out of skeleton copy (titles use ' - ', prose reworded); split hardening after review: poll errors name the failing repo, failed release is not retried until a new commit, link-content checks all three dirs, editor write-access note, two-repo unit descriptions and comments

This commit is contained in:
2026-09-03 19:41:56 +02:00
parent 13f945fbf3
commit 751fd0ec79
21 changed files with 54 additions and 42 deletions
+3 -2
View File
@@ -14,8 +14,9 @@ const news = defineCollection({
date: z.coerce.date(),
category: z.string().default('news'),
author: z.string().default('CTAO'),
// Public-path string, e.g. "/uploads/foo.jpg" — Sveltia uploads media to
// public/uploads, which Astro's image() helper can't validate (src/ only).
// Public-path string, e.g. "/uploads/foo.jpg" — media lives in the
// content repo's uploads/, overlaid to public/uploads at build time,
// which Astro's image() helper can't validate (src/ only).
cover: z.string().optional(),
// BCP-47 tag when an article is not in English (e.g. "pl") — set as lang
// on the <article> element so screen readers pick the right voice.
+5 -5
View File
@@ -2,7 +2,7 @@
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 } = Astro.props;
// Absolute URLs for canonical/OG/RSS (head pattern from the official Astro
// blog template). `site` comes from astro.config.mjs and is always set.
const site = Astro.site;
@@ -43,7 +43,7 @@ const links = [
<meta property="og:url" content={canonical} />
<meta property="og:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
<link rel="alternate" type="application/rss+xml" title="CTAO Science Portal — News" href={new URL('/rss.xml', site)} />
<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" />
@@ -59,7 +59,7 @@ const links = [
<a class="skip" href="#main">Skip to content</a>
<header class="site-header">
<div class="container nav">
<a class="brand" href="/" aria-label="CTAO Science Portal — home">
<a class="brand" href="/" aria-label="CTAO Science Portal, home">
<img src="/brand/AAFF_CTAO_Logo_RGB_Monochrome-negative.svg" alt="CTAO" />
<span class="brand-sub">Science&nbsp;Portal</span>
</a>
@@ -164,7 +164,7 @@ const links = [
<div class="container">
<div class="foot-top">
<img src="/brand/AAFF_CTAO_Logo_RGB_Monochrome-negative.svg" alt="CTAO" />
<p>CTAO Science Portal — demo by Cyfronet (SUSS-PORT team).</p>
<p>CTAO Science Portal demo by Cyfronet (SUSS-PORT team).</p>
</div>
{/* Order: action/utility first, legal middle, meta last (GOV.UK/NN-g
footer anatomy). Spec §3.3.1 requires the five items, not an order. */}
@@ -183,7 +183,7 @@ const links = [
{/* The real brand flash — path taken from the official logo SVG (BRAND D.4).
Sole decorative accent in this view; static by design. */}
<svg class="flash" viewBox="85.3 15 15 15" aria-hidden="true"><path fill="currentColor" d="M94.7,23.8c1-1.4,3.3-2.1,5.2-2.7c-2,0.1-4.4,0.3-5.8-0.6c-1.4-1-2.1-3.3-2.7-5.2c0.1,2,0.3,4.4-0.6,5.8c-1,1.4-3.3,2.1-5.2,2.7c2-0.1,4.4-0.3,5.8,0.6c1.4,1,2.1,3.3,2.7,5.2C93.9,27.6,93.7,25.2,94.7,23.8z"/></svg>
<span>© 2026 CTAO — demonstration, not an official service.</span>
<span>© 2026 CTAO. Demonstration, not an official service.</span>
</div>
</div>
</footer>
+3 -3
View File
@@ -1,7 +1,7 @@
---
import Base from '../layouts/Base.astro';
---
<Base title="CTAO Science Portal — Page not found" description="This page does not exist">
<Base title="CTAO Science Portal - Page not found" description="This page does not exist">
{/* Document archetype (DESIGN.md): the document IS the page — h1, one line,
recovery links, and a real GET search form as the way forward. */}
<div class="container article-layout">
@@ -10,8 +10,8 @@ import Base from '../layouts/Base.astro';
<div class="prose">
{/* Keep "the <a>" on one line: the compiler drops the whitespace at a
line break before a tag, which glued "the" to the link text. */}
<p>The address may be mistyped or the page may have moved —
go to the <a href="/">home page</a> or browse <a href="/news">all news</a>.</p>
<p>The address may be mistyped or the page may have moved.
Go to the <a href="/">home page</a> or browse <a href="/news">all news</a>.</p>
</div>
<form class="search-form" role="search" action="/search" method="get">
<label class="sr-only" for="nf-q">Search news</label>
+1 -1
View File
@@ -11,7 +11,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>CTAO — Content Editor</title>
<title>CTAO Content Editor</title>
<meta name="theme-color" content="#00004A" />
<link rel="icon" href="/brand/CTAO_Logo_positive.svg" type="image/svg+xml" />
<style>
+1 -1
View File
@@ -4,7 +4,7 @@ import Base from '../layouts/Base.astro';
// and help-desk tickets. No integrations exist yet, so panels show empty
// states instead of fabricated sample rows (source-documents-only rule).
---
<Base title="CTAO Science Portal — Dashboard" description="User dashboard (mock)">
<Base title="CTAO Science Portal - Dashboard" description="User dashboard (mock)">
<section class="band--moon">
<header class="container page-head">
<h1>Dashboard</h1>
+2 -2
View File
@@ -25,9 +25,9 @@ const services = [
icon: '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4"/><path d="m5.7 5.7 3.5 3.5m5.6 0 3.5-3.5m0 12.6-3.5-3.5m-5.6 0-3.5 3.5"/>' },
// Two subdued planned tiles complete the 2×3 grid (an orphan 4th tile in a
// 3-col grid reads broken); the remaining TBD services stay on the quiet line.
{ title: 'Software', planned: true, desc: 'Landing page for CTAO software — planned.',
{ title: 'Software', planned: true, desc: 'Landing page for CTAO software (planned).',
icon: '<rect x="3" y="4.5" width="18" height="15" rx="2"/><path d="m7 9.5 3 2.5-3 2.5M12.5 15H17"/>' },
{ title: 'Documentation', planned: true, desc: 'CTAO user documentation — planned.',
{ title: 'Documentation', planned: true, desc: 'CTAO user documentation (planned).',
icon: '<path d="M12 6.7C10.6 5.2 8.6 4.5 5.7 4.5H4v13.6h1.7c2.9 0 4.9.7 6.3 2.2 1.4-1.5 3.4-2.2 6.3-2.2H20V4.5h-1.7c-2.9 0-4.9.7-6.3 2.2z"/><path d="M12 6.7v13.6"/>' },
];
const planned = ['Scheduling', 'Science alerts'];
+2 -2
View File
@@ -1,14 +1,14 @@
---
import Base from '../layouts/Base.astro';
---
<Base title="CTAO Science Portal — Sign in" description="Sign in via CTAO AAI (mock)">
<Base title="CTAO Science Portal - Sign in" description="Sign in via CTAO AAI (mock)">
<section class="auth-band">
<div class="band-bg" aria-hidden="true"></div>
<div class="auth-card">
<img class="auth-logo" src="/brand/CTAO_Logo_positive.svg" alt="CTAO" />
<h1>Sign in</h1>
{/* Auth pages are scanned, not read — one line, no reassurance prose */}
<p class="muted">Use your CTAO account — single sign-on via CTAO AAI.</p>
<p class="muted">Use your CTAO account (single sign-on via CTAO AAI).</p>
<button class="btn btn-wide" type="button">Continue with your CTAO account</button>
<p class="notice">No account? <a>Register via CTAO AAI</a></p>
</div>
+3 -3
View File
@@ -45,8 +45,8 @@ for (let n = 1; n <= page.lastPage; n++) {
const hrefFor = (n) => (n === 1 ? '/news' : `/news/${n}`);
---
<Base
title={first ? 'CTAO Science Portal — News' : `CTAO Science Portal — News, page ${page.currentPage}`}
description={first ? 'News and announcements of the CTAO' : `News and announcements of the CTAO — page ${page.currentPage} of ${page.lastPage}`}
title={first ? 'CTAO Science Portal - News' : `CTAO Science Portal - News, page ${page.currentPage}`}
description={first ? 'News and announcements of the CTAO' : `News and announcements of the CTAO, page ${page.currentPage} of ${page.lastPage}`}
>
{/* Section-landing archetype: white head, display Galaxy h1 + standfirst
(the navy band is reserved for / and /login — DESIGN.md). */}
@@ -56,7 +56,7 @@ const hrefFor = (n) => (n === 1 ? '/news' : `/news/${n}`);
</header>
<section class="container page">
<h2 class="sr-only">{first ? 'All news' : `All news — page ${page.currentPage}`}</h2>
<h2 class="sr-only">{first ? 'All news' : `All news, page ${page.currentPage}`}</h2>
<div class="grid">
{page.data.map((post, i) => <NewsCard post={post} featured={first && i === 0} />)}
</div>
+1 -1
View File
@@ -20,7 +20,7 @@ const { Content, headings } = await render(post);
const toc = headings.filter((h) => h.depth === 2 || h.depth === 3);
const readMin = readMinOf(post);
---
<Base title={`${post.data.title} — CTAO`} description={post.data.description} type="article" image={post.data.cover && encodeURI(post.data.cover)}>
<Base title={`${post.data.title} - CTAO`} description={post.data.description} type="article" image={post.data.cover && encodeURI(post.data.cover)}>
{/* Reading progress (scroll-driven CSS, no JS) — styled only where
animation-timeline is supported; elsewhere it stays an empty div. */}
<div class="read-progress" aria-hidden="true"></div>
+1 -1
View File
@@ -10,7 +10,7 @@ export async function getStaticPaths() {
const { page } = Astro.props;
const { Content } = await render(page);
---
<Base title={`${page.data.title} — CTAO Science Portal`} description={page.data.description}>
<Base title={`${page.data.title} - CTAO Science Portal`} description={page.data.description}>
{/* Same wrapper pattern as news/[slug] (never .container and .article on
one element — both set max-width and would depend on rule order). */}
<div class="container article-layout">
+5 -5
View File
@@ -1,7 +1,7 @@
---
import Base from '../layouts/Base.astro';
---
<Base title="CTAO Science Portal — Proposals" description="Observation proposals — Proposal Handling System integration (planned)">
<Base title="CTAO Science Portal - Proposals" description="Observation proposals: Proposal Handling System integration (planned)">
<section class="band--moon">
<header class="container page-head">
<h1>Observation proposals</h1>
@@ -13,15 +13,15 @@ import Base from '../layouts/Base.astro';
hand-off instead of imitating their submission UI. */}
<div class="panel panel--narrow">
<h2 class="panel-title">Proposal Handling System</h2>
<p>Submitting observation proposals — including Target of Opportunity (ToO)
and multi-wavelength (MWL) requests — happens in the Proposal Handling
System, built by the APC team and integrated into this portal.</p>
<p>Submitting observation proposals, including Target of Opportunity (ToO)
and multi-wavelength (MWL) requests, happens in the Proposal Handling
System. That system is built by the APC team and integrated into this portal.</p>
<p>What the portal contributes:</p>
<ul class="panel-list">
<li>This menu entry, with a single sign-on hand-off (CTAO AAI).</li>
<li>Proposal status feedback in your <a href="/dashboard">Dashboard</a>.</li>
</ul>
<button class="btn" type="button" disabled>Open the Proposal Handling System — integration planned</button>
<button class="btn" type="button" disabled>Open the Proposal Handling System (integration planned)</button>
</div>
</div>
</section>
+1 -1
View File
@@ -29,7 +29,7 @@ export async function GET(context) {
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>CTAO Science Portal — News</title>
<title>CTAO Science Portal News</title>
<link>${new URL('/news', site).href}</link>
<description>News and announcements of the Cherenkov Telescope Array Observatory</description>
<language>en</language>
+1 -1
View File
@@ -1,7 +1,7 @@
---
import Base from '../layouts/Base.astro';
---
<Base title="CTAO Science Portal — Search" description="Search CTAO news and announcements">
<Base title="CTAO Science Portal - Search" description="Search CTAO news and announcements">
{/* Utility archetype: ONE surface per page — Moon canvas from the landing
head down (borderless cards/panels pop against it); editorial pages stay
all-white. No mid-page surface seams (DESIGN.md). */}
+1 -1
View File
@@ -8,7 +8,7 @@ const channels = [
{ title: 'Mailing lists', desc: 'Announcements and topical mailing lists.' },
];
---
<Base title="CTAO Science Portal — Support" description="User support: help desk, FAQ, forum, mailing lists (mock)">
<Base title="CTAO Science Portal - Support" description="User support: help desk, FAQ, forum, mailing lists (mock)">
<section class="band--moon">
<header class="container page-head">
<h1>User Support</h1>