Capture the sidebar grouping candidates and add a mobile-drawer pa11y run
Twenty-three shots in toc-ux-shots/: the status quo, the responsive treatment
and the collapsed treatment, at 1440x900 and 390x844, in both themes and both
languages, plus the tapped and keyboard-focused states of the fold control.
Desktop shots are clipped to the sidebar column, which is the subject; phone
shots are the whole viewport, because there the tree is a drawer over the page.
The pa11y config for the drawer opens the hamburger before testing, which the
default run never does, so the folded tree and its controls are audited in the
state a phone reader actually sees.
The fold control keeps a 40px square target on the drawer, past the 24px floor
of WCAG 2.2 SC 2.5.8 and small enough that the eleven closed groups still fit
one screen, and it restates the two eyebrow-header rules that the row wrapper
would otherwise stop matching.
Rework the front page, and add a mobile theme toggle and language detection
Front page. The landing was the README feature list as ten cards of 60 to 90
words: it stated everything and showed nothing, and its numbers were an
earlier release's (371 checks, 235 standards, against the 427 over 278 the
conformance report now produces). It is now five blocks that each answer one
question: the numbers with no adjectives, what this is with who it is for and
an explicit list of what it is not, one worked example beside the figure it
draws and one rating beside the PDF fiche it renders, the coverage of nine
areas as a table of standards, and a three-step path from nothing to a first
analysis. Text lives in src/data/home.ts, one object per locale sharing one
shape, so English and Spanish cannot drift apart; every number in it is
sourced from the repository and the file records where.
The splash column widens to 62rem, the sidebar gutter Starlight reserves is
zeroed so the page is centred, and the hero grid collapses to one column
since there is no hero image.
Mobile header. Below the md breakpoint Starlight hides the theme control
behind the hamburger. Header.astro now surfaces it next to the language
picker, in the desktop order, as an icon-and-caret stub. Starlight's own
updatePickers() already walks every theme select on the page, so the mobile
stub and the desktop control stay in sync with no extra code.
Language detection. LangSuggest.astro offers the other language on a first
visit, in banner mode by default, with redirect and off available from the
prototype switcher. An explicit locale in the URL wins, the language picker
records the choice, and once anything is stored nothing ever navigates on its
own again, so a deliberately opened English URL is never hijacked.
Redirection is guarded by a stored choice, a session flag and a target check,
so it cannot loop; crawlers are skipped by user agent; the English-only API
subtree opts out entirely; and none of it touches canonical or hreflang.
scripts/check-lang-suggest.mjs drives eleven scenarios in isolated browser
contexts: 0 failing.
Build with link check, html-validate, pa11y at WCAG2AA (46/46) and the EN/ES
parity gate all pass.
Take the standards information out of the sidebar and prototype chip pills
The sidebar keeps the tree and nothing else. The annotation experiment is
deleted rather than switched off: the data-toc-style dimension and its five
presentations, the annotation line, the hover card and its keyboard handling,
the page subtitle and the section landing tables all go, and with them the
attrs['data-chips'] classification in the sidebar config and in the API
generator, plus the shortened sidebar labels the chips had justified.
SidebarSublist.astro and Sidebar.astro are back to the smallest diff against
upstream Starlight that still gives me non-collapsible groups, the
overview-first convention where a group label links to its landing page, and
the fold toggle the API treatments need. Each file header now records what
differs from upstream and why, so a future Starlight upgrade is cheap to
reconcile.
Everything about what governs a page now lives in the page header run, which
takes its data from the frontmatter bibliography. That run gains two more
presentations to compare against the quiet text version: outlined pills, so
the chips look like the links they are, and the same pills with a faint
category tint. Both keep the eight chips of the densest page on one line and
clear 5.9:1 on their text in either theme.
Land the "+N more" chip where the entries land, and raise the cap to nine
Three things on the header chips.
The "+N more" chip pointed at the References heading, which had no landing
offset of its own, while the entries had one. Starlight's scroll-padding
clears the sticky chrome for both, so neither was hidden, but the heading came
to rest hard against the sticky bar while an entry came to rest a comfortable
way below it, and on a phone, where the mobile table of contents is part of
that chrome, the difference is the whole gap. The offset is now one custom
property in one rule covering the entries, the heading and its wrapper, so
the two targets cannot drift apart again. Both land at 168 px on a 1440 px
desktop and 200 px on a 390 px phone, EN and ES, with and without the
language bar.
The cap is nine chips for the run as a whole, with a tenth slot for the
"+N more" link, replacing five standards plus three works. The budget is not
split per category any more, with one guard: the named works hold a
reservation of up to three slots when the page has any, the standards take
the rest, and whatever the standards do not use goes back to the works. Nine
standards on a standards-only page, nine papers on a paper-only page, and a
page with fourteen standards and three papers shows six and three rather than
nine and none. The `primary: true` flag still orders the run first: flagging a
work that was past the old cap on the underwater page brings it to the front
of its run and into the visible nine.
Worth knowing: nine chips no longer fit the one line the run was designed
around. The densest page is four rows at 1440 px and six at 390 px. It reads
as a block under the H1 rather than a dateline, which is the trade the higher
cap buys.
scripts/check-page-chips.mjs is the new gate: the cap on seven pages in both
locales, and the landing of an entry chip against the more chip at four
viewport sizes, both themes, both locales and with the language bar up.
Lift the language bar out of the content column
The bar is fixed across the whole bottom edge, but it was mounted in the
Footer override, which renders inside Starlight's `.main-pane`. That pane
sets `isolation: isolate`, so the bar got its own stacking context and
painted under the sidebar pane no matter what its z-index said: on a desktop
layout the sentence was cut mid-word by the sidebar and the dismiss button
was cut by the table of contents. Mounting it in a PageFrame override makes
it a sibling of the page frame, in the root stacking context, where its
z-index means what it reads. The frame renders on every route, splash
included, so nothing loses the bar.
The floating treatment switcher was landing on the dismiss button as well,
the two branches having each pinned something to that corner. The bar now
publishes its height on <html> while it is on screen and the switcher steps
over it.
check-lang-suggest.mjs gets the scenario that would have caught this: hit
test the bar over the sidebar, over the content and over the toc, plus the
dismiss button itself. The markup was always right; only the paint order
was wrong, so only a hit test can see it.
Settle the page chips on the outlined pill and give authors a priority flag
The pill without fill is the chosen style, so it is the only one left: the
plain text run and the filled pill are deleted with their CSS, the
data-page-chips attribute is gone and the chips render whenever a page has
references. The switcher keeps only the API treatment and is labelled for it.
The pill outline was the one thing I had left below its accessibility target.
It now clears 3:1 against the page background in both themes, measured on the
composited colour: 50 % alpha dark for both categories, 80 and 90 % light,
where solid amber on white only reaches 3.99:1 to begin with. Nothing else
about the chip changed, so the approved size, padding, radius and spacing are
untouched.
Which sources survive the caps is no longer frontmatter order alone: a
reference marked primary: true is promoted within its category run, with
frontmatter order as the tiebreak, so a page with a long bibliography can
advertise the sources it leans on. The field is optional and documented in
the schema.
The ICAO Annex 16 entry on the aircraft-noise page carried an edition string
where its document number belongs, so that page derived no chip for the
standard it implements. Both language versions now name the document.
feat(site): unified APA references, accessible video embeds and build optimization (#223)
* feat(site): unified per-page references from typed frontmatter
Pages can now declare their bibliography as a typed references list in
the frontmatter (docsSchema extension: standard, book, article, web and
report entries with DOI/URL fields). A MarkdownContent override renders
one localized APA-7 References section at the end of the article,
alphabetized, with the title carrying the link and the DOI rendered as
its own descriptive link, and the route middleware appends the matching
On this page entry. Custom UI strings ride Starlight's i18n collection
(EN/ES).
* feat(site): accessible video embed with a download link
Video.astro wraps the Tier-1 animation convention (preload none, poster,
reserved width/height, EN/ES x light/dark WebM variants resolved from
the clip basename and the page language) and adds the accessibility
layer: required accessible name and textual description (aria-label +
aria-describedby), a visible localized download link per theme variant,
an in-element textual fallback, an optional visible caption and no
autoplay. The theme switch now also covers the wrapping figure.
* fix(site): keep the programme-loudness page titles within 70 characters
html-validate's long-title rule caps document titles at 70 characters
and the page suffix pushed both languages over the limit. The ITU-R/UIT-R
qualifier moves out of the title (the description and body keep the full
designations).
* docs: pilot migration to frontmatter references and the video embed
Loudness, aircraft noise and psychoacoustic annoyance (EN and ES) move
their References and Standards prose into the typed frontmatter
bibliography, with verified publisher links for every entry (ISO/IEC and
Ecma catalogues, ICAO store, SAE, ECAC, doi.org). Loudness and surface
scattering become MDX and embed their animations through the Video
component. The pa11y audit gains the six migrated URLs.
* perf(site): recompress served raster images and parallelize page rendering
A postbuild step palette-quantizes PNGs and re-encodes JPEGs in dist/
(sources untouched, rewritten only when smaller): the social card drops
from 663 KiB to 337 KiB. Page rendering moves to four concurrent pages.
The build profile documents the ceiling: the content-sync phase cannot
be cached while starlight-links-validator is enabled, since the plugin
clears the content-layer cache so its link map sees every page.
* docs: changelog for the site references, video embed and build optimization
* fix(site): review pass over the references and video infrastructure
References: nothing rendered after a DOI (APA-7), the annotation moves
to its own line and auto-links bare URLs keeping trailing sentence
punctuation out of the link (restoring the IEC 61265:2018 and ECAC
documents-page links in the aircraft-noise notes and the ICA 2016 venue
gloss in the annoyance notes), the Spanish pages join the last author
with "y" instead of the ampersand per the Spanish adaptation of APA-7,
the injected heading gets the same hover anchor as authored headings,
journal volumes italicize with <i> instead of <cite>, undated entries
sort first and the unreachable author fallback now fails loudly.
Video: figcaption kept as the last figure child (valid HTML) and an id
override for repeated embeds. Image recompression: per-file failures
skip with the file named instead of failing the build, and
already-indexed PNGs are skipped so a manual postbuild re-run cannot
re-quantize. Stale autoplay wording removed from the theme CSS comment;
leftover double blank lines collapsed.