Replaces my SVG approximation of the mark with the supplied artwork.
The reconstruction was wrong, and not subtly: the real mark is a teardrop pin with a white window and a path flowing out of its base, carrying three leaves. I had drawn a circle with a separate tail.
The supplied sheet has a genuinely transparent background, so both colourways are extracted rather than traced:
file
colourway
public/brand/mark.png
teal pin, white window and path, green leaves
public/brand/mark-on-dark.png
white pin, counter knocked through to the ground
Why two colourways and not one
I rendered the teal artwork against every ground the site actually uses before deciding. It holds up on Warm White, white cards, Sand and both dark-theme grounds — but on the teal footer band it disappears, leaving only a floating white window with no silhouette.
So the header serves the teal artwork and swaps to the on-dark artwork for dark-theme viewers through a <picture> source — no JavaScript, no client boundary. The footer forces variant="onDark", because its band is teal in both themes.
Everything downstream derives from those two files
app/icon.png — favicon, replacing icon.svg
app/apple-icon.png — touch icon, replacing the generated apple-icon.tsx
the share card, which reads public/brand/mark.png off disk so it can never drift from the header
The logo sizing CSS keyed off a square box in both the header and the footer, which would have squashed a 153:189 artwork. Height now drives and width follows.
Two judgement calls
The wordmark stays live text in Manrope. The sheet's wordmark is a raster with visible edge fringing; the written style guide specifies Manrope; and live text stays selectable, scales cleanly and recolours with the theme. Easy to switch to the image if you'd rather.
Known limitation — the 512px PWA icon is slightly soft. The largest instance anywhere on the sheet is 153×189. That is ample for the header at 38px, the favicon and the share card, but a 512px icon needs upscaling. A vector (SVG/AI/EPS) dropped into public/brand fixes it and is a single swap, because every consumer goes through components/Logo.tsx or that folder.
Verification
tsc clean, 159/159 unit tests, production build green, /icon.png and /apple-icon.png emit as static routes. The header (both themes), the footer, the share card and all five icons were rendered from the compiled output and inspected.
Replaces my SVG approximation of the mark with the supplied artwork.
The reconstruction was wrong, and not subtly: the real mark is a **teardrop pin with a white window and a path flowing out of its base**, carrying three leaves. I had drawn a circle with a separate tail.
The supplied sheet has a genuinely transparent background, so both colourways are *extracted* rather than traced:
| file | colourway |
|---|---|
| `public/brand/mark.png` | teal pin, white window and path, green leaves |
| `public/brand/mark-on-dark.png` | white pin, counter knocked through to the ground |
## Why two colourways and not one
I rendered the teal artwork against every ground the site actually uses before deciding. It holds up on Warm White, white cards, Sand and **both** dark-theme grounds — but on the teal footer band it disappears, leaving only a floating white window with no silhouette.
So the header serves the teal artwork and swaps to the on-dark artwork for dark-theme viewers through a `<picture>` source — no JavaScript, no client boundary. The footer forces `variant="onDark"`, because its band is teal in *both* themes.
## Everything downstream derives from those two files
- `app/icon.png` — favicon, replacing `icon.svg`
- `app/apple-icon.png` — touch icon, replacing the generated `apple-icon.tsx`
- `public/icon-192.png`, `icon-512.png`, `icon-maskable-512.png`
- the share card, which reads `public/brand/mark.png` off disk so it can never drift from the header
The logo sizing CSS keyed off a **square** box in both the header and the footer, which would have squashed a 153:189 artwork. Height now drives and width follows.
## Two judgement calls
**The wordmark stays live text in Manrope.** The sheet's wordmark is a raster with visible edge fringing; the written style guide specifies Manrope; and live text stays selectable, scales cleanly and recolours with the theme. Easy to switch to the image if you'd rather.
**Known limitation — the 512px PWA icon is slightly soft.** The largest instance anywhere on the sheet is 153×189. That is ample for the header at 38px, the favicon and the share card, but a 512px icon needs upscaling. A vector (SVG/AI/EPS) dropped into `public/brand` fixes it and is a single swap, because every consumer goes through `components/Logo.tsx` or that folder.
## Verification
`tsc` clean, 159/159 unit tests, production build green, `/icon.png` and `/apple-icon.png` emit as static routes. The header (both themes), the footer, the share card and all five icons were rendered from the compiled output and inspected.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The mark shipped so far was my SVG approximation, and it was wrong: the real
mark is a teardrop pin with a white window and a path flowing out of its base,
carrying three leaves — not a circle with a separate tail.
Both colourways are extracted from the supplied sheet, which has a genuinely
transparent background, so these are the artwork rather than a trace:
public/brand/mark.png teal pin, white window and path, green leaves
public/brand/mark-on-dark.png white pin with the counter knocked through
Two colourways are needed, not one. Rendered against every real ground, the
teal pin holds up on Warm White, white cards, Sand and both dark-theme grounds
— but it vanishes on the teal footer band, where only the white window
survives. The header therefore serves the teal artwork and swaps to the
on-dark artwork for dark-theme viewers through a <picture> source, needing no
JavaScript; the footer forces on-dark, because its band is teal in both
themes.
Everything downstream now derives from those two files: the favicon
(app/icon.png, replacing icon.svg), the touch icon (app/apple-icon.png,
replacing the generated apple-icon.tsx), the three PWA rasters, and the share
card, which reads public/brand/mark.png off disk so it can never drift from
the header. The logo sizing CSS keyed off a square box, which would have
squashed a 153:189 artwork — height now drives and width follows.
The wordmark stays live text in Manrope. The sheet's wordmark is a raster with
visible edge fringing, and the written style guide specifies Manrope; live
text also stays selectable, scales cleanly and recolours with the theme.
KNOWN LIMITATION: the largest instance on the sheet is 153×189. That is ample
for the header at 38px, the favicon and the share card, but short of the 512px
PWA icon, which is upscaled and slightly soft. A vector would fix it and is a
single swap — every consumer goes through components/Logo.tsx or public/brand.
Verified: tsc clean, 159/159 tests, build green, /icon.png and /apple-icon.png
emit as static routes, and the header, footer, share card and all five icons
were rendered and inspected in both themes.
This PR replaces the site's programmatically-generated SVG logo/favicon/OG-image system with supplied raster brand artwork (mark.png / mark-on-dark.png), updating the favicon, apple-touch-icon, manifest, header, and footer to use the new PNGs. The change is otherwise clean and well-reasoned (CSP/cache headers and Next.js icon conventions updated consistently), with one real but cosmetic aspect-ratio bug.
🟡 Minor
nextjs-app/components/Logo.tsx: LogoMark computes width from a single hardcoded ASPECT (153/189, derived from mark.png) for both colourways, but mark-on-dark.png's actual intrinsic ratio is 98x112 (~0.875), not ~0.810. Since both call sites (Footer's onDark variant, and Navigation's auto variant for OS dark-mode viewers) rely on CSS width:auto/height:100%, the mismatched width/height attributes will cause the on-dark mark to render stretched or shift on load.
## 🤖 AI Code Review (Claude Code)
This PR replaces the site's programmatically-generated SVG logo/favicon/OG-image system with supplied raster brand artwork (mark.png / mark-on-dark.png), updating the favicon, apple-touch-icon, manifest, header, and footer to use the new PNGs. The change is otherwise clean and well-reasoned (CSP/cache headers and Next.js icon conventions updated consistently), with one real but cosmetic aspect-ratio bug.
### 🟡 Minor
- **nextjs-app/components/Logo.tsx**: LogoMark computes width from a single hardcoded ASPECT (153/189, derived from mark.png) for both colourways, but mark-on-dark.png's actual intrinsic ratio is 98x112 (~0.875), not ~0.810. Since both call sites (Footer's onDark variant, and Navigation's auto variant for OS dark-mode viewers) rely on CSS width:auto/height:100%, the mismatched width/height attributes will cause the on-dark mark to render stretched or shift on load.
LogoMark derived width from a single hardcoded 153/189, taken from mark.png,
while mark-on-dark.png was 98×112. Both call sites size the mark with
height:100%/width:auto, so the rendered size came out right in the end — but
the width/height attributes are the pre-load aspect hint, so the on-dark
artwork reserved the wrong box and reflowed on load. Any future call site
without that CSS would have rendered it stretched outright.
Per-variant attributes would not have fixed it. variant="auto" is a single
<img> whose srcset swaps the file underneath it, so one set of attributes has
to serve both colourways; the only correct fix is for the two files to share
a ratio.
They also had different artwork ratios (0.810 against 0.833) and different
padding, which the review did not reach: the logo changed size slightly
whenever the OS theme flipped. Both are now written onto one 176×208 canvas
with the artwork at the same height, centred, so they are drop-in swappable.
Measured on the built output, header mark, before → after:
light attr 31×38, rendered 30.75×38 → attr 32×38, rendered 32.15×38
dark attr 31×38, rendered 33.25×38 → attr 32×38, rendered 32.15×38
A 2.25px reflow and a cross-theme size jump both become 0.15px of rounding.
The share card reads the same file and had its own hardcoded 45×56, which the
re-crop would have stretched; it is now 47×56, with a comment tying it to the
canvas. The comment on ASPECT records that re-cropping either file means
re-normalising both.
Verified: tsc clean, 159/159 tests, build green, and both files report
naturalWidth 176 × naturalHeight 208 in the browser.
tudor
merged commit 6b117dd26c into main2026-08-08 21:41:47 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Replaces my SVG approximation of the mark with the supplied artwork.
The reconstruction was wrong, and not subtly: the real mark is a teardrop pin with a white window and a path flowing out of its base, carrying three leaves. I had drawn a circle with a separate tail.
The supplied sheet has a genuinely transparent background, so both colourways are extracted rather than traced:
public/brand/mark.pngpublic/brand/mark-on-dark.pngWhy two colourways and not one
I rendered the teal artwork against every ground the site actually uses before deciding. It holds up on Warm White, white cards, Sand and both dark-theme grounds — but on the teal footer band it disappears, leaving only a floating white window with no silhouette.
So the header serves the teal artwork and swaps to the on-dark artwork for dark-theme viewers through a
<picture>source — no JavaScript, no client boundary. The footer forcesvariant="onDark", because its band is teal in both themes.Everything downstream derives from those two files
app/icon.png— favicon, replacingicon.svgapp/apple-icon.png— touch icon, replacing the generatedapple-icon.tsxpublic/icon-192.png,icon-512.png,icon-maskable-512.pngpublic/brand/mark.pngoff disk so it can never drift from the headerThe logo sizing CSS keyed off a square box in both the header and the footer, which would have squashed a 153:189 artwork. Height now drives and width follows.
Two judgement calls
The wordmark stays live text in Manrope. The sheet's wordmark is a raster with visible edge fringing; the written style guide specifies Manrope; and live text stays selectable, scales cleanly and recolours with the theme. Easy to switch to the image if you'd rather.
Known limitation — the 512px PWA icon is slightly soft. The largest instance anywhere on the sheet is 153×189. That is ample for the header at 38px, the favicon and the share card, but a 512px icon needs upscaling. A vector (SVG/AI/EPS) dropped into
public/brandfixes it and is a single swap, because every consumer goes throughcomponents/Logo.tsxor that folder.Verification
tscclean, 159/159 unit tests, production build green,/icon.pngand/apple-icon.pngemit as static routes. The header (both themes), the footer, the share card and all five icons were rendered from the compiled output and inspected.🤖 Generated with Claude Code
🤖 AI Code Review (Claude Code)
This PR replaces the site's programmatically-generated SVG logo/favicon/OG-image system with supplied raster brand artwork (mark.png / mark-on-dark.png), updating the favicon, apple-touch-icon, manifest, header, and footer to use the new PNGs. The change is otherwise clean and well-reasoned (CSP/cache headers and Next.js icon conventions updated consistently), with one real but cosmetic aspect-ratio bug.
🟡 Minor