fix: regenerate favicon.ico with a transparent ground; tick Pouya's read-through
public/favicon.ico shipped with no transparency: all three frames declared a 32-bit alpha channel and then carried alpha=255 on every one of their 256/1024/ 2304 pixels, ground opaque cream rgba(250,247,242,255). Pouya's read-through finding, confirmed by parsing the ICO container directly. The render source carries true alpha (2,272,386 transparent px, 20,795 partial), so this is an export, not a mask derived from the cream ground — R13's harder branch did not fire and R13 is unchanged on its own terms. New scripts/icons.mjs + npm run icons re-derives the icon from the committed master: asserts the source is still the documented crop (R14), verifies a candidate file and renames on success so a rejected build cannot replace a good favicon, and runs a boundary-colour halo test. Composition is unchanged — ink bbox and pixel count identical at all three sizes. apple-touch-icon.png is byte-identical and stays opaque cream deliberately; the reason lives in docs/reference/brand-assets.md §The icon set, with the bar and a pointer in BaseLayout.astro, docs/06 and R13. docs/06: the read-through is ticked, and the cutover callout drops to ONE blocker — Q60's waiting period. Two adversarial review rounds, 15 findings, all resolved, none declined; stopped at two per D19. claims-auditor correctly deferred to cutover per D20. Gates on the committed bytes, exit status read: check 0, build 0 (23 pages), check:claims 0, check:intake 0, og:proof 0, lint 0, lighthouse 0 (worst of 23 99/100/100/100). Nothing deployed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
4735989f0b
commit
67847d94fa
+60
-15
@@ -395,8 +395,22 @@ Then invalidate `/*`.
|
||||
> reversing them puts 22 of 23 pages behind a 403 for as long as a CloudFront
|
||||
> deployment takes.
|
||||
|
||||
> 🛑 **TWO THINGS BLOCK THIS ENTIRE LIST AS AT 2026-09-02: ONE WAITING PERIOD
|
||||
> AND ONE READ-THROUGH.**
|
||||
> 🛑 **ONE THING BLOCKS THIS ENTIRE LIST AS AT 2026-09-02, AND IT IS A WAITING
|
||||
> PERIOD RATHER THAN A TASK: Q60.**
|
||||
>
|
||||
> ✅ **THE READ-THROUGH IS COMPLETE — Pouya, 2026-09-02, and it returned ONE
|
||||
> FINDING WHICH WAS NOT COPY.** `public/favicon.ico` shipped with no
|
||||
> transparency; fixed and verified the same day (see **Favicon set complete**
|
||||
> below). His read carried the approvals with it, in terms: the
|
||||
> `/legal/privacy/` §Who can see it wording, the **SML Company Ltd** consent
|
||||
> line, and `/med-arb/` **as shipped**. That discharges blocker 2 and every
|
||||
> wording sign-off that had been routed into it.
|
||||
>
|
||||
> ⚠️ **THE COUNT NOW READS ONE AGAIN, AND THE EARLIER ONE WAS A DEFECT — READ
|
||||
> THE REASON, NOT THE NUMBER.** It said ONE earlier on 2026-09-02 because an
|
||||
> approval had gone **missing** from the list; it says ONE now because the pass
|
||||
> that approval was routed into has been **done**. A tally cannot tell those
|
||||
> apart, which is the point the note below has been making all day.
|
||||
>
|
||||
> ⚠️ *(The count has moved repeatedly in one day and the DIRECTION is the only
|
||||
> part worth reading — the number of moves is deliberately not stated, because a
|
||||
@@ -421,12 +435,12 @@ Then invalidate `/*`.
|
||||
> record is written and it does not call failure before **7 days**, so
|
||||
> **start it before anything else on this page.** It is the one blocker
|
||||
> that is a waiting period rather than a task.
|
||||
> 2. **Pouya has not yet read every page against `AGENTS.md` §4.** The human
|
||||
> pass — the other half of D20, and not delegable. **It is also where the
|
||||
> §Who can see it approval now lands:** Pouya ruled on 2026-09-02 that the
|
||||
> read-through *is* the approval and that nothing is to be held open waiting
|
||||
> on a separate wording sign-off. The item under **Copy and claims** below
|
||||
> carries what to read first and why.
|
||||
> 2. ✅ **DONE 2026-09-02 — Pouya read every page against `AGENTS.md` §4.** The
|
||||
> human pass, the other half of D20 and not delegable. It was also where the
|
||||
> §Who can see it approval was routed, and his ruling that the read-through
|
||||
> *is* the approval means that sign-off is now discharged rather than
|
||||
> pending. **Sole finding: the favicon's opaque ground.** No copy finding on
|
||||
> any of the 23 pages.
|
||||
>
|
||||
> ✅ **CLOSED 2026-09-02 — Q64, MOOT.** It asked whether anyone else holds the
|
||||
> AWS root password or its MFA device, because the page published *"has no
|
||||
@@ -650,12 +664,25 @@ the decision is re-readable rather than re-litigated.
|
||||
count has been wrong twice, and this line carried "eight" for a round after
|
||||
the comment itself had been corrected to nine (`adversarial-reviewer`,
|
||||
round 2). Read the list, not a number
|
||||
- [ ] **Pouya has read every page against `AGENTS.md` §4.** The human pass. It is
|
||||
the other half of D20 and it is not delegable — his reading is what the
|
||||
per-step audit was traded for.
|
||||
⚠️ **START WITH `/legal/privacy/` §Who can see it. IT IS BLOCKER 2 IN THE
|
||||
CALLOUT ABOVE, AND THIS READ *IS* THE APPROVAL** — Pouya ruled on
|
||||
2026-09-02 that nothing waits on a separate wording sign-off. Every
|
||||
- [x] ✅ **DONE 2026-09-02 — Pouya has read every page against `AGENTS.md` §4.**
|
||||
The human pass, the other half of D20 and not delegable — his reading is
|
||||
what the per-step audit was traded for. **It returned one finding across 23
|
||||
pages and that finding was not copy:** the favicon shipped with an opaque
|
||||
cream ground. **The `/legal/privacy/` §Who can see it wording, the
|
||||
SML Company Ltd consent line and `/med-arb/` as shipped are approved by
|
||||
this read**, per his ruling that the read-through *is* the approval.
|
||||
⚠️ **This does NOT discharge `claims-auditor`'s cutover pass**, which is a
|
||||
separate item on this list: D20 traded the per-step machine audit for the
|
||||
human pass **plus** one machine pass over the finished site, and one of
|
||||
those two has now happened.
|
||||
~~⚠️ **START WITH `/legal/privacy/` §Who can see it. IT IS BLOCKER 2 IN THE
|
||||
CALLOUT ABOVE, AND THIS READ *IS* THE APPROVAL**~~ — **struck 2026-09-02:
|
||||
the pass is DONE, and an unstruck imperative on a ticked item told an
|
||||
operator to begin a read this page also records as finished, pointing at a
|
||||
blocker that no longer exists** (`adversarial-reviewer`, round 2). What it
|
||||
said remains true of what happened: Pouya ruled on
|
||||
2026-09-02 that nothing waits on a separate wording sign-off, and he read
|
||||
§Who can see it first. Every
|
||||
sentence in it changed three times that day — Q62's ruling, Q63's, then the
|
||||
ruling that cut it to **four plain statements** — and it is the only
|
||||
section on the site whose subject lives entirely outside this repository.
|
||||
@@ -972,7 +999,25 @@ the decision is re-readable rather than re-litigated.
|
||||
instead. A `Disallow` will not do it: a blocked URL can still be listed.
|
||||
Found by `adversarial-reviewer`, 2026-08-31
|
||||
- [ ] Booking link works, including the no-JavaScript fallback — **conditional on R6**; booking is parked and `CONTACT.bookingUrl` is `null`, so nothing renders and this passes vacuously until a tool is chosen. **Nothing on `/contact/` mentions booking**, deliberately
|
||||
- [ ] Favicon set complete
|
||||
- [x] ✅ **Favicon set complete, and REGENERATED 2026-09-02 — it had shipped with
|
||||
no transparency at all.** Pouya's read-through finding. All three frames
|
||||
(16/32/48) declared a 32-bit alpha channel and then carried `alpha = 255`
|
||||
on every pixel, the ground opaque cream — so the tab icon showed as a cream
|
||||
rectangle on any dark tab strip. `public/favicon.ico` is now transparent,
|
||||
regenerated by `npm run icons` from the committed master and verified
|
||||
programmatically and by eye, on dark grounds and light.
|
||||
⚠️ **`public/apple-touch-icon.png` STAYS OPAQUE CREAM AND MUST NOT BE
|
||||
"FIXED" TO MATCH.** The reason is a platform behaviour — iOS composites a
|
||||
transparent touch icon onto black — **stated by Pouya on 2026-09-02 and not
|
||||
re-tested on a handset**; the item directly below is where it would be. The
|
||||
touch icon is byte-identical across this change.
|
||||
⚠️ **AND THE CHANGE IS NOT FREE ON DARK.** The maroon half of the ribbon
|
||||
effectively drops out against a dark tab strip; the champagne half carries
|
||||
the mark. **The figures are deliberately NOT repeated here** — they live in
|
||||
`docs/reference/brand-assets.md` §The icon set, with the method, and a copy
|
||||
on this page had already gone stale within a day by quoting the 32 px row
|
||||
as if it were the general case (`adversarial-reviewer`, round 2). Read them
|
||||
there.
|
||||
- [ ] Tested on iOS Safari, Android Chrome, desktop Safari/Chrome/Firefox
|
||||
- [ ] Tested at 320 px and at 200% zoom
|
||||
- [x] ✅ **THE 200%-TEXT NAV OVERFLOW IS FIXED, 2026-09-01 — THIS ITEM IS
|
||||
|
||||
@@ -5,9 +5,22 @@ is `CLAUDE.md`'s rule and `AGENTS.md` R14, and this file exists because the
|
||||
infinity mark was reconstructed wrongly and **two adversarial review passes could
|
||||
not catch it**, since the real artwork was not in the repo to compare against.
|
||||
|
||||
**Every measurement below is `[verified 2026-08-26]`** — computed with `sharp`
|
||||
against the files in this repository, and re-derivable by anyone from the
|
||||
commands given. Nothing here is quoted from an external source.
|
||||
**The measurements here are computed with `sharp` against the files in this
|
||||
repository**, and are re-derivable by anyone from the commands given.
|
||||
|
||||
**Unless a section says otherwise, every figure below is `[verified
|
||||
2026-08-26]`. Where a section carries its own stamp, that stamp wins** — the
|
||||
render ladders are `[measured 2026-08-27]` and §The icon set is `[verified
|
||||
2026-09-02]`. ⚠️ *This line has been wrong in both directions in one week: first
|
||||
as a blanket 2026-08-26 that was already stale for the ladders, then as
|
||||
"each section carries its own stamp" when five sections carry none. It is a floor
|
||||
plus overrides because that is the only shape that covers every section without
|
||||
mis-dating one* (`adversarial-reviewer`, rounds 1 and 2).
|
||||
|
||||
⚠️ **Two things in §The icon set are NOT read off this repository and are
|
||||
labelled where they appear:** the tab-strip colours used in the contrast figures,
|
||||
and iOS's handling of a transparent touch icon. Neither is derivable from
|
||||
anything committed, so neither is stamped as if it were.
|
||||
|
||||
## Files
|
||||
|
||||
@@ -103,6 +116,138 @@ Passing an explicit `width` is load-bearing: without it Astro emits the
|
||||
untouched 2668 px master as the `<img src>` fallback — **1,146,406 bytes** —
|
||||
which any client without AVIF or WebP support would actually download.
|
||||
|
||||
## The icon set
|
||||
|
||||
`[verified 2026-09-02 — every figure below read off the icon files in this
|
||||
repository, EXCEPT the two external constants flagged inline]`
|
||||
|
||||
| File | What it is | Ground |
|
||||
|---|---|---|
|
||||
| `public/favicon.ico` | 16, 32 and 48 px frames, each a PNG-encoded 32-bit RGBA image inside the ICO container | **Transparent** |
|
||||
| `public/apple-touch-icon.png` | 180 × 180 | **Opaque cream `#faf7f2`, and that is deliberate — see below** |
|
||||
|
||||
**The two grounds differ on purpose, and this is the line that stops someone
|
||||
"fixing" it.** ⚠️ *The reason is an external platform behaviour, not a repository
|
||||
fact, and it is recorded here as what it is:* **iOS does not honour transparency
|
||||
in a touch icon — it composites it onto black**, so a transparent touch icon
|
||||
ships a black tile on the home screen. Stated by Pouya in his ruling of
|
||||
**2026-09-02** and not independently re-tested here; **it has not been checked on
|
||||
a handset in this repository, and the place that does check it is the unticked
|
||||
`docs/06` item "Tested on iOS Safari…".** The tab favicon has the opposite
|
||||
requirement: a tab strip is dark for many readers, and an opaque ground shows
|
||||
there as a visible rectangle around the mark. So the favicon is transparent, the
|
||||
touch icon is matted, and **neither should be changed to match the other.**
|
||||
|
||||
### Composition
|
||||
|
||||
The mark spans **7/8 of the canvas width**, centred on both axes — 14/16, 28/32,
|
||||
42/48, and 158/180 on the touch icon. That was measured off the icons as they
|
||||
already shipped, so a regeneration reproduces the composition rather than
|
||||
restyling the mark.
|
||||
|
||||
### Regenerating
|
||||
|
||||
```
|
||||
npm run icons
|
||||
```
|
||||
|
||||
`scripts/icons.mjs` resizes `src/assets/brand/sml-infinity-mark.png` onto a
|
||||
transparent square canvas and assembles the ICO container itself, because
|
||||
`sharp` does not write `.ico`. **It writes the favicon only** and never touches
|
||||
the touch icon. It refuses to run if the render source has no alpha channel, and
|
||||
it asserts that the source is still byte-identical to the documented crop of
|
||||
`sml-infinity-mark-master.png` — R14, so the icon stays traceable to committed
|
||||
artwork. It verifies a **candidate** file and renames it into place only on
|
||||
success, so a rejected build cannot replace a good favicon.
|
||||
|
||||
**It also carries the halo test**, because the check that matters was living
|
||||
only in prose here while the generator could not run it
|
||||
(`adversarial-reviewer`, round 2). For each frame it takes every painted pixel
|
||||
touching a fully transparent one and measures how many sit within 20 of cream:
|
||||
|
||||
| | boundary px | near cream | share |
|
||||
|---|---|---|---|
|
||||
| correct, 16 / 32 / 48 px | 61 / 146 / 258 | 1 / 2 / 5 | **1.6 / 1.4 / 1.9 %** |
|
||||
| haloed fixture, 16 px | 56 | 11 | **19.6 %** |
|
||||
|
||||
The gate is **10 %**, roughly 5× clear of both. ⚠️ **The first version of this
|
||||
guard inspected only partial-alpha pixels and MISSED the fixture completely** —
|
||||
a knockout sets alpha per pixel and leaves **no partial alpha at all**, so there
|
||||
was nothing for it to look at. The fixture is built by matting the mark on cream
|
||||
and then knocking the ground out by alpha, which is the defect exactly; it fires
|
||||
at 19.6 % and leaves `public/favicon.ico` untouched. **A guard that cannot see
|
||||
the defect it is named for is worse than none**, and this one passed the real
|
||||
icon while blind, which is the shape that ends a check instead of starting one.
|
||||
|
||||
### Why the favicon was regenerated, 2026-09-02
|
||||
|
||||
It had **no transparency at all**: all three frames declared a 32-bit alpha
|
||||
channel and then carried `alpha = 255` on every one of their 256 / 1,024 / 2,304
|
||||
pixels, with the ground opaque cream `rgba(250,247,242,255)`. Found by Pouya on a
|
||||
read-through, confirmed by parsing the container directly.
|
||||
|
||||
Three measurements stand behind the replacement.
|
||||
|
||||
**1. The composition did not change.** Composited back onto cream, the new icon
|
||||
reproduces the old matted one to within **1 of 255 on every channel of every
|
||||
pixel** at all three sizes (mean delta 0.01–0.02, 0 pixels over a delta of 8).
|
||||
So the regeneration did not restyle, rescale or reposition the mark.
|
||||
|
||||
⚠️ **That is NOT a test for a halo, and an earlier draft of this file filed it as
|
||||
one.** Composite-onto-cream returns ~0 whether the edge is correct *or* is a
|
||||
cream-matted edge that has merely had its background knocked out — the second
|
||||
case composites straight back to what it came from. Both branches pass, so the
|
||||
test cannot discriminate. Found by `adversarial-reviewer`, 2026-09-02.
|
||||
|
||||
**2. No halo — the measurement that does discriminate.** Read the RGB the
|
||||
partial-alpha pixels actually carry. A cream halo means that RGB is near cream; a
|
||||
correct export means it is the ribbon's own colour. Of the partial-alpha pixels,
|
||||
**0 of 94 / 300 / 603** are within 12 of `rgb(250,247,242)`; the nearest is 13
|
||||
away, the mean distance is **174.0 / 178.3 / 177.0**, and the mean colour per
|
||||
frame is about `rgb(118,86,74)` — maroon-brown, not cream and not black.
|
||||
|
||||
**3. Legible on dark and on light, and NOT at the same cost.** ⚠️ *The ground
|
||||
colours below are external constants, not repository facts: `#202124` is
|
||||
Chrome's dark tab strip and `#f1f3f4` its light one, both `[observed
|
||||
2026-09-02]`.* All ratios are computed on **composited** pixels, and the ink
|
||||
colours are **fully opaque** pixels only — a ratio taken from a raw channel value
|
||||
is a claim about a colour that is never painted, which is how an earlier draft
|
||||
came to quote `14.02:1` for a pixel whose alpha is 251.
|
||||
|
||||
| | darkest opaque ink | lightest opaque ink | vs `#202124` | vs `#f1f3f4` |
|
||||
|---|---|---|---|---|
|
||||
| 16 px | `rgb(70,33,33)` | `rgb(216,188,143)` | champagne **8.82:1** | maroon **12.58:1** |
|
||||
| 32 px | `rgb(60,29,29)` | `rgb(234,214,172)` | champagne **11.28:1** | maroon **13.62:1** |
|
||||
| 48 px | `rgb(61,26,26)` | `rgb(238,219,175)` | champagne **11.80:1** | maroon **13.86:1** |
|
||||
|
||||
Whichever ground it sits on, one end of the ribbon carries the silhouette. **But
|
||||
the other end does not merely dim — on dark it goes.** The maroon lobe
|
||||
composites to **1.04–1.15:1**, and counting pixels that reach 3:1 against each
|
||||
ground gives **23 / 87 / 189** on dark against **40 / 168 / 378** on light, at
|
||||
16 / 32 / 48 px. **So about half as many pixels reach 3:1 on dark as on light.**
|
||||
⚠️ *Those pixels are not absent — they are painted and fall below 3:1, and the
|
||||
mark's full outline is still there, dim. An earlier draft said "roughly half the
|
||||
mark's visible pixels are absent", which is neither what was counted (pixels at
|
||||
`alpha > 0` are 109 / 388 / 805) nor what a render shows* — `adversarial-reviewer`,
|
||||
round 2. The previous opaque-cream icon was still more legible on dark.
|
||||
|
||||
**That is the price of the change and it was accepted, not overlooked.** What was
|
||||
bought is the removal of a cream rectangle from every dark tab strip and from
|
||||
white. Raised by `adversarial-reviewer`, 2026-09-02, against a draft that
|
||||
recorded the change as costless.
|
||||
|
||||
**The obvious alternative is an icon pair keyed on `prefers-color-scheme`, and it
|
||||
was NOT ruled out on measurement.** ⚠️ *An earlier draft dismissed it on a
|
||||
mechanism that is wrong: it said the query keys off the page's colour scheme. It
|
||||
does not — it reports the user's system or browser preference, and this site
|
||||
declares `color-scheme` nowhere (`git grep -n color-scheme -- src`, exit 1), so
|
||||
it would resolve to the same preference that makes the tab strip dark.* The real
|
||||
objections are **untested here** and are recorded as such: `media` on
|
||||
`<link rel="icon">` is unevenly supported for raster icons, a browser theme can
|
||||
be set independently of the system preference, and it doubles the artefact
|
||||
`npm run icons` has to keep in sync. **If this cost is ever revisited, that is
|
||||
the option to test** — do not re-dismiss it on the reason struck above.
|
||||
|
||||
## The colours are the artwork's, not the palette's
|
||||
|
||||
`tokens.css` is not involved. The ribbon carries its own gradient and it is
|
||||
|
||||
Reference in New Issue
Block a user