Three phone defects, one of them measured (#215) - #223
Merged
Conversation
ARROWS RENDERED AS EMOJI. The external-link marker is U+2197 NORTH EAST ARROW, which has emoji presentation by DEFAULT on iOS — so every external link on a phone trailed a blue-and-white tile instead of a hairline arrow. `︎` (variation selector-15) forces text presentation. Applied in all four places that emit it: index.html, 404.html, build.mjs's nav renderer, gen-conformance. CARD COPY AT 32 CHARACTERS PER LINE. Measured at 393px, not eyeballed. These are 30-word blurbs rather than long-form prose, so the 45-75 guidance does not transfer directly — but 32 is tight even for a card, and the cost was structural: the card spent 64px of the viewport on its own inset and the wrap another 32, so a third of the screen was margin. 32 → 36 characters per line tallest card 351px → 284px (-19%) document 4776px → 4605px The page gutter stays at 16px. Dropping it to 12 buys one more character and makes the page look like it is falling off the edge. 16px of card inset is also comfortably clear of the 12px floor the card-inset gate enforces, so that gate still has room to catch a real regression. UNDERLINES THAT WERE NOT UNDERLINES. `.btn-link` drew its rule with border-bottom, which spans the padding box — so on a phone, where the colophon links stack instead of sitting in a row, each one trailed a rule wider than its own text and the section read as a list of dividers. Now text-decoration, which hugs the glyphs. The padding stays: it is the touch target, and shrinking that to fix a hairline would be a bad trade. WHAT WOULD HAVE CAUGHT THE SECOND ONE: nothing in the stack. axe scores the accessibility tree, not whitespace. The card-inset gate checks the FLOOR — text must clear its border — so it is structurally incapable of seeing a ceiling. A characters-per-line floor would have caught it; I have not added one, because that is the fourth instrument this session and the ceremony budget says stop. Recorded here instead so the choice is visible.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
From two screenshots on a phone. All three are on the live page right now.
1. The arrows were emoji
The external-link marker is U+2197 NORTH EAST ARROW, which has emoji presentation by default on iOS. Every external link on a phone trailed a blue-and-white tile instead of a hairline arrow.
︎(variation selector-15) forces text presentation.Applied in all four places that emit it:
index.html,404.html,build.mjs's nav renderer,gen-conformance.mjs.2. Card copy at 32 characters per line
Measured at 393px, not eyeballed. These are 30-word blurbs rather than long-form prose, so the 45–75 guidance doesn't transfer directly — but 32 is tight even for a card, and the cost was structural: the card spent 64px of the viewport on its own inset and the wrap another 32, so a third of the screen was margin.
The page gutter stays at 16px — dropping it to 12 buys one more character and makes the page look like it's falling off the edge. 16px of card inset is also comfortably clear of the 12px floor the card-inset gate enforces, so that gate still has room to catch a real regression.
3. Underlines that weren't underlines
.btn-linkdrew its rule withborder-bottom, which spans the padding box. On a phone, where the colophon links stack instead of sitting in a row, each one trailed a rule wider than its own text and the section read as a list of dividers. Nowtext-decoration, which hugs the glyphs.The padding stays — it's the touch target, and shrinking that to fix a hairline would be a bad trade.
What would have caught #2: nothing in the stack
You asked whether padding is an axe check. It isn't. axe scores the accessibility tree — contrast, names, roles, focus order, target size. Whitespace isn't in it.
And the card-inset gate (#216) checks the floor: text must clear its border by 12px. It is structurally incapable of seeing a ceiling — too much padding looks identical to correct padding from where it stands.
A characters-per-line floor would have caught this. I have not added one. That would be the fourth instrument this session, and the ceremony budget says stop. Recorded here so the choice is visible rather than silently skipped — say the word and it's about six lines inside the gate that already renders the page.
Verified
npm run check(23 gates) · brandmeta/content/coverage/a11y· axe (13 pages, 0 serious) ·a11y-heuristic(0 errors) ·structure-audit·legibilityPASS · and the unmerged card-inset gate from #216 run against this tree: 8 renders, all clear.Generated by Claude Code