Files
AgentCompany/landing/components/sections/bento.tsx
T
ZacharyZhang-NY 2e8121d8b9 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).
2026-07-07 23:16:56 -04:00

102 lines
3.9 KiB
TypeScript

"use client";
import { ShieldCheck } from "reicon-react/icons/ShieldCheck";
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.
const layout: { id: string; span: string }[] = [
{ id: "org-chart", span: "lg:col-span-7" },
{ id: "cost-controls", span: "lg:col-span-5" },
{ id: "office", span: "lg:col-span-5" },
{ id: "messages", span: "lg:col-span-7" },
{ id: "connectors", span: "lg:col-span-8" },
];
const featureById = new Map(featureSections.map((feature) => [feature.id, feature]));
function CornerGlow() {
return (
<div
aria-hidden="true"
className="pointer-events-none absolute -right-20 -top-20 h-56 w-56 rounded-full opacity-70"
style={{ filter: "blur(44px)", background: "radial-gradient(circle, var(--aurora-mint) 0%, transparent 70%)" }}
/>
);
}
function BentoCard({ feature, span }: { feature: FeatureSection; span: string }) {
return (
<div
className={`group relative flex flex-col overflow-hidden rounded-2xl border border-[var(--border)] bg-[var(--panel)] p-6 transition-colors duration-300 hover:border-[var(--border-strong)] lg:p-7 ${span}`}
>
<CornerGlow />
<div className="relative flex flex-col gap-1.5">
<Eyebrow>{feature.eyebrow}</Eyebrow>
<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>
<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>
);
}
function LocalFirstCard() {
return (
<div
className="relative flex flex-col justify-between overflow-hidden rounded-2xl border border-[var(--border)] p-7 lg:col-span-4"
style={{
background:
"linear-gradient(160deg, var(--aurora-mint) -40%, transparent 55%), var(--panel)",
}}
>
<span className="inline-flex h-11 w-11 items-center justify-center rounded-full bg-[var(--accent-soft)] text-[var(--accent)]">
<ShieldCheck size={22} />
</span>
<div className="mt-8">
<h3 className="text-xl font-medium tracking-[-0.02em] text-[var(--text)]">Local-first and private</h3>
<p className="mt-2 max-w-[36ch] text-sm leading-relaxed text-[var(--muted)]">
Every company runs on your machine. Data lives in a local SQLite database, secrets are held in your OS
keychain, and the only network calls go to the AI provider you connect.
</p>
</div>
</div>
);
}
export function Bento() {
return (
<section id="features" className="scroll-mt-20 py-20 md:py-28 lg:py-32">
<Container>
<Reveal>
<SectionHeading
eyebrow="The platform"
title="Everything a company needs, on your desktop"
description="One goal in — an org that hires itself, works in the open, plugs into your stack, and holds its own budget."
align="center"
className="mx-auto"
/>
</Reveal>
<Reveal delay={80} className="mt-14 grid grid-cols-1 gap-5 lg:grid-cols-12">
{layout.map(({ id, span }) => {
const feature = featureById.get(id);
return feature ? <BentoCard key={id} feature={feature} span={span} /> : null;
})}
<LocalFirstCard />
</Reveal>
</Container>
</section>
);
}