Give product screenshots a painterly atmospheric stage

Float each screenshot over an ambient wash painted from its own colours (a tiny
blurred thumbnail), layered with the aurora, a designed green->teal gradient,
and fine film grain — the "based on our real product screenshot" treatment.
- ui/art-stage: reusable atmospheric stage (ambient LQIP + aurora + grain + a
  floating shot with depth)
- hero + bento: swap the flat frames for ArtStage
- public/images/ambient: per-screenshot colour-wash thumbnails (<250B each)
- remove the now-unused media-frame

e2e green (12 passed).
This commit is contained in:
ZacharyZhang-NY committed 2026-07-07 23:16:56 -04:00
1 parent 8f1a5f1f4e
commit 2e8121d8b9
10 files changed
+83 -59

No files matched your search

+8 -11
View File
@@ -5,6 +5,7 @@ import { Container } from "../ui/container";
import { Reveal } from "../ui/reveal";
import { Eyebrow } from "../ui/eyebrow";
import { SectionHeading } from "../ui/section-heading";
import { ArtStage } from "../ui/art-stage";
import { featureSections, type FeatureSection } from "../../lib/landing-content";
// Explicit order + column spans so the cells pack into full 12-column rows.
@@ -39,17 +40,13 @@ function BentoCard({ feature, span }: { feature: FeatureSection; span: string })
<h3 className="text-xl font-medium tracking-[-0.02em] text-[var(--text)]">{feature.title}</h3>
<p className="max-w-[46ch] text-sm leading-relaxed text-[var(--muted)]">{feature.description}</p>
</div>
<div className="relative mt-6 overflow-hidden rounded-xl border border-[var(--border)] bg-[var(--panel-illustration)] shadow-[0_18px_50px_-24px_rgba(10,29,8,0.28)]">
<img
src={feature.image}
alt={feature.imageAlt}
width={2400}
height={1500}
loading="lazy"
decoding="async"
className="block aspect-[16/10] w-full object-cover object-top transition-transform duration-500 group-hover:scale-[1.02]"
/>
</div>
<ArtStage
src={feature.image}
alt={feature.imageAlt}
className="mt-6"
stageClassName="flex aspect-[16/10] items-center justify-center p-4 sm:p-5"
contentClassName="max-h-full w-auto max-w-full object-contain transition-transform duration-500 group-hover:scale-[1.02]"
/>
</div>
);
}
+7 -19
View File
@@ -1,7 +1,7 @@
import { Container } from "../ui/container";
import { Badge } from "../ui/badge";
import { Button } from "../ui/button";
import { MediaFrame } from "../ui/media-frame";
import { ArtStage } from "../ui/art-stage";
import { landingHeroNarrative } from "../../lib/product-narrative";
export function Hero() {
@@ -52,25 +52,13 @@ export function Hero() {
</p>
</div>
<div className="enter-rise relative mt-14 md:mt-20" style={{ animationDelay: "0.3s" }}>
<div
aria-hidden="true"
className="pointer-events-none absolute -inset-x-8 -top-10 bottom-0"
style={{
filter: "blur(52px)",
background:
"radial-gradient(55% 45% at 50% 22%, var(--aurora-mint) 0%, transparent 70%)," +
"radial-gradient(45% 40% at 22% 65%, var(--aurora-teal) 0%, transparent 72%)," +
"radial-gradient(45% 42% at 80% 60%, var(--aurora-lime) 0%, transparent 72%)",
}}
<div className="enter-rise mt-14 md:mt-20" style={{ animationDelay: "0.3s" }}>
<ArtStage
src="/images/dashboard.webp"
alt="AgentCompany desktop dashboard showing the quarter goal, budget, agent workload, and recent runs"
priority
stageClassName="p-5 sm:p-8 md:p-12 lg:p-14"
/>
<div className="relative z-10">
<MediaFrame
src="/images/dashboard.webp"
alt="AgentCompany desktop dashboard showing the quarter goal, budget, agent workload, and recent runs"
priority
/>
</div>
</div>
</Container>
</section>