fix: footer email reflow to zero under all four methods; reopen the skip-link residual as Q61

The footer mailto was the last recorded overflow: `info@smlcompany.ca` demanded
310px of min-content in a 224-243px column. One declaration —
`overflow-wrap: anywhere` on `.footer-contact a[href^='mailto:']`. `anywhere`
and not `break-word`, established with a negative control rather than from the
rule: only `anywhere` reduces min-content, and `break-word` injected in its
place failed the same 88 rows as the unfixed baseline.

Minimum-font-size 32 goes 88/352 -> 0/352. All four methods now read 0 of 352
(22 pages x 16 widths). Normal-settings identity: 0 differences across 8
metrics, with a positive control proving the comparison can detect one. It also
closed 57 element-level cases the page-level table reports as clean, hidden
inside `.wrap`'s 96px gutter.

The item-2 ruling is NOT applied, and this is the deviation to read first. The
acceptance rested on "no CSS mechanism can see minimum-font-size", which is
false: the font-metric units — `ch`, `ex`, `cap`, `lh`, `rlh` — read the used
font size and double, in property values, in `@media` and in `@container`. Only
`rem`, `em`, `ic` and `px` are blind. And the cost is not a convenience loss:
keyboard focus lands entirely behind the opaque header on 290 of 1,455 stops,
36 of them inside `#main`, which is WCAG 2.2 SC 2.4.11 at AA — the same level as
the 1.4.10 failure it was traded against. A build of fce89d4~1 measures 0, so
the header fix created it. Opened as Q61 with a verified candidate; docs/06
restored to unticked.

R20's gate is now a build failure rather than three prose cross-references,
which demonstrably did not gate it: with two articles published the build and
all five checks passed while both header defects shipped. SiteHeader throws.

R11's two majors (@astrojs/mdx 7->8, typescript 6->7) move to a new cutover-prep
group in docs/06 with the 19-pin currency sweep.

Two review rounds, eight findings, all resolved; four of round 2's five were
defects in round 1's own fixes. Stopped at two per D19.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
Pouya Lajevardi
2026-09-01 14:51:37 -04:00
co-authored by Claude Opus 5
parent fce89d46eb
commit ca1c2524e1
8 changed files with 960 additions and 98 deletions
+6
View File
@@ -244,6 +244,12 @@ const aboutLinks = [
color: var(--text-inverse-2);
text-decoration: underline;
}
/* `anywhere`, NOT `break-word` — only `anywhere` reduces min-content size, which
is the defect: the address has no break opportunity. `docs/02` §Reflow. */
.footer-contact a[href^='mailto:'] {
overflow-wrap: anywhere;
}
/* Not a link, so no target floor — but it shares a column with links and
should sit on the same rhythm. */
.footer-meta {
+17
View File
@@ -23,7 +23,24 @@ import InfinityMark from './InfinityMark.astro';
import Button from './Button.astro';
const published = await getCollection('insights', ({ data }) => !data.draft);
/* ⚠️ GATED BY A BUILD FAILURE, NOT BY THIS COMMENT — `AGENTS.md` R20 and Q61.
The seventh nav item arms two measured header defects under fallback font
metrics. Prose cross-references did not gate it: every check passed while it
fired. Delete the throw as part of the fix, not before it. */
const showInsights = published.length >= 2;
if (showInsights) {
throw new Error(
'AGENTS.md R20 — the seventh nav item is gated and this build would ship it.\n' +
`A second Insights article is published (${published.length} live), which puts ` +
'Insights in the primary nav. With seven items under FALLBACK font metrics — ' +
'the font-display: swap window, at the default text size, no reader setting ' +
'involved — the masthead measures 141px across 1056-1091px instead of 81px: a ' +
'60px shift on every page against the CLS < 0.05 budget, and 44px of #main ' +
'behind the sticky header after "Skip to content".\n' +
'Fix that first (docs/02 §Reflow lists the two candidate fixes), then delete ' +
'this guard. Do not work around it by unpublishing the article.',
);
}
const items = PRIMARY_NAV.filter(
(item) => item.href !== '/insights/' || showInsights,
+6 -2
View File
@@ -124,8 +124,12 @@ html {
`--header-h` is defined in tokens.css beside the value it has to match, and it
is a FLOOR — above the default text size the masthead reflows and is taller, and
`SiteHeader` gates stickiness so the offset is generous rather than short.
⚠️ TWO SETTINGS DEFEAT THAT GATE and leave this offset short; `docs/02` §Reflow
names them and shows why no CSS can detect either. */
⚠️ TWO CASES DEFEAT THAT GATE and leave this offset short — one a reader
setting, one the webfont swap window. Under Chrome's minimum font size the
shortfall is an OPEN WCAG 2.2 SC 2.4.11 (AA) failure, not an accepted one:
`AGENTS.md` Q61. **CSS CAN detect that setting** — the font-metric units
(`ch`, `ex`, `cap`, `lh`) respond to it where `rem`/`em` do not — so a fix is
possible here and is awaiting a ruling. Measurements: `docs/02` §Reflow. */
@media (min-width: 66rem) {
html {
scroll-padding-top: calc(var(--header-h) + var(--space-4));
+3 -3
View File
@@ -142,9 +142,9 @@
is why the nav no longer runs off-screen. `global.css` drives
`scroll-padding-top` off it and `SiteHeader` gates stickiness so the offset is
generous rather than short — **but not in every case**: `docs/02` §Reflow lists
the two settings where it is still short and why no CSS can see them. If
SiteHeader's padding or nav sizing changes, re-measure and change this with
it — one fact living in two files.
the two cases where it is still short, one of them an OPEN SC 2.4.11 (AA)
failure (`AGENTS.md` Q61). If SiteHeader's padding or nav sizing changes,
re-measure and change this with it — one fact living in two files.
[measured 2026-08-26, re-measured 2026-09-01 — headless Chrome, six nav items
and a seventh injected. 81.00px at all EIGHT widths from 1056 to 1920px
(1056/1100/1216/1240/1280/1440/1600/1920): 32 padding + 48 reserved brand