diff --git a/landing/app/globals.css b/landing/app/globals.css
index b8480d5f..97be94da 100644
--- a/landing/app/globals.css
+++ b/landing/app/globals.css
@@ -179,17 +179,24 @@ body {
animation: rise-enter 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}
-/* Scroll-reveal primitive: hidden until IntersectionObserver marks it in view. */
+/*
+ * Scroll-reveal primitive. Progressive enhancement: content is visible by
+ * default and only starts hidden once the `js` class is present, so the page
+ * stays fully readable if scripts never run.
+ */
.reveal {
- opacity: 0;
- transform: translateY(16px);
transition:
opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
transition-delay: var(--reveal-delay, 0ms);
}
-.reveal[data-in-view="true"] {
+.js .reveal {
+ opacity: 0;
+ transform: translateY(16px);
+}
+
+.js .reveal[data-in-view="true"] {
opacity: 1;
transform: translateY(0);
}
@@ -208,7 +215,7 @@ body {
transition-duration: 0.01ms !important;
}
- .reveal {
+ .js .reveal {
opacity: 1;
transform: none;
}
diff --git a/landing/app/layout.tsx b/landing/app/layout.tsx
index 4982762e..c8cf55de 100644
--- a/landing/app/layout.tsx
+++ b/landing/app/layout.tsx
@@ -99,7 +99,7 @@ export const metadata: Metadata = {
};
const themeScript = `
-(function(){try{var t=localStorage.getItem("agentcompany-theme");if(t==="dark"||(!t&&window.matchMedia("(prefers-color-scheme:dark)").matches)){document.documentElement.classList.add("dark")}}catch(e){}})();
+(function(){document.documentElement.classList.add("js");try{var t=localStorage.getItem("agentcompany-theme");if(t==="dark"||(!t&&window.matchMedia("(prefers-color-scheme:dark)").matches)){document.documentElement.classList.add("dark")}}catch(e){}})();
`;
const softwareJsonLd = {
diff --git a/landing/app/page.tsx b/landing/app/page.tsx
index 769e26dd..dbde0cd3 100644
--- a/landing/app/page.tsx
+++ b/landing/app/page.tsx
@@ -1,10 +1,10 @@
import { DownloadSection } from "../components/download-section";
import { FAQ } from "../components/faq";
-import { Features } from "../components/features";
+import { Features } from "../components/sections/features";
import { Footer } from "../components/footer";
-import { Hero } from "../components/hero";
+import { Hero } from "../components/sections/hero";
import { HowItWorks } from "../components/how-it-works";
-import { Navbar } from "../components/navbar";
+import { Navbar } from "../components/layout/navbar";
import { RuntimesBar } from "../components/runtimes-bar";
export default function Page() {
diff --git a/landing/components/features.tsx b/landing/components/features.tsx
deleted file mode 100644
index 26d77088..00000000
--- a/landing/components/features.tsx
+++ /dev/null
@@ -1,191 +0,0 @@
-"use client";
-
-import { motion } from "framer-motion";
-
-const features = [
- {
- number: "01",
- title: "One-Click Company Creation",
- description:
- "Name your company, describe your mission, connect your AI runtime, and launch. Your first agents start working in under a minute.",
- image: "/screenshots/Onboarding.jpeg",
- imageAlt: "Company creation onboarding flow with mission and runtime setup",
- imageLeft: true,
- },
- {
- number: "02",
- title: "Self-Organizing Teams",
- description:
- "Your AI CEO builds the org chart. It identifies the roles needed, hires specialists, and creates reporting lines — all from a single goal.",
- image: "/screenshots/Auto-OrgChart-Team.jpeg",
- imageAlt: "AI-generated org chart showing self-organizing team structure",
- imageLeft: false,
- },
- {
- number: "03",
- title: "Autonomous Task Management",
- description:
- "Goals break down into tasks automatically. Agents pick up work, report progress, and escalate blockers — you decide when to step in.",
- image: "/screenshots/Auto-Task.jpeg",
- imageAlt: "Autonomous task board with agents managing work items",
- imageLeft: true,
- },
- {
- number: "04",
- title: "Real-Time Agent Communication",
- description:
- "Agents communicate through department channels and direct messages. Watch strategic decisions happen in real time, like a Slack workspace you built.",
- image: "/screenshots/AI-Internal-Realtime-Message.jpeg",
- imageAlt: "Real-time messaging between AI agents in department channels",
- },
- {
- number: "05",
- title: "Human-in-the-Loop Approvals",
- description:
- "Stay in control. Critical decisions surface for your review. Approve, reject, or redirect — your company respects the chain of command.",
- image: "/screenshots/Approval-by-Human.jpeg",
- imageAlt: "Approval interface showing human review of agent decisions",
- },
- {
- number: "06",
- title: "AI Document Generation",
- description:
- "Business plans, marketing strategies, technical specs — agents draft and iterate on real deliverables, stored in your document center.",
- image: "/screenshots/Document-Center.jpeg",
- imageAlt: "Document center with AI-generated business deliverables",
- },
-];
-
-function FeaturePair({ feature }: { feature: (typeof features)[number] }) {
- const { number, title, description, image, imageAlt, imageLeft } = feature;
- const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];
-
- const media = (
-
-
-

-
-
- );
-
- const copy = (
-
-
- {number}
-
-
-
-
- {number}
-
-
{title}
-
{description}
-
-
- );
-
- return (
-
- {media}
- {copy}
-
- );
-}
-
-export function Features() {
- return (
-
-
-
-
- Features
-
-
- Your Company, Under the Hood
-
-
-
-
- {features.slice(0, 3).map((feature) => (
-
- ))}
-
-
-
- {features.slice(3).map((feature) => (
-
-
-

-
-
-
-
- {feature.number}
-
-
{feature.title}
-
{feature.description}
-
-
- ))}
-
-
-
- );
-}
diff --git a/landing/components/hero.tsx b/landing/components/hero.tsx
deleted file mode 100644
index 1cf01bf8..00000000
--- a/landing/components/hero.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-"use client";
-
-import { motion } from "framer-motion";
-import { AsciiBackground } from "./ascii-background";
-import { landingHeroNarrative } from "../lib/product-narrative";
-
-const sharedEase: [number, number, number, number] = [0.16, 1, 0.3, 1];
-
-function heroMotion(delay: number) {
- return {
- initial: { opacity: 0, y: 24 },
- animate: { opacity: 1, y: 0 },
- transition: { duration: 0.7, delay, ease: sharedEase },
- };
-}
-
-function AppleIcon() {
- return (
-
- );
-}
-
-function WindowsIcon() {
- return (
-
- );
-}
-
-function LinuxIcon() {
- return (
-
- );
-}
-
-export function Hero() {
- return (
-
-
-
-
-
-
-
-
- {landingHeroNarrative.eyebrow}
-
-
-
-
- {landingHeroNarrative.titleLine1}
- {landingHeroNarrative.titleLine2}
-
-
-
- {landingHeroNarrative.description}
-
-
-
-
- See Downloads
-
-
-
-
-
-
- {landingHeroNarrative.availability}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/landing/components/layout/navbar.tsx b/landing/components/layout/navbar.tsx
new file mode 100644
index 00000000..80cd72ae
--- /dev/null
+++ b/landing/components/layout/navbar.tsx
@@ -0,0 +1,114 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import { Menu } from "reicon-react/icons/Menu";
+import { Xmark } from "reicon-react/icons/Xmark";
+import { Container } from "../ui/container";
+import { Button } from "../ui/button";
+import { IconMark } from "../icon-mark";
+import { ThemeToggle } from "../theme-toggle";
+
+const navLinks = [
+ { label: "Features", href: "#features" },
+ { label: "How it works", href: "#how-it-works" },
+ { label: "FAQ", href: "#faq" },
+];
+
+export function Navbar() {
+ const [mobileOpen, setMobileOpen] = useState(false);
+ const [scrolled, setScrolled] = useState(false);
+
+ useEffect(() => {
+ const onScroll = () => setScrolled(window.scrollY > 8);
+ window.addEventListener("scroll", onScroll, { passive: true });
+ onScroll();
+ return () => window.removeEventListener("scroll", onScroll);
+ }, []);
+
+ useEffect(() => {
+ const onResize = () => {
+ if (window.innerWidth >= 768) {
+ setMobileOpen(false);
+ }
+ };
+ window.addEventListener("resize", onResize, { passive: true });
+ return () => window.removeEventListener("resize", onResize);
+ }, []);
+
+ return (
+
+ );
+}
diff --git a/landing/components/navbar.tsx b/landing/components/navbar.tsx
deleted file mode 100644
index 26444012..00000000
--- a/landing/components/navbar.tsx
+++ /dev/null
@@ -1,132 +0,0 @@
-"use client";
-
-import { useEffect, useState } from "react";
-import { IconMark } from "./icon-mark";
-import { ThemeToggle } from "./theme-toggle";
-
-const navLinks = [
- { label: "Features", href: "#features" },
- { label: "How It Works", href: "#how-it-works" },
- { label: "FAQ", href: "#faq" },
- { label: "Download", href: "#download" },
-];
-
-function MenuIcon({ open }: { open: boolean }) {
- return (
-
- );
-}
-
-export function Navbar() {
- const [mobileOpen, setMobileOpen] = useState(false);
- const [scrolled, setScrolled] = useState(false);
-
- useEffect(() => {
- const handleScroll = () => setScrolled(window.scrollY > 8);
- window.addEventListener("scroll", handleScroll, { passive: true });
- handleScroll();
- return () => window.removeEventListener("scroll", handleScroll);
- }, []);
-
- useEffect(() => {
- const handleResize = () => {
- if (window.innerWidth >= 768) {
- setMobileOpen(false);
- }
- };
-
- window.addEventListener("resize", handleResize, { passive: true });
- return () => window.removeEventListener("resize", handleResize);
- }, []);
-
- return (
-
- );
-}
diff --git a/landing/components/sections/feature-section.tsx b/landing/components/sections/feature-section.tsx
new file mode 100644
index 00000000..9c7a3846
--- /dev/null
+++ b/landing/components/sections/feature-section.tsx
@@ -0,0 +1,18 @@
+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 (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/landing/components/sections/features.tsx b/landing/components/sections/features.tsx
new file mode 100644
index 00000000..1b45bb11
--- /dev/null
+++ b/landing/components/sections/features.tsx
@@ -0,0 +1,15 @@
+import { Container } from "../ui/container";
+import { FeatureSection } from "./feature-section";
+import { featureSections } from "../../lib/landing-content";
+
+export function Features() {
+ return (
+
+
+ {featureSections.map((feature) => (
+
+ ))}
+
+
+ );
+}
diff --git a/landing/components/sections/hero.tsx b/landing/components/sections/hero.tsx
new file mode 100644
index 00000000..6adfad94
--- /dev/null
+++ b/landing/components/sections/hero.tsx
@@ -0,0 +1,65 @@
+import { Container } from "../ui/container";
+import { Badge } from "../ui/badge";
+import { Button } from "../ui/button";
+import { MediaFrame } from "../ui/media-frame";
+import { landingHeroNarrative } from "../../lib/product-narrative";
+
+export function Hero() {
+ return (
+
+
+
+
+
+
{landingHeroNarrative.eyebrow}
+
+
+ {landingHeroNarrative.titleLine1} {landingHeroNarrative.titleLine2}
+
+
+
+ {landingHeroNarrative.description}
+
+
+
+
+
+
+
+
+ {landingHeroNarrative.availability}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/landing/components/theme-toggle.tsx b/landing/components/theme-toggle.tsx
index 7434d0b4..a286657f 100644
--- a/landing/components/theme-toggle.tsx
+++ b/landing/components/theme-toggle.tsx
@@ -1,31 +1,9 @@
"use client";
+import { Sun } from "reicon-react/icons/Sun";
+import { Moon } from "reicon-react/icons/Moon";
import { useTheme } from "./theme-provider";
-function SunIcon() {
- return (
-
- );
-}
-
-function MoonIcon() {
- return (
-
- );
-}
-
export function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
@@ -34,9 +12,9 @@ export function ThemeToggle() {
type="button"
onClick={toggleTheme}
aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`}
- className="relative inline-flex items-center justify-center w-11 h-11 rounded-lg transition-colors duration-200 cursor-pointer hover:bg-[var(--panel-soft)] text-[var(--muted)] hover:text-[var(--text)]"
+ className="inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-full text-[var(--muted)] transition-colors hover:bg-[var(--panel-soft)] hover:text-[var(--text)]"
>
- {theme === "light" ? : }
+ {theme === "light" ? : }
);
}
diff --git a/landing/components/ui/media-frame.tsx b/landing/components/ui/media-frame.tsx
new file mode 100644
index 00000000..51543a81
--- /dev/null
+++ b/landing/components/ui/media-frame.tsx
@@ -0,0 +1,29 @@
+/** Framed product screenshot panel: rounded, bordered, soft shadow on the page. */
+export function MediaFrame({
+ src,
+ alt,
+ priority = false,
+ className = "",
+}: {
+ src: string;
+ alt: string;
+ priority?: boolean;
+ className?: string;
+}) {
+ return (
+
+

+
+ );
+}