feat: eyebrow 14px and one small-text floor; fix a site-wide reflow defect; stamp TTL; §4 bars the struck universal
Pouya's five rulings of 2026-08-31, after 64bce10. One commit, because AGENTS.md
entry (aj) covers all five and the review fixes interleave across them —
recorded here rather than left to be inferred.
1. THE EYEBROW, 13 -> 14px, at the one token definition. `--text-eyebrow` is
deliberately NOT an alias of `--text-sm` despite sharing its value: the two move
for different reasons, and aliasing would mean a change to body-meta type
silently moving every eyebrow. Sweep by rendering, 22 pages x 2 widths, 801 mono
instances: 441 carry `.eyebrow`, 420 now at 14px, 21 held at 11px. Zero of 801
below 4.5:1.
Header check, which Pouya asked for explicitly: nothing header-side consumes the
token, `--header-h` is 81px, and the sticky header measures exactly 81.00px at
every width from 66rem up with the CTA on `.header-inner`'s content edge. Nothing
overflowed, so nothing was improvised.
2. /contact/'s LABELS RAISED, AND THE FLOOR CLAIM REWRITTEN BECAUSE THE RULING'S
PREMISE WAS FALSE. The ruling asked docs/02 to record the tagline as "the ONLY
sub-14px text on the site". It is not: the `--text-xs` 12px rung has ten
declaration sites and 130 elements rendering at 12px. So docs/02 records the
claim that IS verified — `--text-2xs` has one consumer in the repository — and
enumerates the 12px rung as a separate treatment. Writing a false claim into the
spec because the conclusion was handed down is the move the rules forbid.
A third block moved that the ruling did not name: /bio/'s ten <h2>s and its strap
were copies of five of `.eyebrow`'s six declarations at 11px — the same escape the
footer headings were. docs/02 justified holding them by the one-page PDF
constraint; measured, `@media print` sets both to 7pt, so the screen size never
reached the PDF and that was never the reason.
Consolidating them DID change the printed sheet, because the missing sixth
declaration was `font-weight`: 500 grew the PDF 89,496 -> 91,151 bytes. Print
therefore freezes 400, the committed PDF stays byte-identical (10 differing
bytes, all /CreationDate and /ModDate), and unifying is Pouya's call.
3. THE REFLOW DEFECT WAS SITE-WIDE AND /bio/ WAS NOT THE BINDING CAUSE.
`white-space: nowrap` on `SiteHeader .brand-name` held all 22 pages 63px over at
320px/root 32. Eight cause-specific fixes, no `overflow-x` anywhere; all eight
produce byte-identical geometry at root 16. `Pill` is marked in docs/02 as the
backstop it is — the real cause was `PracticeCard`'s rem-based padding, and with
it clamped "Construction" goes from 94x220 in six two-character lines to 158x85 in
two.
Three instrument findings now in docs/02, each of which hid a real defect:
`break-word` does not reduce min-content and `anywhere` does;
`getBoundingClientRect()` reports border boxes, so an element sweep cannot see
text spilling outside its own box; and `mobile: true` emulation expands the
layout viewport, so `scrollWidth - innerWidth` reads 0 while the reader still
scrolls sideways.
4. TTL STAMPED `ENABLED` in §7, with `DISABLED` at first verification recorded
rather than overwritten. Q60 narrowed to its second half and OPEN: no record has
been watched to vanish, and `ENABLED` proves the setting, not the behaviour.
R19's sweep found three stale copies outside §7; all now defer to it. R19 itself
was not edited — it points at §7 rather than carrying state, which is the
property that made it work.
5. §4 GAINS THE STRUCK-UNIVERSAL ROW, citing the committed ontario.ca extract and
cross-referenced to `check:claims`'s `struck-universal-q39`. It bars the claim in
BOTH directions: the commercial half is Pouya's attributed position, not a
verified fact. The row immediately caught two places asserting it flatly —
`SiteHeader.astro` and §9 Q33 — both now attributed. `check:claims` unmodified;
still frozen.
REVIEW: adversarial-reviewer, two rounds, 16 findings, ALL ACCEPTED, NONE
DECLINED. claims-auditor did not run (D20). Eight of round 2's ten were defects
in round 1's own fixes.
Round 1's blocking finding was a defect in my own record: I wrote that every
reflow residual was zero at "root 16 and root 32, 286 measurements". Two ways of
simulating 200% text are NOT equivalent, because media-query `rem` resolves
against the DEFAULT font size, not the root element's. Under the method docs/02
itself prescribes the site is 944px over on 21 pages and 508px on / at 1280, and
304px at 1920 — nav clipped mid-word, Practice/Fees/Contact and the CTA
off-screen, WCAG 1.4.4 with loss of functionality. My 286 excluded exactly the
widths where the defect lives.
NOT FIXED, DELIBERATELY: the cause is `flex-wrap: nowrap` on `.nav-list` above
66rem, a locked step-1 decision, and the standing instruction is to stop and
report rather than improvise a header change. It is now a blocking item on
docs/06's cutover checklist, ticked only by ruling on it — "not by re-measuring
it with the method that reports zero".
Round 2 also caught: a 63,743-byte figure that was the `cmp -l` differing-byte
count rather than the 1,655-byte size delta; a lost-navigation list naming
Med-Arb, which is not in the masthead at any width, while omitting Contact; the
tagline's justification left recorded at 13px, where one clause of it is false at
14px (20px of document overflow at 1216 with a seventh nav item); my own label
raise reintroducing a 38px element overflow at the width just ruled on; two
copies of the eyebrow treatment left at weight 400; three stale residual tables;
and the min-content explanation duplicated six times in src/.
VERIFIED, exit statuses read directly, never through a pipe: build 0 (22 pages),
check 0 (0 errors/0 warnings/0 hints), check:claims 0, og:proof 0, check:intake 0,
lint 0, minifier tripwire clean, TODO in dist 0 with a source sanity check.
Overflow: 374 measurements over 22 pages, every one zero, row counts asserted
before reading, with positive controls (119px at width 200, 319px at root 64).
Lighthouse 0, run three times with identical category scores: perf 99 on / and
100 elsewhere, a11y 100, best practices 100, SEO 100 on all indexable pages,
CLS 0.000. / sits at LCP 2.03s against a 2.0s budget, unchanged by this work.
The zsh `$VAR` word-split trap fired twice more and both times read as a clean
pass; caught only by asserting row counts first. Two of my own instruments were
wrong before they were right: a `grep -F '0.875rem'` state check that could never
match because Lightning CSS writes `.875rem`, and a probe whose inline
`!important` was outranked by a running CSS transition.
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
64bce105f8
commit
0f7595b602
+230
-45
@@ -99,7 +99,8 @@ Geist 400.
|
||||
|
||||
**Scale.** Fluid, `clamp()`, `1.25` ratio at the small end widening to `1.333` at
|
||||
the display end. Tokens `--text-2xs` through `--text-6xl` in `tokens.css`, plus
|
||||
`--text-eyebrow` at 13 px — see the eyebrow rule below for why it is not a rung.
|
||||
`--text-eyebrow` at 14 px — the same value as `--text-sm` and deliberately not an
|
||||
alias of it; see the eyebrow rule below.
|
||||
|
||||
**Rules.**
|
||||
|
||||
@@ -108,31 +109,84 @@ the display end. Tokens `--text-2xs` through `--text-6xl` in `tokens.css`, plus
|
||||
- Display line-height `0.95`–`1.05`; letter-spacing `-0.02em`.
|
||||
- Body line-height `1.6`. Measure capped at `68ch` — the old site ran full-bleed
|
||||
paragraphs at 1400 px, which is unreadable.
|
||||
- Eyebrows: mono, **13 px** (`--text-eyebrow`), `0.18em` tracking, uppercase,
|
||||
always paired with a real heading. **13 px is not a rung on the scale** — it
|
||||
sits between `--text-xs` and `--text-sm` because uppercase mono at this
|
||||
tracking reads smaller than it measures, and at 12 px it was being lost
|
||||
against the display type (Pouya, 2026-08-31; it read 11–12 px until then).
|
||||
There is **one definition**, `.eyebrow` in `global.css`; the footer's column
|
||||
headings carry that class rather than repeating it. An eyebrow is not a
|
||||
heading and never carries the `<h*>` — a real heading may carry the class.
|
||||
**"One definition" means one definition of the 13 px eyebrow.** The four 11 px
|
||||
blocks in the next bullet repeat the mono/`0.18em`/uppercase treatment
|
||||
deliberately and are not covered by it.
|
||||
- `--text-2xs` (11 px) is the compressed-label floor, not the eyebrow floor.
|
||||
**Three carve-outs, and they are deliberate rather than incidental** — do not
|
||||
read this line as licence for an 11 px label anywhere else. (a) The header
|
||||
tagline, and **it is load-bearing today, not at some future step:** 13 px takes
|
||||
the header to 83.4 px while `--header-h` is 81 px, which `global.css` feeds
|
||||
into `scroll-padding-top`. A seventh nav item is the second reason and that one
|
||||
does arrive with Insights. Both measurements are in `SiteHeader.astro`. (b) The `/bio/` print sheet, which
|
||||
`npm run bio:pdf` holds to one page. (c) On `/contact/`, both the
|
||||
`<label>`/`<legend>` set and the direct-contact `<dl>` terms.
|
||||
⚠️ **(c) is the weak one and is flagged as such.** 11 px uppercase mono
|
||||
measures 5.47 : 1 and breaches no floor in this document or in WCAG, but it
|
||||
now sits two steps below the eyebrow on the page that collects inquiries, for
|
||||
no reason beyond it having been written that way. Raised with Pouya
|
||||
2026-08-31; it is an accepted size, not a ratified one.
|
||||
- Eyebrows: mono, **14 px** (`--text-eyebrow`), `0.18em` tracking, uppercase,
|
||||
weight 500, always paired with a real heading. Pouya raised it **12 → 13 → 14 px
|
||||
on 2026-08-31**, in two passes, because uppercase mono at this tracking reads
|
||||
smaller than it measures and 13 px was still getting lost against the display
|
||||
type. There is **one definition**, `.eyebrow` in `global.css`. An eyebrow is not
|
||||
a heading and never carries the `<h*>` — but a real heading may carry the class,
|
||||
and **fourteen do, in two groups**: the footer's four column headings
|
||||
(`SiteFooter.astro`) and `/bio/`'s ten block headings.
|
||||
⚠️ **"ONE DEFINITION" HAS ONE CARVE-OUT AND IT IS NAMED RATHER THAN IMPLIED:**
|
||||
`/contact/`'s `<label>`/`<legend>` set and its direct-contact `<dt>`s repeat the
|
||||
treatment instead of taking the class, because they need `--text-secondary`
|
||||
(11.75 : 1) rather than `.eyebrow`'s `--text-meta` (5.47 : 1) — a form label is
|
||||
operative text. **Everything else about them matches, `font-weight` included**;
|
||||
without that they rendered at 400 beneath a `p.eyebrow` of the same size and
|
||||
colour, which is the divergence a carve-out is meant to bound rather than hide.
|
||||
Do not widen this to any other element.
|
||||
**14 px is the same value as `--text-sm`, and `--text-eyebrow` is deliberately
|
||||
not an alias of it.** The two move for different reasons; aliasing would mean a
|
||||
future change to body-meta type silently moved every eyebrow on the site.
|
||||
(This bullet said "13 px is not a rung on the scale — it sits between
|
||||
`--text-xs` and `--text-sm`" for one revision. At 14 px it is that rung.)
|
||||
- **THE 11 px FLOOR HAS EXACTLY ONE CONSUMER, AND THAT IS THE CLAIM THAT IS
|
||||
TRUE.** Pouya's ruling, 2026-08-31: *"form labels are operative text, and the
|
||||
site should have exactly one small-text floor."* `--text-2xs` (11 px) now has
|
||||
**one consumer in `src/`** — the header tagline (`git grep 'var(--text-2xs)' --
|
||||
src` returns one hit, `SiteHeader.astro`; 21 rendered instances, every one
|
||||
`span.eyebrow.brand-tagline`) — and nothing else may use it without a
|
||||
measurement recorded beside it.
|
||||
⚠️ **THIS BULLET SAID "THE SMALL-TEXT FLOOR IS 14 px, AND THERE IS EXACTLY ONE
|
||||
EXCEPTION" FOR ONE REVISION, AND THAT WAS FALSE** — falsified by this document
|
||||
thirty lines below, which concedes a 12 px family. The ruling asked for the
|
||||
record that the tagline is the only sub-14 px text on the site; **it is not, so
|
||||
that is not what is recorded here.** What is true is the sentence above: one
|
||||
consumer of the 11 px token. `--text-xs` (12 px) is a separate rung and is
|
||||
enumerated below.
|
||||
**The exception, and why it is deliberate rather than residual:** the tagline is
|
||||
ornamental and layout-constrained. 13 px already took the header to 83.4 px while
|
||||
`--header-h` is 81 px, which `global.css` feeds into `scroll-padding-top`; and
|
||||
with a seventh nav item the CTA lands past `.header-inner`'s content edge at
|
||||
1216, 1240, 1280 and 1440 — it does not resolve as the viewport widens. Insights
|
||||
is that seventh item. Both measurements are in `SiteHeader.astro`, and document
|
||||
overflow is 0 in every one of those cases, so no page-level check can see it.
|
||||
**Three blocks moved to `--text-eyebrow` on 2026-08-31 and their carve-outs are
|
||||
superseded.** (a) `/contact/`'s `<label>`/`<legend>` set — *raise, do not
|
||||
ratify*, superseding the "accepted, not ratified" note this bullet carried for
|
||||
one revision. (b) `/contact/`'s direct-contact `<dl>` terms, which are label
|
||||
text on the same page and would otherwise have been left a step behind the
|
||||
labels beside them. (c) `/bio/`'s ten block headings and its strap, which were
|
||||
**copies of five of `.eyebrow`'s six declarations, at 11 px** — the same escape
|
||||
the footer's column headings turned out to be — and now carry the class. Not
|
||||
byte-for-byte: the `font-size` differed, and **the missing sixth was
|
||||
`font-weight`**, which is precisely the one the print block now has to freeze.
|
||||
⚠️ **(c)'s carve-out was justified by a reason that did not apply.** This bullet
|
||||
said the `/bio/` sheet was held at 11 px because `npm run bio:pdf` holds it to
|
||||
one page. Measured 2026-08-31: the `@media print` block sets both elements to
|
||||
**7 pt**, so the screen size never reached the PDF and the one-page constraint
|
||||
was never what kept them small. **Print does now freeze `font-weight: 400`**,
|
||||
because taking `.eyebrow`'s 500 changed the printed sheet — the PDF grows from
|
||||
**89,496 to 91,151 bytes, +1,655** — and the ruling that moved them was about
|
||||
size. *(This read "63,743 bytes" for one revision. That is the `cmp -l`
|
||||
differing-byte count, not the size delta: the content stream is Flate-compressed,
|
||||
so a one-property change scrambles most of the file. Two figures, and the wrong
|
||||
one answered a question nobody asked.)* That freeze is a held decision, not a
|
||||
design position — see `bio.astro`.
|
||||
**`--text-xs` (12 px) IS A SEPARATE RUNG AND IT WAS NOT IN SCOPE ON 2026-08-31.
|
||||
Ten declaration sites, all of them:** `Pill`, `Breadcrumbs`, `CredentialRow`,
|
||||
`DefinitionGrid`, `ArticleCard`, `ProcessStep` (two), `insights/[...slug].astro`,
|
||||
and **`/bio/`'s two — `.fine` and `.sheet-contact p`**. The first eight are mono
|
||||
and uppercase or tracked at `0.06em`, a third of the eyebrow's tracking, which is
|
||||
what makes them a different treatment. **`/bio/`'s two are neither uppercase nor
|
||||
tracked**, so they are not in that family at all — they are simply 12 px text,
|
||||
and an earlier draft of this bullet defined the exception in a way that excluded
|
||||
them and therefore missed them.
|
||||
**Rendered count, and say what it is a number of:** at 1280 px / root 16 across
|
||||
all 22 pages, **130 elements carrying their own text compute to 12 px** (149 if
|
||||
elements that merely inherit the size are counted). `ArticleCard` and the article
|
||||
meta contribute **zero** today — no article is published, so neither renders.
|
||||
Every instance measures ≥ 5.01 : 1.
|
||||
- Italic display (`.it`) is the one flourish the design allows. One italic phrase
|
||||
per headline, at most.
|
||||
- Never skip a heading level. `<h1>` once per page.
|
||||
@@ -251,6 +305,12 @@ Not a polish pass. A build requirement.
|
||||
32 px, a real accessibility setting and not page zoom — `/` measured **234 px**
|
||||
of overflow at 390. Brought down in three measured steps:
|
||||
|
||||
⚠️ **THE THREE TABLES BELOW ARE A HISTORY OF HOW THE NUMBER CAME DOWN, NOT THE
|
||||
CURRENT STATE.** Every residual in their final rows — the 3 px, the 23 px and the
|
||||
63 px — went to **0 on 2026-08-31**, on all 22 pages at 320 / 360 / 390 / 414 /
|
||||
640 / 1024 px. The current state is §Reflow below, which also carries what is
|
||||
still NOT zero at 1280 px and 1920 px. Read the rows as dated steps.
|
||||
|
||||
| Fix | 390 px | 320 px |
|
||||
|---|---|---|
|
||||
| as first built | 234 px | 304 px |
|
||||
@@ -280,10 +340,13 @@ Not a polish pass. A build requirement.
|
||||
| `/med-arb/` | **0 px** | 23 px | 63 px |
|
||||
|
||||
At the **default** root size all three are **0 px at every width measured**.
|
||||
The element-level sweep at 320/root-32, predicate `right > clientWidth`,
|
||||
names **three** `PracticeCard` chips on `/mediation/` — Construction,
|
||||
Technology, Shareholder — plus the header and footer brand elements, which
|
||||
appear on all five pages. *(This read "six" for one pass. Six is the count of
|
||||
⚠️ **THE ELEMENT-LEVEL SWEEP BELOW IS ALSO HISTORICAL.** It read: *"the
|
||||
element-level sweep at 320/root-32, predicate `right > clientWidth`, names three
|
||||
`PracticeCard` chips on `/mediation/` — Construction, Technology, Shareholder —
|
||||
plus the header and footer brand elements, which appear on all five pages."*
|
||||
Re-run with that exact predicate on 2026-08-31: **0 elements**, on all five pages
|
||||
at 320 / 360 / 390 with root 32. The chips were fixed at their cause
|
||||
(`PracticeCard`'s padding) and the brand elements at theirs; see §Reflow. *(This read "six" for one pass. Six is the count of
|
||||
`article.card` with `scrollWidth > clientWidth`, a different predicate on a
|
||||
different element; `adversarial-reviewer` re-ran it and no predicate yields
|
||||
six chips. A number in this table has to be re-runnable, which is the whole
|
||||
@@ -299,27 +362,149 @@ Not a polish pass. A build requirement.
|
||||
single unbreakable 9-character name ("Lajevardi") exceeds the 224 px content
|
||||
box at 320 px; `overflow-wrap: anywhere` is the only remedy that reduces
|
||||
min-content size. `/about/` now measures equal to or better than `/` at all
|
||||
three widths, and its 320/360 residual is the same header decision.
|
||||
three widths. *(Its 320/360 residual was recorded here as "the same header
|
||||
decision" until 2026-08-31, when that attribution turned out to be wrong and the
|
||||
residual went to 0 — see below.)*
|
||||
|
||||
Command, so the numbers are re-runnable rather than quoted: headless Chrome
|
||||
over the built `dist`, `document.documentElement.style.fontSize = '32px'`, then
|
||||
`documentElement.scrollWidth - documentElement.clientWidth`, plus an
|
||||
enumeration of every element wider than `clientWidth` to name the offender.
|
||||
|
||||
Two things worth keeping. **`overflow-wrap: break-word` permits a break at
|
||||
layout time but does not reduce min-content size** — `anywhere` does, and that
|
||||
distinction was the whole of one of those fixes. And 1280 px stays over, from the header's
|
||||
deliberate `flex-wrap: nowrap` above 66 rem plus `white-space: nowrap` on the
|
||||
brand name — **602 px on `/` and 944 px on every other page**, because
|
||||
`SiteHeader` gates the tagline on `!isHome`, so the masthead is wider
|
||||
everywhere except home. *(This read a flat "602 px" until 2026-08-28. That
|
||||
figure was measured on `/` and generalised; `/about/` was already 944 when it
|
||||
was added to this table, and step 4's three pages are 944 too. Found by
|
||||
`adversarial-reviewer`.)* The 320 px residual is the same header
|
||||
plus the display headline's 104 px floor. Undoing either re-opens the measured
|
||||
step-1 header decision, so they stand. All of this is beyond what this floor
|
||||
requires — page zoom is clean — so it is a robustness margin rather than a
|
||||
failure. Revisit if a real reader hits it.
|
||||
⚠️ **THE NARROW-WIDTH RESIDUALS ARE 0. THE 1280 px AND 1920 px ONES ARE NOT, AND
|
||||
THIS PARAGRAPH CLAIMED THEY WERE.** Pouya ruled the narrow case a defect on
|
||||
2026-08-31 — *"the 152/112/82 px overflows at 320/360/390 with 32 px root text
|
||||
violate WCAG 1.4.10 and are not accepted"* — and that case is fixed. The wide
|
||||
case is a **different cause**, is **not** fixed, and is now stated correctly
|
||||
rather than reported as zero.
|
||||
|
||||
**TWO METHODS OF SIMULATING 200% TEXT, AND THEY ARE NOT EQUIVALENT. This is the
|
||||
whole of the error.** Every earlier number in this section came from the command
|
||||
below — `documentElement.style.fontSize = '32px'`. A later sweep used Chrome's
|
||||
`Page.setFontSizes({standard: 32})` instead and reported 0 everywhere, and the
|
||||
prose generalised that to *"at root 16 px and root 32 px"*.
|
||||
|
||||
| | media query `66rem` resolves to | header above 1056 px | 1280 px, root 32 |
|
||||
|---|---|---|---|
|
||||
| `documentElement.style.fontSize='32px'` | **1056 px** — matches | `sticky`, `flex-wrap: nowrap` | **944 px over** |
|
||||
| `Page.setFontSizes({standard:32})` | **2112 px** — never matches | `relative`, `flex-wrap: wrap` | **0** |
|
||||
|
||||
In a media query `rem` resolves against the **default** font size, not the root
|
||||
element's. So raising the *default* moves the breakpoints along with the type and
|
||||
the desktop nav is never reached; setting the *root* doubles the type while
|
||||
leaving the breakpoints at 16 px, which is the layout the desktop nav was
|
||||
measured in. **Both are real settings, and there is a THIRD mechanism which is
|
||||
the one a reader actually reaches.** Chrome exposes "Font size" — the default,
|
||||
the second row, which moves the breakpoints along with the type and overflows
|
||||
nothing — and, separately, **"Minimum font size", which FLOORS computed sizes
|
||||
rather than scaling them and leaves media queries alone.** Measured at 1280 px
|
||||
with `--blink-settings=minimumFontSize=32`: the `66rem` query matches, the nav is
|
||||
`sticky` / `nowrap`, `.brand-name` computes to **32 px (floored, not scaled to
|
||||
42.6 px)**, and the document is over by **830 px**. So the failure is reachable,
|
||||
and **830 px is the reachable figure while 944 px is the `documentElement`-root
|
||||
one — they are not the same measurement and must not be quoted as one.** The two
|
||||
rows below are the two simulations, not the three mechanisms.
|
||||
|
||||
**The corrected figures, `documentElement.style.fontSize='32px'`, 22 pages:**
|
||||
|
||||
| width | pages over | overflow |
|
||||
|---|---|---|
|
||||
| 320 / 360 / 390 / 414 / 640 / 1024 | **0 of 22** | **0** — the ruled targets, fixed |
|
||||
| 1280 | 22 of 22 | **944 px** on 21 pages, **508 px** on `/` |
|
||||
| 1920 | 21 of 22 | **304 px** (all but `/`) |
|
||||
|
||||
Root 16 is 0 at every width. The old **944 px** figure is **unchanged**; 602 px
|
||||
became 508 px on `/` only because `.brand-name`'s `nowrap` went.
|
||||
|
||||
⚠️ **AND AT 1280 px IT IS NOT A MARGIN — IT IS UNREACHABLE NAVIGATION.** The
|
||||
furthest element is `div.header-cta` at **2224 px** against a 1280 px viewport;
|
||||
the nav clips mid-word after "Arbitration", and **Practice (left 1378), Fees
|
||||
(1556), Contact (1666) and the header CTA are entirely off-screen** behind a
|
||||
horizontal scrollbar — including the route to the inquiry form. *(This named
|
||||
"Med-Arb" for one revision. Med-Arb is in `SECONDARY_NAV` and is not in the
|
||||
masthead at any width; the item actually lost, and the worst of them, is
|
||||
Contact.)* That is
|
||||
WCAG 1.4.4 with loss of functionality. The paragraph struck here called it *"a
|
||||
robustness margin rather than a failure. Revisit if a real reader hits it."*
|
||||
|
||||
**THE CAUSE AT 1280 px IS `flex-wrap: nowrap` ON `.nav-list` ABOVE 66 rem, AND
|
||||
THAT IS A LOCKED STEP-1 DECISION — SO IT IS AN OPEN DECISION FOR POUYA, NOT A
|
||||
FIX MADE HERE.** His instruction with the eyebrow ruling was explicit: *"if
|
||||
anything header-side does overflow, stop and report rather than improvising a
|
||||
layout change."* The options are an `em`-based breakpoint so the header drops to
|
||||
its stacked layout when the type grows, or letting the nav wrap above 66 rem and
|
||||
giving up the constant 81 px `--header-h`. Both change the desktop masthead.
|
||||
Carried on `docs/06`'s cutover checklist so it cannot ship unresolved.
|
||||
|
||||
**What the narrow-width fix DID establish, and it is worth keeping separate.**
|
||||
The narrow residual had been charged to that same `flex-wrap: nowrap` — and for
|
||||
the narrow case that attribution was **wrong**. The cause there was
|
||||
`white-space: nowrap` on `.brand-name`, a different declaration in the same
|
||||
component, and removing it **changes nothing at any real size**: the brand name
|
||||
is one line at all 16 widths at root 16, the sticky header still measures exactly
|
||||
81 px at every width from 66 rem up, and the CTA still lands exactly on
|
||||
`.header-inner`'s content edge. **A residual defended by the wrong cause is
|
||||
defended forever**, because the reason given is one nobody wants to re-open —
|
||||
which is exactly what happened for four days.
|
||||
|
||||
**The eight narrow-width fixes — no `overflow-x` was added anywhere.** Seven are
|
||||
cause-specific; the eighth is marked as the backstop it is:
|
||||
|
||||
| Element | Was | 320 px | Cause |
|
||||
|---|---|---|---|
|
||||
| `SiteHeader .brand-name` | `white-space: nowrap` removed | **63 px, all 22 pages** | Two words glued into one unbreakable box |
|
||||
| `/bio/ .rates-list` | `overflow-wrap: anywhere` | **152 px** | `https://adr.smlcompany.ca/fees/` has no break opportunity, and the single grid track it sized stretched all five rows to 424 px |
|
||||
| `/ .hero-h` | `overflow-wrap: anywhere` | 36 px | "contract," at 104 px held `.hero-copy` open |
|
||||
| `/ .feature-body` | `overflow-wrap: anywhere` | 26 px | "party-appointed" at 202 px |
|
||||
| `CredentialRow .credential-label` | `overflow-wrap: anywhere` | 38 px | "designation" needs 143 px in an 88 px track |
|
||||
| `SiteFooter .footer-brand` | `flex-wrap: wrap` | 12 px | Flex item at `min-width: auto` cannot shrink below "Lajevardi" |
|
||||
| `PracticeCard .card` | `padding` clamped | *(the cause under `Pill`)* | The space scale is rem-based, so `--space-6` is 64 px a side at root 32 — 128 px of padding in a ~224 px box |
|
||||
| `Pill` | `overflow-wrap: anywhere` | 33 px → **1 px** | ⚠️ **SYMPTOM, NOT CAUSE.** A one-word pill cannot wrap at a space that is not there |
|
||||
|
||||
`flex-wrap: wrap` on the footer brand rather than `anywhere`, because it reflows
|
||||
without hyphenating a person's name.
|
||||
|
||||
⚠️ **`Pill`'s `anywhere` IS A BACKSTOP AND THE TRADE IS RECORDED RATHER THAN
|
||||
HIDDEN.** It removes the min-content floor of a shrink-to-fit `inline-flex` box,
|
||||
so the pill collapses to whatever its parent gives it. The real cause was
|
||||
`PracticeCard`'s padding: with it clamped, "Construction" at root 32 / 320 px
|
||||
went from **94 × 220 px broken into six two-character lines** to **158 × 85 px on
|
||||
two lines**, and root 16 is unchanged at 121 × 27 px on one line. **`anywhere` is
|
||||
still load-bearing** — removing it leaves 1 px of document overflow on `/`,
|
||||
`/mediation/` and `/practice/`, and renders the pill 240 px wide inside a 224 px
|
||||
card, escaping its own rounded border. Two lines is the better of those. The
|
||||
clamp does not change any normal size: 10vw holds 32 px from 320 px up.
|
||||
|
||||
**Three instrument findings, and each one hid a real defect:**
|
||||
|
||||
1. **`overflow-wrap: break-word` permits a break at layout time but does not
|
||||
reduce min-content size** — `anywhere` does. Five of the fixes are this
|
||||
distinction. `global.css:166` sets `break-word` on **`p` AND `h1`–`h6`** —
|
||||
*(this line said "`h1`–`h6` and nothing else, so body copy inherits no
|
||||
wrapping at all", which was wrong in a way that mattered: `.feature-body`
|
||||
**is** a `<p>` and already had `break-word`, so the premise given for its fix
|
||||
was false while the fix itself was right)*. Nothing else gets one, so a
|
||||
`<span>`, `<li>`, `<dd>` or `<a>` inherits no wrapping.
|
||||
2. **`getBoundingClientRect()` reports BORDER BOXES, so an element sweep cannot
|
||||
see text spilling outside its own box.** `.credential-label`'s words ran 86 px
|
||||
past an 88 px cell while every element's rect stayed inside the viewport —
|
||||
the document was 38 px over and the offender was invisible to the predicate
|
||||
this table's own command uses. Read `scrollWidth - clientWidth` per element as
|
||||
well as per document.
|
||||
3. **Under `Emulation.setDeviceMetricsOverride({mobile: true})` the LAYOUT
|
||||
viewport expands to fit the content**, so `innerWidth` becomes 472 at a
|
||||
requested 320 and `scrollWidth - innerWidth` reads **0** while the reader is
|
||||
still scrolling sideways. The honest formula is
|
||||
`documentElement.scrollWidth - documentElement.clientWidth`, which is correct
|
||||
in both modes.
|
||||
|
||||
**What is still latent, measured and not a defect today:** `.hero-h` has **16
|
||||
scoped rules, one per page, and only 2 carry `overflow-wrap: anywhere`** (`/` and
|
||||
`/about/`). The other 14 measure 0 because their headlines' longest words are
|
||||
shorter. The single-source fix would be to change `global.css`'s `h1`–`h6` rule
|
||||
from `break-word` to `anywhere` and delete both overrides; that is a design-system
|
||||
change with a site-wide blast radius on intrinsic sizing and it has not been
|
||||
measured, so it is recorded here rather than done.
|
||||
|
||||
- **Measure the elements, not only the page.** A document-level overflow check
|
||||
passes while a flex child absorbs the deficit by being crushed — that is how
|
||||
|
||||
@@ -537,6 +537,15 @@ Not both halves of the rule.**
|
||||
long-term designation goal* row, which carries the reasoning and the
|
||||
deliberate deviation from the strategy brief. `check:claims`
|
||||
`c-med-arb-struck` sweeps `dist/`
|
||||
- [ ] **A class statement about what Ontario law does or does not gate behind an
|
||||
arbitral designation** — decided by §4 Forbidden's *"Anyone may be appointed
|
||||
an arbitrator in Ontario" / "nothing in law gates the role"* row, which
|
||||
carries the committed source and the reason the scoped replacement is
|
||||
**attributed to Pouya rather than stamped**. It bars the claim in **both**
|
||||
directions; this repository does not conclude a proposition of law.
|
||||
`check:claims` `struck-universal-q39` sweeps `dist/`. *(Added 2026-08-31,
|
||||
when Pouya ruled the §4 row into existence: this line could not exist before
|
||||
it, because an item here cites a row rather than restating a bar.)*
|
||||
- [ ] **A firm, a team, or offices that do not exist** — §4 Forbidden rows the
|
||||
specific false artefacts (*"Since 2009"*, *"sixteen years"*, the London
|
||||
and New York offices, the company number, and the fictitious founder);
|
||||
|
||||
@@ -373,7 +373,7 @@ Plausible or Fathom, cookieless, no consent banner.
|
||||
- [x] **Honeypot live.** ⚠️ **The timing check is NOT implemented** — see deviation 1 above; it is unimplementable on a CDN-cached static page and would be a control that does nothing
|
||||
- [ ] **Rate limit configured** — API Gateway throttling, 5 requests / 5 minutes per source IP. Not expressible in handler code; not done
|
||||
- [x] **The form's own protection is the `Origin` check, not CORS** — see deviation 2. CORS on the endpoint still to be restricted for scripted calls
|
||||
- [ ] **TTL set and verified by test record.** ⚠️ **THIS ONE BACKS A PUBLISHED PROMISE, AND THE SETTING WAS MEASURED OFF ON 2026-08-31.** `/legal/privacy/` states that records are deleted automatically after 24 months. The handler writes the `ttl` attribute — epoch seconds, 24 months, confirmed against this spec `[verified 2026-08-31]` — but `describe-time-to-live` returned **`DISABLED`** when Pouya first ran it, so the page promised a mechanism that was **not running**, from the day it was written. Enabling was initiated the same day with `AttributeName=ttl`; §7 records the state and deliberately does not yet stamp `ENABLED`. **The test record is what closes this, not the status:** `ENABLED` proves the setting, a record written with a near-future `ttl` and observed to vanish proves the behaviour
|
||||
- [ ] **TTL set and verified by test record.** ⚠️ **THIS ONE BACKS A PUBLISHED PROMISE.** `/legal/privacy/` states that records are deleted automatically after 24 months, and it asserts the **mechanism**, not only the period. The handler writes the `ttl` attribute — epoch seconds, 24 months, confirmed against this spec `[verified 2026-08-31]` — and **writing the attribute is not the mechanism**: TTL must also be enabled on the table, which is a table setting the code cannot see. **`AGENTS.md` §7 holds that status and its stamp; this line does not restate it** — it restated it once, went stale within the day, and had to be pulled back (§12 R19). **The test record is what closes this item, not the status:** `ENABLED` proves the setting, a record written with a near-future `ttl` and observed to vanish proves the behaviour. Tracked as §9 Q60
|
||||
- [ ] KMS customer-managed key and PITR enabled. **Neither is claimed on `/legal/privacy/`** — the page says "encrypted at rest", which is true of every DynamoDB table unconditionally, and does not mention either of these because §7 does not verify them
|
||||
- [ ] Both emails send; SPF/DKIM/DMARC aligned; inbox-tested, not spam-tested
|
||||
- [ ] DLQ and CloudWatch alarm configured. The handler writes to DynamoDB **before** sending mail, so a replay cannot lose a submission
|
||||
|
||||
@@ -534,6 +534,21 @@ Then invalidate `/*`.
|
||||
- [ ] Favicon set complete
|
||||
- [ ] Tested on iOS Safari, Android Chrome, desktop Safari/Chrome/Firefox
|
||||
- [ ] Tested at 320 px and at 200% zoom
|
||||
- [ ] ⚠️ **THE 200%-DEFAULT-TEXT RESIDUAL AT 1280 px AND 1920 px IS RULED ON,
|
||||
EITHER WAY. BLOCKING, AND IT IS A DECISION RATHER THAN A TASK.** With
|
||||
`documentElement.style.fontSize = '32px'` the site is over by **944 px on 21
|
||||
pages and 508 px on `/` at 1280 px**, and **304 px on 21 pages at 1920 px**
|
||||
— and it is not a scroll margin: the nav clips mid-word and **Practice, Fees,
|
||||
Contact and the header CTA are entirely off-screen — including the route to
|
||||
the inquiry form**, WCAG 1.4.4 with loss of functionality. The cause is `flex-wrap: nowrap` on `.nav-list` above
|
||||
66 rem, a **locked step-1 header decision**, so no fix was improvised — see
|
||||
`docs/02` §Reflow for the measurement, the two non-equivalent ways of
|
||||
simulating 200% text, and the two candidate fixes. **This item is ticked by
|
||||
Pouya either fixing it or recording it as knowingly accepted with the
|
||||
measured consequence — not by re-measuring it with the method that reports
|
||||
zero.** The narrow widths (320/360/390/414/640/1024) are fixed and are 0.
|
||||
Raised by `adversarial-reviewer`, 2026-08-31, against a record that had
|
||||
declared the whole thing fixed
|
||||
|
||||
**Infrastructure**
|
||||
- [ ] S3 versioning enabled
|
||||
|
||||
Reference in New Issue
Block a user