Enrich the landing page with a bento grid and aurora atmosphere
Close the flat-vs-adaline gap by adding depth and motion to our product shots: - bento: replace the flat stacked features with a varied 12-column grid (org chart, cost, office, messages, connectors, plus a local-first highlight card), each with a corner glow and hover - showcase: a dark aurora "Set the goal" statement band (Newsreader serif over a drifting northern-lights glow) for a light -> dark -> light rhythm - hero + footer: aurora glow staging behind the dashboard and under the CTA - ui/aurora + globals: mint/teal/lime drift-animated glow tokens - remove the superseded flat feature components e2e green (12 passed); build verified.
This commit is contained in:
1 parent
4f0d03ad72
commit
8f1a5f1f4e
9 files changed
+199
-42
No files matched your search
@@ -47,6 +47,9 @@
|
||||
--glow-warm: rgba(32, 59, 20, 0.05);
|
||||
--glow-accent: rgba(99, 143, 61, 0.06);
|
||||
--section-alt: rgba(32, 59, 20, 0.02);
|
||||
--aurora-mint: rgba(94, 236, 151, 0.22);
|
||||
--aurora-teal: rgba(45, 212, 191, 0.16);
|
||||
--aurora-lime: rgba(137, 175, 84, 0.16);
|
||||
}
|
||||
|
||||
/* ── Dark theme (Material-3 dark surfaces + mint primary) ── */
|
||||
@@ -81,6 +84,9 @@
|
||||
--glow-warm: rgba(94, 236, 151, 0.05);
|
||||
--glow-accent: rgba(94, 236, 151, 0.04);
|
||||
--section-alt: rgba(94, 236, 151, 0.03);
|
||||
--aurora-mint: rgba(94, 236, 151, 0.3);
|
||||
--aurora-teal: rgba(45, 212, 191, 0.22);
|
||||
--aurora-lime: rgba(137, 175, 84, 0.18);
|
||||
}
|
||||
|
||||
/* ── Base ── */
|
||||
@@ -201,6 +207,24 @@ body {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* ── Aurora: slow-drifting gradient light for dark showcase surfaces ── */
|
||||
@keyframes aurora-drift {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: translate3d(-4%, 3%, 0) scale(1.12);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.aurora-layer {
|
||||
animation: aurora-drift 20s ease-in-out infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* ── Reduced motion ── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Bento } from "../components/sections/bento";
|
||||
import { DownloadSection } from "../components/sections/download-section";
|
||||
import { FAQ } from "../components/sections/faq";
|
||||
import { Features } from "../components/sections/features";
|
||||
import { Footer } from "../components/layout/footer";
|
||||
import { Hero } from "../components/sections/hero";
|
||||
import { HowItWorks } from "../components/sections/how-it-works";
|
||||
import { Navbar } from "../components/layout/navbar";
|
||||
import { Runtimes } from "../components/sections/runtimes";
|
||||
import { Showcase } from "../components/sections/showcase";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
@@ -22,7 +23,8 @@ export default function Page() {
|
||||
<main id="main">
|
||||
<Hero />
|
||||
<Runtimes />
|
||||
<Features />
|
||||
<Bento />
|
||||
<Showcase />
|
||||
<HowItWorks />
|
||||
<FAQ />
|
||||
<DownloadSection />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Container } from "../ui/container";
|
||||
import { Reveal } from "../ui/reveal";
|
||||
import { Button } from "../ui/button";
|
||||
import { Aurora } from "../ui/aurora";
|
||||
import { IconMark } from "../brand/icon-mark";
|
||||
import { getTrackedDownloadHref } from "../../lib/downloads";
|
||||
import { CONTACT_EMAIL, WEBSITE_URL } from "../../lib/site-constants";
|
||||
@@ -40,8 +41,9 @@ export function Footer() {
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<footer className="bg-[var(--footer-bg)] text-[var(--footer-text)]">
|
||||
<Container>
|
||||
<footer className="relative overflow-hidden bg-[var(--footer-bg)] text-[var(--footer-text)]">
|
||||
<Aurora className="opacity-90" />
|
||||
<Container className="relative">
|
||||
<div className="border-b border-white/10 py-24 text-center md:py-32">
|
||||
<Reveal>
|
||||
<h2 className="font-display text-[clamp(2.75rem,1.8rem+4vw,5.5rem)] leading-[1] tracking-[-0.02em]">
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
"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 { 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>
|
||||
<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>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Reveal } from "../ui/reveal";
|
||||
import { SectionHeading } from "../ui/section-heading";
|
||||
import { MediaFrame } from "../ui/media-frame";
|
||||
import type { FeatureSection as FeatureSectionData } from "../../lib/landing-content";
|
||||
|
||||
/** One feature: heading + subhead above a full-width product panel (adaline rhythm). */
|
||||
export function FeatureSection({ feature }: { feature: FeatureSectionData }) {
|
||||
return (
|
||||
<div id={feature.id} className="flex scroll-mt-24 flex-col gap-8 md:gap-10">
|
||||
<Reveal>
|
||||
<SectionHeading eyebrow={feature.eyebrow} title={feature.title} description={feature.description} />
|
||||
</Reveal>
|
||||
<Reveal delay={90}>
|
||||
<MediaFrame src={feature.image} alt={feature.imageAlt} />
|
||||
</Reveal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Container } from "../ui/container";
|
||||
import { FeatureSection } from "./feature-section";
|
||||
import { featureSections } from "../../lib/landing-content";
|
||||
|
||||
export function Features() {
|
||||
return (
|
||||
<section id="features" className="scroll-mt-20 py-20 md:py-28 lg:py-32">
|
||||
<Container className="flex flex-col gap-24 md:gap-32">
|
||||
{featureSections.map((feature) => (
|
||||
<FeatureSection key={feature.id} feature={feature} />
|
||||
))}
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -52,12 +52,25 @@ export function Hero() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="enter-rise mt-14 md:mt-20" style={{ animationDelay: "0.3s" }}>
|
||||
<MediaFrame
|
||||
src="/images/dashboard.webp"
|
||||
alt="AgentCompany desktop dashboard showing the quarter goal, budget, agent workload, and recent runs"
|
||||
priority
|
||||
<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="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>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Container } from "../ui/container";
|
||||
import { Reveal } from "../ui/reveal";
|
||||
import { Aurora } from "../ui/aurora";
|
||||
|
||||
export function Showcase() {
|
||||
return (
|
||||
<section className="relative overflow-hidden bg-[var(--band)] text-[var(--band-text)]">
|
||||
<Aurora />
|
||||
<Container className="relative py-24 md:py-32 lg:py-40">
|
||||
<Reveal className="mx-auto max-w-4xl text-center">
|
||||
<p className="eyebrow text-sm opacity-60">One human in the loop</p>
|
||||
<h2 className="mt-6 font-serif text-[clamp(2.25rem,1.4rem+3.6vw,4.5rem)] font-light leading-[1.05] tracking-[-0.02em]">
|
||||
Set the goal.
|
||||
<br />
|
||||
The company forms around it.
|
||||
</h2>
|
||||
<p className="mx-auto mt-6 max-w-[52ch] text-lg leading-relaxed opacity-75">
|
||||
An AI CEO hires the roles the mission needs, delegates the work, and reports back — while you keep the final
|
||||
say on every decision that matters.
|
||||
</p>
|
||||
</Reveal>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Northern-lights glow for dark showcase surfaces: three soft, slowly drifting
|
||||
* radial blooms in mint / teal / lime. Purely decorative.
|
||||
*/
|
||||
export function Aurora({ className = "" }: { className?: string }) {
|
||||
return (
|
||||
<div aria-hidden="true" className={`pointer-events-none absolute inset-0 overflow-hidden ${className}`}>
|
||||
<div
|
||||
className="aurora-layer absolute -inset-[25%]"
|
||||
style={{
|
||||
filter: "blur(56px)",
|
||||
background:
|
||||
"radial-gradient(42% 55% at 22% 62%, var(--aurora-mint) 0%, transparent 62%)," +
|
||||
"radial-gradient(38% 50% at 72% 38%, var(--aurora-teal) 0%, transparent 60%)," +
|
||||
"radial-gradient(34% 44% at 52% 84%, var(--aurora-lime) 0%, transparent 58%)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user