eddf74745f86c9c6d9eb07d867246ff9cc90dc20
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eddf74745f |
feat(home): swap in the higher-fidelity hero artwork
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 10s
PR Checks / Build Frontend (no push) (pull_request) Successful in 43s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 13s
Same 16:9 frame, but not a drop-in replacement — the composition, palette and
copy area all moved, and each one drives a change here.
COPY AREA
The old artwork was a flat #FDF9F3 down its whole left side. This one runs
peach #FEE8D2 at the top to cream #FDF3E7 around 43% height, and below ~48%
the left edge is foliage rather than cream at all. --hero-ground is resampled
to #FEF2E1, the middle of the pale run where the headline and search actually
sit; the scrim covers the foliage further down.
Measured on rendered pixels with the text hidden, sampling the real glyph runs
(via Range, not the element boxes) plus a 120px growth margin:
title body byline
light 13.61:1 5.74:1 6.66:1
dark 9.49:1 5.45:1 8.35:1
Body drops from 6.52:1 to 5.74:1 as the foliage comes closer, still clear.
BAND CROP
The schoolhouse moved to ~82% across the frame, leaving only ~140px of artwork
to its right, so the band crop is anchored to the right edge and takes 1344px
back — putting the school at 73%, which the build script now derives and
prints rather than leaving it to drift from the CSS.
The crop is also 3.2:1 rather than matching the phone. The band is not one
ratio: it runs 2.4:1 on a phone to about 3.8:1 under the one-column
breakpoint. Cropping at the narrow end means the wide end throws away height,
which cut the flag off the roof and the base off the building. Sitting above
the middle costs a little width on phones — where the crop's left is hillside —
and keeps the building whole where it matters.
BAND HEIGHTS
Raised to 13rem (861–860px) and 10rem (≤640px). The band was widest-per-height
at exactly 640px, where an 8.5rem band measured 4.2:1 — worse than any wider
viewport, because the height steps down at that breakpoint while the width does
not. Ratios across the range are now 2.0 / 2.6 / 3.6 / 3.1 / 3.8 rather than
spiking. The search still lands at 442px on a 667px viewport.
WEIGHT
Source is 3.1MB; a browser fetches one file — 29–59kB on desktop, 10–14kB on a
phone. Widths re-cut for the larger master: 2000/1400/1000 wide, 1344/900/600
band.
Verified: 0 AA failures across both themes at 1440 / 860 / 390, every srcset
entry present on disk with no orphans, tsc clean, 159/159, build green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
3f0e05cc99 |
feat(home): use the supplied hero artwork instead of a drawn one
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m3s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 46s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m29s
Replaces the hand-drawn SVG landscape with the illustration supplied by the project owner. Master is assets/hero-source.png; everything under public/brand/hero-* comes from scripts/build-hero-images.js and should never be hand-edited. LAYOUT The artwork is composed as a full-bleed hero: it reserves an empty cream area down its left side for the headline. The old hero was a two-column grid with art in the right 0.88fr, which would have cropped that reserved area off and shrunk the scene into a thumbnail — the one thing the picture is built not to be. So the panel is now a single layered block: artwork behind, copy on top, and below the one-column breakpoint the artwork leaves the background and becomes a band under the search. Overlaying does not survive down to phone widths — the panel gets too narrow for the copy to stay inside the cream, so the scrim would have to cover nearly the whole image and you would be left with a tinted rectangle. Hence the switch at 860px rather than a single treatment stretched across every width. CONTRAST The copy sits on a gradient of --hero-ground, a new token sampled from the artwork's own cream (#FDF9F3) rather than from Sand. Sand is eight to thirteen points darker per channel, which leaves a visible seam straight down the hero. The scrim exists because the artwork is a fixed image on a fluid panel: past some width the headline would otherwise land on hillside green. Measured on rendered pixels, sampling background up to 120px beyond the right edge of each line, so a longer line still has margin: light title 14.36:1 body 6.52:1 dark title 11.01:1 body 6.44:1 The worst light case is hillside green showing through the scrim at 6.52:1. TWO CROPS The slot is two shapes: roughly 2.1:1–2.7:1 behind the desktop panel, and 2.6:1–4.9:1 as the band. A single file under object-fit: cover centre-crops, and at the band's extreme that slices a strip through the scene and loses the schoolhouse — exactly how the drawn hero failed on phones. <picture> switches crop, not just resolution: the band file is pre-cropped around the school and is already near 2.6:1, with the subject at ~65% across so squeezing toward 4.9:1 crops the empty sides instead. WEIGHT 1.6 MB PNG in, AVIF and WebP out; a browser fetches exactly one file — about 23–33 kB on desktop, 9–18 kB on a phone. The JPEG is only the <img> fallback. `sizes` describes the real panel box (max-width 1400 minus padding) rather than 100vw, which over-requested a candidate at every width on the LCP element. DARK THEME A raster cannot be re-graded token by token the way the drawing was, but it would reproduce the same failure — a bright illustration is the brightest object on a near-black page. It is dimmed in CSS to read as dusk, and the scrim fades it into the dark panel rather than into cream. TESTS The two illustration journeys are replaced by three, each covering a failure that still renders a valid-looking page: the artwork actually loading (naturalWidth, not src), the crop switching at the breakpoint, a modern format winning negotiation, and the dark theme dimming it. public/brand/CREDITS.md records provenance for every asset in that folder. The hero's licence line is marked unconfirmed — that one needs the owner. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9ee4d45a94 |
fix(brand): give both logo colourways one canvas so the aspect hint is right
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m1s
PR Checks / Backend Smoke (pull_request) Successful in 8s
PR Checks / Build Backend (no push) (pull_request) Successful in 35s
PR Checks / Build Frontend (no push) (pull_request) Successful in 44s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 1m11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 10s
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. |
||
|
|
b11ee3c8de |
feat(brand): use the supplied logo artwork instead of a reconstruction
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 12s
PR Checks / Build Frontend (no push) (pull_request) Successful in 49s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m7s
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. |