Stop the landing clause number from landing on top of its heading
The number beside each landing block was an absolutely positioned
::before, and the gutter it needs was reserved by a padding that only
existed inside a `min-width: 62rem` media query. Everywhere else the
number was painted straight onto the first letter of the title: the
teal "01" sat on the Q of "Qué es" at every width below 992px, at
200 % and 400 % browser zoom, and at any width at all once the reader
enlarges the default text size, because a rem media query resolves
against that size and 62rem stops matching a 1440px window as soon as
the default goes past 23px. I measured it at 20 of the 26 cases I
checked, in both locales.
The number is now a real box in the layout instead of an overlay. Each
block is a wrapping flex line of two items, the number and the block
body, so the space is reserved by the layout itself at every width:
when the line has room the number sits in its gutter beside the
heading, and when it does not the body wraps and the number ends up on
its own line above the title. There is no threshold left to get wrong,
and no state in which the two can occupy the same pixels.
scripts/check-home-headings.mjs proves it: 40 cases, both locales, 320
to 1920 px, 200 % and 400 % zoom, and default text sizes of 24 and 32
px. It asserts that no clause number overlaps any text of its block,
that no step number overlaps its step heading, that the list markers
fit the indent their item reserves, and that the document never
scrolls sideways.
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.
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.
Ship one palette and one language behaviour, and delete the switching
I have decided both questions this branch was carrying, so the code
should carry one answer and not three. The palette is "instrument",
cool steel greys with a deep cyan indicator, and the language handling
is the banner: it offers the other language and nothing ever navigates
on its own.
Gone with them: the floating prototype switcher, the blueprint and
graphite palettes, the `data-accent` attribute and the before-paint
script in Head.astro that stamped it, the `phonometry:accent` and
`phonometry:lang-mode` storage keys, the redirect and off language
modes with their per-session guard, and the bar-height custom property
that only existed so the switcher could sit clear of the bar.
src/styles/theme-directions.css becomes src/styles/theme.css, with the
winning direction promoted to the plain :root and
:root[data-theme='light'] rules.
The language feature keeps a kill switch, but as a build-time constant
rather than a control: ENABLED in LangSuggest.astro renders no markup
and no script when it is false. Nothing on the page and nothing in
storage can flip it.
Everything else about the behaviour is unchanged and still checked: an
explicit choice always wins, the picker and a dismissal both record
one, crawlers are skipped and the English-only API subtree renders no
bar at all. check-contrast.mjs now resolves the two themes of the one
palette (25 pairs, 0 below threshold) and check-lang-suggest.mjs runs
the nine scenarios that survive without modes.
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.
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.
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.
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.
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.
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.
docs(site): migrate every guide to typed references, accessible media components and prose-aligned figures (#224)
* docs(site): migrate signal-analysis and level guides to typed references
Levels, time weighting, frequency weighting, calibration, block
processing, spectral analysis, filter banks, multichannel, correlation
and GUM uncertainty (EN and ES) move their manual References and
Standards sections into the typed frontmatter bibliography with
verified catalogue links. Time weighting becomes MDX and embeds its
needle animation through the Video component. Media placement fixes
from the audit: the levels tonal-adjustment figure joins its
explanatory paragraph (and a residual duplicated code block goes
away), the time-weighting video and figure follow the Fast/Slow/
Impulse bullets, calibration's flow diagram follows its intro
paragraph and block-processing's diagram and figure each join their
own paragraph, applied in the GitHub docs and both site languages.
* feat(site): theme-aware figure component and first migration wave
ThemeImage.astro renders the light/dark figure pair from the light
variant URL and a single alt text, deriving the _dark twin and keeping
the exact markup the theme switch and the responsive width tiers key
on, with native lazy-loading (the page hero opts into eager). The
signal-analysis guides, the pilots, getting started and why-phonometry
(EN and ES, 130 figure pairs) migrate their hand-written pairs to it,
becoming MDX where needed.
* docs(site): migrate psychoacoustics and hearing guides to typed references
Sound quality, hearing threshold, noise-induced hearing loss,
occupational exposure, speech intelligibility, speech transmission,
tone audibility, tone prominence, impulse prominence and programme
loudness (EN and ES) move their manual References and Standards
sections into the typed frontmatter bibliography with verified
catalogue links, become MDX and migrate their figure pairs to
ThemeImage. Impulse prominence embeds the onset-detection animation
through the Video component. Media placement fixes from the audit,
applied in the GitHub docs and both site languages: the STIPA chain
diagram joins the direct-method snippet it draws (with a new intro
sentence), the onset-detection clip moves next to the 10 dB/s onset
criterion and the KI(P) figure joins the paragraph that reads it, the
NIPTS/HTLAN panel joins its worked example and the occupational Annex D
figure follows the welder snippet.
* docs(site): migrate building-acoustics insulation guides to typed references
Laboratory and field insulation, insulation prediction (EN 12354),
enclosed-space absorption, dynamic and transfer stiffness, mechanical
mobility and structure-borne power (EN and ES) move their manual
References and Standards sections into the typed frontmatter
bibliography with verified catalogue links, become MDX and migrate
their figure pairs to ThemeImage. Insulation prediction embeds the
flanking-paths animation through the Video component. Media placement
fixes from the audit, applied in the GitHub docs and both site
languages: the flanking video joins its junction paragraph and the
facade figure regains its code block, the delta-L and Kij figures join
their explanatory paragraphs, the airborne rig diagram and the
uncertainty rating figure join theirs, and the mobility test-bench
diagram follows its description.
* docs(site): migrate rooms and materials guides to typed references
Installed structure-borne sources, vibration sound power,
reverberation prediction, room acoustics, room noise, acoustic
materials, porous absorbers and FDTD simulation (EN and ES) move their
manual References and Standards sections into the typed frontmatter
bibliography with verified catalogue links, become MDX, migrate their
figure pairs to ThemeImage and embed their animations (sweep
deconvolution, comb filtering, Schroeder decay, standing-wave tube and
room modes) through the Video component. Media placement fixes from
the audit, applied in the GitHub docs and both site languages: the
comb-filter clip joins the correlated-positions bullet, the open-plan
decay figure joins its metrics snippet, the impedance-tube diagram
follows its transmission-loss equation, the ISO 12999-2 uncertainty
figure regains its code block and the FDTD barrier field moves to the
geometry section it illustrates.
* docs(site): migrate environment and transport guides to typed references
Outdoor propagation, sound power, intensity, wind-turbine noise,
rotorcraft noise, electroacoustics, human vibration and multiple-shock
vibration (EN and ES) move their manual References and Standards
sections into the typed frontmatter bibliography with verified
catalogue links; together with the aircraft-noise pilot they become
MDX, migrate their figure pairs to ThemeImage and embed their
animations (ground effect, barrier diffraction, two rooms with one
sound power, intensity scanning and instantaneous intensity) through
the Video component. Media placement fixes from the audit, applied in
the GitHub docs and both site languages: the two-rooms clip opens the
sound-power story and the p-p probe diagram joins the intensity
paragraph, the phasor clip gets its own introduction, the SAE
absorption, NPD and SEL-contour figures join their explaining
paragraphs, and the wind-turbine tonality and rotorcraft ground-effect
figures join theirs.
* docs(site): migrate underwater guides to typed references
Underwater acoustics metrics and underwater propagation (EN and ES)
move their manual References and Standards sections into the typed
frontmatter bibliography (the propagation page carries its sixteen
JASA-heavy citations with bare DOIs), become MDX, migrate their figure
pairs to ThemeImage and embed the SOFAR-ducting animation through the
Video component. Media placement fixes from the audit, applied in the
GitHub docs and both site languages: the metrics page reunites each
figure with its code block, and the propagation page unwinds its
inverted layout by moving all seven figures below the prose,
formulas or snippets that explain them.
* docs(site): migrate theory pages to typed references
The five theory chapters (signal analysis, perception, rooms and
buildings, environment and transport, vibration; EN and ES) move
their manual References sections into the typed frontmatter
bibliography, reusing the verified catalogue links of the guides for
the works they share.
* docs(site): finish the reference migration and widen the accessibility gate
Surface scattering joins the typed bibliography (its in-situ ISO 13472
parts and the ISO 9613-1 coefficient gain verified catalogue entries,
and the outdoor-propagation pointer moves to See also). The pa11y gate
gains six representative migrated pages across both languages, and the
changelog records the completed migration.
* docs: reunite the loudness specific-loudness media with their prose
Second review pass. The loudness guide's triple media stack unwinds in
the GitHub docs and both site languages: the specific-loudness
animation gains an introductory sentence and the pattern figure moves
after the usage snippet, next to its code block. The Spanish
electroacoustics entry adopts the UIT-R acronym the programme-loudness
guide already uses.
* docs(site): review fixes to Spanish reference notes
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.
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.