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;