fix: header reflows under enlarged text; reopen the step-1 nowrap decision
The step-1 header decision is formally reopened (AGENTS.md (ak)): its record attributed the residual to the wrong cause and read a measured 944px functional failure as a robustness margin. Mechanism — wrapping, plus a gated sticky offset: - `flex-wrap: nowrap` removed from `.header-inner` (measured necessary AND sufficient) and from `.nav-list` (measured inert; removed so the prohibition is not contradicted by a `nowrap` in the same file), with a dead `flex: none`. - `inset-block-start` becomes a two-band, two-term saturating clamp() so the header is sticky only while the masthead is one row. A media query cannot express this: its `rem` resolves against the browser DEFAULT font size, a property's against the root element. The second term catches a root BELOW the default, where the 80rem content cap shrinks faster than the header's px minimums; without it 65px of `#main` sat behind the header at 9px. - Wrapping is the only mechanism that reflows under all THREE enlargement paths, because Chrome's minimum-font-size setting is invisible to @media, to @container and to every length unit. Measured, 22 pages x 16 widths = 352 page-widths per method: root-style 32px 175/352 -> 0/352 (1280px: 944px overflow -> 0) minimum-font-size 32 219/352 -> 88/352 (residual is the footer email) default-font-size 32 0/352 -> 0/352 default (root 16) 0/352 -> 0/352 Nav items and CTA on-screen in 1408/1408. A further 762 points across roots 9-32, both thresholds, the band seam and all five Chrome presets: 0 failing. Normal-settings identity: 0 differences on 352 page-widths across six metrics, with six nav items and with a seventh injected. Header 81.00px at all eight widths >= 1056, CTA gap 0.00px. Lighthouse: 22 pages, no category below 95, CLS 0.000 on every page. --header-h is reworded as a FLOOR, not a constant; value unchanged. Also in this step, per ruling: - /bio/ print `font-weight` frozen at 400 — the circulated PDF's typography changes only when its content is deliberately revised, never as a side effect of a screen refactor. Declaration byte-identical; the constraint is recorded. - CLAUDE.md: the two-simulation rule for enlarged text, the zsh no-word-splitting rule, the third (minimum-font-size) mechanism, and "state the grid with the count". Two rounds of adversarial-reviewer, eleven findings, all resolved; round 2's blocking finding was a defect in round 1's own fix. Two suggested fixes declined with reasons in (ak). claims-auditor deliberately not run — D20. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
0f7595b602
commit
fce89d46eb
@@ -273,6 +273,15 @@ argument and the comparison never ran. Prefer `git grep`, quote or array-expand
|
||||
anything you pass as flags, and re-check any result whose shape is "uniformly
|
||||
bad".
|
||||
|
||||
**zsh does not word-split parameter expansions; a loop over `$VAR` runs ONCE —
|
||||
use command substitution or arrays, and assert the iteration count.** *Pouya's
|
||||
convention, 2026-09-01.* `for p in $PAGES` iterates one item, not twenty-two,
|
||||
and `node probe.mjs 320,360 $P` measures one page — both of which then report
|
||||
"max=0, nonzero=0" and read as a clean sweep. `$(cat file)` and `${=VAR}` do
|
||||
split; `"${(@f)VAR}"` splits on newlines. **The fix is not remembering which:
|
||||
assert the count before reading the result** — a probe that says how many rows it
|
||||
measured cannot silently measure one.
|
||||
|
||||
**And re-check "uniformly GOOD" too — that is the dangerous half.** *Added
|
||||
2026-08-30; sharpened on Pouya's instruction 2026-08-31, as "the sharpest
|
||||
instrument finding yet".* The same `set -- $pair` loop recurred while confirming
|
||||
@@ -387,6 +396,32 @@ So before acting on a number: say what it is a number *of*; confirm the command
|
||||
actually ran and read its exit status; and check it against a second method that
|
||||
cannot fail the same way — the bytes on disk, a screenshot, a hit test.
|
||||
|
||||
**Two simulations of 200% text are not equivalent: media-query `rem` resolves
|
||||
against the browser DEFAULT font size, not the root element — measure under both
|
||||
methods before declaring a reflow result.** *Pouya's convention, 2026-09-01.*
|
||||
Raising the default moves the breakpoints along with the type, so the desktop
|
||||
layout is never reached and nothing overflows; setting `documentElement.style
|
||||
.fontSize` doubles the type and leaves the breakpoints where they were, which is
|
||||
the layout the desktop nav was measured in. One of those reported **0** while the
|
||||
other reported **944 px** on the same 22 pages, and the prose generalised the
|
||||
zero.
|
||||
|
||||
⚠️ **AND THERE ARE THREE MECHANISMS, NOT TWO — the third is the one that defeats
|
||||
every CSS conditional.** Measured 2026-09-01: Chrome's **"Minimum font size"**
|
||||
*floors* computed font sizes instead of scaling them, so text enlarges while
|
||||
`rem` keeps resolving at 16 px. A media query does not see it, and neither does a
|
||||
container query — `@container` `rem`/`em` DO track the root element (that is the
|
||||
one real difference from `@media`, and it is measured), but under a minimum-font-
|
||||
size setting they still resolve at 16 px while `getComputedStyle` reports 32 px.
|
||||
**So no query fires, and only used-value layout — wrapping — reflows.** That path
|
||||
was the worst of the three: on one grid of 22 pages × 16 widths, **219 of 352
|
||||
page-widths overflowed** against root-style's **175**, and it was the only one
|
||||
failing at 320 px and 1024 px. **Always state the grid with the count** — two
|
||||
sweeps in that session quoted totals of 220, 330 and 352 for the same claim, and
|
||||
side by side they read as contradictions rather than as different width lists.
|
||||
Measure all three mechanisms; treat a clean result from one as evidence about
|
||||
that one.
|
||||
|
||||
**And a grep that matches is not a finding until you read what it matched.**
|
||||
A case-insensitive sweep for `LSO` hit `I aLSO practise`; a superlative sweep for
|
||||
`leading` hit `the pLEADINGs`. Both on the same page on the same day. Print the
|
||||
|
||||
Reference in New Issue
Block a user