feat(tuxedo): editorial photo color grade across hero/pull-quote/founder/packshot
Deploy to route.crispygoat.com / deploy (push) Successful in 4m15s

Pulls the saturated-yellow WP-import JPGs down a half-step in the brightness hierarchy so the white type stays dominant and the photos read as editorial, not product photography.

- globals.css: new filter utilities (.filter-editorial, .filter-editorial-shell with cool/amber split-tone, .filter-editorial-strong, .filter-editorial-vignette) + reduced-motion reset
- TuxedoVideoHero: grade the Ken Burns backdrop image
- tuxedo/page.tsx: apply grades to PullQuoteBand, TheCorn ear macro, FounderStrip (also swap to the retouched founder image from b90f0fa), and HarvestEditorial packshot; bump founder quality 88 -> 92
This commit is contained in:
Nora
2026-07-06 14:23:22 -06:00
parent 68851cfede
commit da09cfbd1a
3 changed files with 96 additions and 9 deletions
+84
View File
@@ -1403,3 +1403,87 @@ select:-webkit-autofill:focus {
transform: none !important; transform: none !important;
} }
} }
/* ── Tuxedo storefront: editorial photo color grade ────────────────────
* Subtle Lightroom-style treatment applied to all hero / pull-quote /
* founder / packshot / ear-macro / storm-field photos. The raw WP-import
* JPGs skew saturated-yellow and slightly flat — the corn itself reads
* garish, the shadows crushed, the highlights cheap. This filter:
* - saturate(.86) pulls the corn's yellow down so the photo doesn't
* shout louder than the white type.
* - contrast(1.06) magazine-print contrast — slightly punchier
* without crushing shadows.
* - brightness(.97) trims ~3% so the photo sits a half-step below the
* type in the brightness hierarchy.
* Stacked with a faint cool-tone overlay (see .filter-editorial-shell)
* for a split-tone effect: shadows drift toward navy/slate, highlights
* stay warm. Reads as a graded magazine photo, not a raw JPG.
*/
.filter-editorial {
filter: saturate(0.86) contrast(1.06) brightness(0.97);
}
/* Wrap an image in a .filter-editorial-shell to also apply the cool
* shadow tint. The shell uses a mix-blend-mode overlay so the tint
* blends with the photo rather than sitting on top of it.
* ::before = slate multiply (cools highlights, lifts shadows)
* ::after = amber soft-light (warms midtones back, restores the
* corn's color without bringing the saturation back) */
.filter-editorial-shell {
position: relative;
isolation: isolate;
}
.filter-editorial-shell::before {
content: "";
position: absolute;
inset: 0;
background: rgba(20, 30, 50, 0.16);
mix-blend-mode: multiply;
pointer-events: none;
z-index: 1;
}
.filter-editorial-shell::after {
content: "";
position: absolute;
inset: 0;
background: rgba(232, 163, 23, 0.07);
mix-blend-mode: soft-light;
pointer-events: none;
z-index: 2;
}
.filter-editorial-shell > img {
filter: saturate(0.86) contrast(1.06) brightness(0.97);
}
/* Heavier grade for the harvest packshot — it's the most chromatically
* dense image on the page (piles of yellow cobs) so it needs an
* extra-strong desaturation pull to read as editorial, not product
* photography. */
.filter-editorial-strong {
filter: saturate(0.78) contrast(1.10) brightness(0.95);
}
/* Subtle film vignette used on full-bleed editorial photos (packshot,
* storm field, founder). Draws the eye toward the center where the
* typography anchors. */
.filter-editorial-vignette::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(
ellipse at center,
transparent 35%,
rgba(0, 0, 0, 0.18) 80%,
rgba(0, 0, 0, 0.38) 100%
);
pointer-events: none;
z-index: 3;
}
@media (prefers-reduced-motion: reduce) {
.filter-editorial,
.filter-editorial-shell > img,
.filter-editorial-strong {
filter: none !important;
}
}
+11 -8
View File
@@ -147,8 +147,11 @@ const WP_IMAGES = {
/** Pre-storm purple sky over deep-green tasseled rows receding to /** Pre-storm purple sky over deep-green tasseled rows receding to
* mountains — the editorial pull-quote band. */ * mountains — the editorial pull-quote band. */
stormField: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-field-storm.jpg", stormField: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-field-storm.jpg",
/** White-haired founder inspecting tassels — the Our Story anchor. */ /** White-haired founder inspecting tassels — the Our Story anchor.
founderPortrait: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-founder-john.jpg", * Editorial-graded version of the original WP shot — golden-hour
* lighting, shallow DOF, sharper focus on the face. Same man,
* same overalls, same tassels — just the photo he deserves. */
founderPortrait: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-founder-john-editorial.jpg",
/** Single yellow ear with silk and dark green bokeh — the product /** Single yellow ear with silk and dark green bokeh — the product
* moment in the editorial "Why" replacement. */ * moment in the editorial "Why" replacement. */
earMacro: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-ear-macro.jpg", earMacro: "https://s3.crispygoat.com/videos/wp-import/images/tuxedo-ear-macro.jpg",
@@ -208,7 +211,7 @@ function PullQuoteBand() {
sizes="100vw" sizes="100vw"
quality={88} quality={88}
priority priority
className="object-cover -z-10" className="object-cover -z-10 filter-editorial"
/> />
{/* Layered tints: top darkens the sky, bottom grounds the type. */} {/* Layered tints: top darkens the sky, bottom grounds the type. */}
<div className="absolute inset-0 bg-gradient-to-b from-stone-950/55 via-stone-950/15 to-stone-950/80 -z-10" /> <div className="absolute inset-0 bg-gradient-to-b from-stone-950/55 via-stone-950/15 to-stone-950/80 -z-10" />
@@ -296,7 +299,7 @@ function TheCorn() {
{/* Right: macro photo, 7/12 — the photograph carries the section. */} {/* Right: macro photo, 7/12 — the photograph carries the section. */}
<div className="lg:col-span-7 order-1 lg:order-2"> <div className="lg:col-span-7 order-1 lg:order-2">
<FadeOnScroll from="right" duration={1}> <FadeOnScroll from="right" duration={1}>
<div className="relative aspect-[5/4] sm:aspect-[16/11] overflow-hidden rounded-2xl shadow-[0_30px_80px_-30px_rgba(15,40,20,0.45)] ring-1 ring-stone-900/5"> <div className="relative aspect-[5/4] sm:aspect-[16/11] overflow-hidden rounded-2xl shadow-[0_30px_80px_-30px_rgba(15,40,20,0.45)] ring-1 ring-stone-900/5 filter-editorial-shell">
<Image <Image
src={WP_IMAGES.earMacro} src={WP_IMAGES.earMacro}
alt="A single ear of Olathe Sweet corn, partially husked, silk still attached, against a field of dark green tassels" alt="A single ear of Olathe Sweet corn, partially husked, silk still attached, against a field of dark green tassels"
@@ -342,13 +345,13 @@ function FounderStrip() {
<LayoutContainer> <LayoutContainer>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-10 lg:gap-14 items-center"> <div className="grid grid-cols-1 lg:grid-cols-12 gap-10 lg:gap-14 items-center">
<FadeOnScroll from="left" className="lg:col-span-5"> <FadeOnScroll from="left" className="lg:col-span-5">
<div className="relative aspect-[4/5] sm:aspect-[5/6] overflow-hidden rounded-2xl ring-1 ring-white/10 shadow-[0_30px_80px_-30px_rgba(0,0,0,0.7)]"> <div className="relative aspect-[4/5] sm:aspect-[5/6] overflow-hidden rounded-2xl ring-1 ring-white/10 shadow-[0_30px_80px_-30px_rgba(0,0,0,0.7)] filter-editorial-shell">
<Image <Image
src={WP_IMAGES.founderPortrait} src={WP_IMAGES.founderPortrait}
alt="John Harold, founder, walking through his corn rows inspecting the tassels" alt="John Harold, founder, walking through his corn rows inspecting the tassels"
fill fill
sizes="(max-width: 1024px) 100vw, 42vw" sizes="(max-width: 1024px) 100vw, 42vw"
quality={88} quality={92}
priority priority
className="object-cover" className="object-cover"
/> />
@@ -450,7 +453,7 @@ function HarvestEditorial() {
</header> </header>
{/* Full-bleed packshot */} {/* Full-bleed packshot */}
<figure className="relative aspect-[16/9] sm:aspect-[21/10] overflow-hidden ring-1 ring-white/[0.06] shadow-[0_40px_120px_-40px_rgba(0,0,0,0.7)]"> <figure className="relative aspect-[16/9] sm:aspect-[21/10] overflow-hidden ring-1 ring-white/[0.06] shadow-[0_40px_120px_-40px_rgba(0,0,0,0.7)] filter-editorial-vignette">
<Image <Image
src={WP_IMAGES.piledCobs} src={WP_IMAGES.piledCobs}
alt="Husked Olathe Sweet cobs piled on the packing shed table the morning of pick" alt="Husked Olathe Sweet cobs piled on the packing shed table the morning of pick"
@@ -458,7 +461,7 @@ function HarvestEditorial() {
sizes="(max-width: 1024px) 100vw, 1280px" sizes="(max-width: 1024px) 100vw, 1280px"
quality={92} quality={92}
priority priority
className="object-cover animate-harvest-drift" className="object-cover animate-harvest-drift filter-editorial-strong"
/> />
{/* A single warm tint along the bottom to echo the existing {/* A single warm tint along the bottom to echo the existing
amber-wash treatment used in The Corn and FounderStrip so amber-wash treatment used in The Corn and FounderStrip so
@@ -264,7 +264,7 @@ function HeroBackdrop({
objectPosition: "center", objectPosition: "center",
zIndex: 0, zIndex: 0,
}} }}
className="select-none pointer-events-none animate-tvh-kenburns" className="select-none pointer-events-none animate-tvh-kenburns filter-editorial"
/> />
) : null} ) : null}