diff --git a/nextjs-app/app/globals.css b/nextjs-app/app/globals.css
index 70ebdea..a83b438 100644
--- a/nextjs-app/app/globals.css
+++ b/nextjs-app/app/globals.css
@@ -193,13 +193,17 @@
drawn SVG, so its colours are in the file, not here. What is left is the
ground the artwork sits on and fades into.
- --hero-ground is sampled from the artwork's own copy area (#FDF9F3),
- not from Sand. The artwork reserves an empty cream region on the left
- for the headline, and the scrim that guarantees text contrast fades from
- this colour into it — a scrim in Sand (#F5EFE6, eight to thirteen points
- darker per channel) leaves a visible seam straight down the hero. */
- --hero-ground: #FDF9F3;
- --hero-ground-rgb: 253, 249, 243;
+ --hero-ground is sampled from the artwork's own copy area, not from
+ Sand — a scrim in Sand (#F5EFE6) is far enough off to leave a visible
+ seam straight down the hero.
+
+ The artwork's copy area is not one flat colour: it runs from a peach
+ #FEE8D2 at the top to a cream #FDF3E7 around 43% height, and below ~48%
+ the left edge is foliage rather than cream. This value is sampled from
+ the middle of that pale run, where the headline and search actually sit;
+ the scrim is what covers the foliage further down. */
+ --hero-ground: #FEF2E1;
+ --hero-ground-rgb: 254, 242, 225;
/* ── Geometry & motion ──────────────────────────────────────────────
"Soft shapes, rounded corners" — the guideline's geometry is markedly
diff --git a/nextjs-app/assets/hero-source.png b/nextjs-app/assets/hero-source.png
index c010296..325939e 100644
Binary files a/nextjs-app/assets/hero-source.png and b/nextjs-app/assets/hero-source.png differ
diff --git a/nextjs-app/components/HomeView.module.css b/nextjs-app/components/HomeView.module.css
index f438e9a..252c1b0 100644
--- a/nextjs-app/components/HomeView.module.css
+++ b/nextjs-app/components/HomeView.module.css
@@ -323,15 +323,21 @@
padding: 1.75rem 1.5rem 1.75rem;
max-width: none;
}
+ /* 13rem, not 11: at 860px an 11rem band is 4.5:1, and squeezing the 3.2:1
+ crop into that throws away enough height to cut the flag off the roof and
+ the base off the building. 13rem holds it at about 3.8:1, where the
+ building stays whole. */
.heroArt {
position: static;
order: -1;
- height: 11rem;
+ height: 13rem;
}
- /* The band crop centres the schoolhouse at about 65% across, so squeezing
- toward 4.9:1 crops the empty sides rather than the subject. */
+ /* The band crop puts the schoolhouse at 73% across — reported by
+ scripts/build-hero-images.js, which derives it from the crop box rather
+ than leaving the two to drift. Squeezing narrower then crops the emptier
+ left side rather than the subject. */
.heroArt img {
- object-position: 65% center;
+ object-position: 73% center;
}
/* The scrim exists to protect text sitting on the artwork. Nothing sits on
it here, and leaving it would wash the band out. */
@@ -372,8 +378,12 @@
font-size: 1.75rem;
margin-bottom: 0.5rem;
}
+ /* 10rem, not 8.5: the band is widest-per-height right at this breakpoint —
+ at 640px an 8.5rem band is 4.2:1, worse than anything above it, because
+ the height steps down here while the width does not. 10rem keeps it near
+ 3.6:1, in line with the rest of the range. */
.heroArt {
- height: 8.5rem;
+ height: 10rem;
}
}
diff --git a/nextjs-app/components/Illustration.tsx b/nextjs-app/components/Illustration.tsx
index 2f85d6a..bd4f20a 100644
--- a/nextjs-app/components/Illustration.tsx
+++ b/nextjs-app/components/Illustration.tsx
@@ -40,8 +40,8 @@
const SIZES = '(min-width: 1400px) 1352px, (min-width: 769px) calc(100vw - 3rem), calc(100vw - 2rem)';
/** Intrinsic size of the wide crop — the aspect hint that prevents reflow. */
-const WIDE_W = 1672;
-const WIDE_H = 941;
+const WIDE_W = 2000;
+const WIDE_H = 1125;
export function HeroIllustration() {
return (
@@ -51,13 +51,13 @@ export function HeroIllustration() {
{/*
@@ -71,15 +71,15 @@ export function HeroIllustration() {
media query does, and it sits after the modern formats so they still
win where supported.
*/}
-
+
{/*
@@ -90,7 +90,7 @@ export function HeroIllustration() {
*/}
{/* eslint-disable-next-line @next/next/no-img-element */}
itself. Flattened onto the artwork's own cream so a
// JPEG (no alpha) can never composite against black.
await sharp(SRC)
- .resize({ width: 1200 })
- .flatten({ background: '#FDF9F3' })
+ .resize({ width: 1400 })
+ .flatten({ background: '#FEF2E1' })
.jpeg({ quality: 82, mozjpeg: true })
- .toFile(path.join(OUT, 'hero-wide-1200.jpg'));
+ .toFile(path.join(OUT, 'hero-wide-1400.jpg'));
const band = sharp(SRC).extract(BAND);
for (const w of BAND_WIDTHS) await emit(band, 'hero-band', w);
await sharp(SRC)
.extract(BAND)
- .resize({ width: 700 })
- .flatten({ background: '#FDF9F3' })
+ .resize({ width: 900 })
+ .flatten({ background: '#FEF2E1' })
.jpeg({ quality: 82, mozjpeg: true })
- .toFile(path.join(OUT, 'hero-band-700.jpg'));
+ .toFile(path.join(OUT, 'hero-band-900.jpg'));
const files = fs.readdirSync(OUT).filter(f => f.startsWith('hero-')).sort();
let total = 0;