7ovr
blockstartupsource: ok · hit
Startup
Lean startup landing page template for early-stage products and waitlists: centered hero section with inline email capture, stats, feature grid, how it works timeline, testimonial, and waitlist signup.
npx shadcn add "https://7ovr.com/r/startup.json"free
Where it goes
herotestimonialstatssignupfeature-grid
Interaction
animated-counter
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightui-primitives@base-ui/react
Registry dependencies
avatarbadgebuttoncardcheckboxinputlabelseparatorsheetsonnerutils
Files10 · source cached 10/14/2026, 4:31:15 PM
registry/templates/startup/install-page.tsx
import { Toaster } from "@/components/ui/sonner"
import Features from "@/components/startup/features"
import Footer from "@/components/startup/footer"
import Header from "@/components/startup/header"
import Hero from "@/components/startup/hero"
import HowItWorks from "@/components/startup/how-it-works"
import Newsletter from "@/components/startup/newsletter"
import Stats from "@/components/startup/stats"
import Testimonials from "@/components/startup/testimonials"
const pool = (size: string, color: string, mid: string, out: string) =>
`radial-gradient(${size}, ${color}, ${mid} 38%, ${out} 78%)`
const wash = (base: string, a: number, b: number) => {
const at = (v: number) => `rgba(${base},${v})`
return [
pool("38% 13% at 84% 9%", at(a), at(a / 2), at(0)),
pool("42% 13% at 12% 28%", at(b), at(b / 2), at(0)),
pool("40% 12% at 70% 47%", at(a), at(a / 2), at(0)),
pool("42% 12% at 14% 66%", at(b), at(b / 2), at(0)),
pool("40% 13% at 74% 87%", at(a), at(a / 2), at(0)),
].join(",")
}
const WASH_LIGHT = wash("0,0,0", 0.04, 0.034)
const WASH_DARK = wash("255,255,255", 0.06, 0.051)
export default function StartupTemplate() {
return (
<div className="relative isolate flex min-h-svh w-full flex-col bg-background text-foreground">
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-[720px] bg-[radial-gradient(65%_60%_at_50%_-8%,rgba(0,0,0,0.06),transparent_72%)] dark:bg-[radial-gradient(65%_60%_at_50%_-8%,rgba(255,255,255,0.13),transparent_72%)]"
/>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 -z-10 dark:hidden"
style={{ backgroundImage: WASH_LIGHT }}
/>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 -z-10 hidden dark:block"
style={{ backgroundImage: WASH_DARK }}
/>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 bottom-0 -z-10 h-[560px] bg-[radial-gradient(55%_50%_at_50%_100%,rgba(0,0,0,0.05),transparent_70%)] dark:bg-[radial-gradient(55%_50%_at_50%_100%,rgba(255,255,255,0.08),transparent_70%)]"
/>
<Toaster />
<Header />
<main className="flex w-full flex-col">
<Hero />
<Stats />
<Features />
<HowItWorks />
<Testimonials />
<Newsletter />
</main>
<div className="border-t border-border/50">
<Footer />
</div>
</div>
)
}
registry/templates/startup/install-route.tsx
export { default } from "@/components/startup/page"
registry/templates/startup/components/features.tsx
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
type IconProps = { className?: string; size?: number | string }
const features = [
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="Flashlight"
tabler="IconBulb"
hugeicons="FlashlightIcon"
phosphor="Flashlight"
remixicon="RiFlashlightLine"
{...p}
/>
),
title: "Lightning fast",
copy: "Ship in milliseconds with an edge-first runtime tuned for speed.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="ShieldCheck"
tabler="IconShieldCheck"
hugeicons="Shield01Icon"
phosphor="ShieldCheck"
remixicon="RiShieldCheckLine"
{...p}
/>
),
title: "Secure by default",
copy: "Encryption, audit logs, and granular access baked into every layer.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="LayoutGrid"
tabler="IconLayoutGrid"
hugeicons="LayoutGridIcon"
phosphor="GridFour"
remixicon="RiLayoutGridLine"
{...p}
/>
),
title: "Composable blocks",
copy: "Drop in sharp, accessible components and compose them your way.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="ChartBar"
tabler="IconChartBar"
hugeicons="BarChartIcon"
phosphor="ChartBar"
remixicon="RiBarChartBoxLine"
{...p}
/>
),
title: "Real-time insights",
copy: "Track usage and performance the moment events happen.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="LineChart"
tabler="IconChartLine"
hugeicons="ChartLineIcon"
phosphor="ChartLine"
remixicon="RiLineChartLine"
{...p}
/>
),
title: "Scales with you",
copy: "From first user to millions without re-architecting a thing.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="Settings"
tabler="IconSettings"
hugeicons="SettingsIcon"
phosphor="GearSix"
remixicon="RiSettings3Line"
{...p}
/>
),
title: "Fully configurable",
copy: "Tune defaults, theming, and workflows to fit your team.",
},
]
export default function Features() {
return (
<section className="flex w-full items-center justify-center px-6 py-16 sm:py-24">
<div className="mx-auto w-full max-w-5xl">
<div className="mx-auto max-w-2xl text-center">
<Badge variant="secondary" className="mb-4 tracking-widest uppercase">
Features
</Badge>
<h2 className="font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl">
Everything you need to build
</h2>
<p className="mt-4 text-muted-foreground">
A focused toolkit that gets out of your way so you can move fast.
</p>
</div>
<div className="mt-12 grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3">
{features.map(({ icon: Icon, title, copy }) => (
<Card key={title} className="p-6">
<CardHeader className="p-0">
<span className="flex size-11 items-center justify-center rounded-lg border border-border bg-muted">
<Icon className="size-5" aria-hidden="true" />
</span>
<CardTitle className="mt-4 text-base font-semibold">
{title}
</CardTitle>
<CardDescription className="mt-2 text-sm">
{copy}
</CardDescription>
</CardHeader>
</Card>
))}
</div>
</div>
</section>
)
}
registry/templates/startup/components/footer.tsx
const NAV_LINKS = [
{ label: "Product", href: "#" },
{ label: "Pricing", href: "#" },
{ label: "Docs", href: "#" },
{ label: "Blog", href: "#" },
{ label: "Privacy", href: "#" },
{ label: "Terms", href: "#" },
]
export default function Footer() {
return (
<section className="flex w-full flex-col items-stretch">
<footer className="mx-auto w-full max-w-5xl px-6 py-8">
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<svg
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
className="size-6 shrink-0 text-primary"
>
<rect
x="3"
y="3"
width="8"
height="8"
transform="rotate(-6 7 7)"
/>
<rect
x="3"
y="13"
width="8"
height="8"
transform="rotate(5 7 17)"
/>
<rect
x="13"
y="13"
width="8"
height="8"
transform="rotate(-4 17 17)"
/>
<rect
x="13"
y="3"
width="8"
height="8"
transform="rotate(15 17 7)"
/>
</svg>
<div className="flex flex-col leading-none">
<span className="text-sm font-bold tracking-tight">Acme</span>
<span className="text-xs text-muted-foreground">
Build fast. Ship faster.
</span>
</div>
</div>
<nav
aria-label="Footer"
className="flex flex-wrap items-center gap-x-5 gap-y-1"
>
{NAV_LINKS.map((link) => (
<a
key={link.label}
href={link.href}
className="text-xs text-muted-foreground transition-colors hover:text-foreground"
>
{link.label}
</a>
))}
</nav>
<p className="shrink-0 text-xs text-muted-foreground">
© {new Date().getFullYear()} Acme, Inc.
</p>
</div>
</footer>
</section>
)
}
registry/templates/startup/components/header.tsx
"use client"
import { Button } from "@/components/ui/button"
import {
Sheet,
SheetClose,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
const navLinks = ["Blocks", "Docs", "Pricing", "Changelog"]
export default function Header() {
return (
<header className="sticky top-0 z-30 w-full border-b border-border bg-background/80 backdrop-blur">
<div className="mx-auto flex h-16 w-full max-w-5xl items-center gap-6 px-6">
<a href="#" className="flex items-center gap-2">
<svg
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
className="size-6 shrink-0 text-primary"
>
<rect x="3" y="3" width="8" height="8" transform="rotate(-6 7 7)" />
<rect
x="3"
y="13"
width="8"
height="8"
transform="rotate(5 7 17)"
/>
<rect
x="13"
y="13"
width="8"
height="8"
transform="rotate(-4 17 17)"
/>
<rect
x="13"
y="3"
width="8"
height="8"
transform="rotate(15 17 7)"
/>
</svg>
<span className="text-lg font-bold tracking-tight">Acme</span>
</a>
<nav className="hidden items-center gap-6 md:flex">
{navLinks.map((link) => (
<a
key={link}
href="#"
className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
>
{link}
</a>
))}
</nav>
<div className="ml-auto flex items-center gap-2">
<Button
render={<a href="#" />}
nativeButton={false}
className="hidden md:inline-flex"
>
Book A Demo
<IconPlaceholder
lucide="ArrowRight"
tabler="IconArrowRight"
hugeicons="ArrowRightIcon"
phosphor="ArrowRight"
remixicon="RiArrowRightLine"
data-icon="inline-end"
aria-hidden="true"
/>
</Button>
<Sheet>
<SheetTrigger
render={
<Button variant="outline" size="icon" className="md:hidden" />
}
aria-label="Open menu"
>
<IconPlaceholder
lucide="Menu"
tabler="IconMenu"
hugeicons="MenuIcon"
phosphor="List"
remixicon="RiMenuLine"
aria-hidden="true"
/>
</SheetTrigger>
<SheetContent side="right" className="w-full sm:max-w-xs">
<SheetHeader>
<SheetTitle className="flex items-center gap-2">
<svg
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
className="size-5 shrink-0 text-primary"
>
<rect
x="3"
y="3"
width="8"
height="8"
transform="rotate(-6 7 7)"
/>
<rect
x="3"
y="13"
width="8"
height="8"
transform="rotate(5 7 17)"
/>
<rect
x="13"
y="13"
width="8"
height="8"
transform="rotate(-4 17 17)"
/>
<rect
x="13"
y="3"
width="8"
height="8"
transform="rotate(15 17 7)"
/>
</svg>
Acme
</SheetTitle>
</SheetHeader>
<nav className="flex flex-col px-2">
{navLinks.map((link) => (
<SheetClose
key={link}
render={<a href="#" />}
nativeButton={false}
className="rounded-md px-2 py-2.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
{link}
</SheetClose>
))}
</nav>
<div className="mt-auto p-4">
<Button
render={<a href="#" />}
nativeButton={false}
className="w-full"
>
Book A Demo
<IconPlaceholder
lucide="ArrowRight"
tabler="IconArrowRight"
hugeicons="ArrowRightIcon"
phosphor="ArrowRight"
remixicon="RiArrowRightLine"
data-icon="inline-end"
aria-hidden="true"
/>
</Button>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</header>
)
}
registry/templates/startup/components/hero.tsx
"use client"
import { useState } from "react"
import { toast } from "sonner"
import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
export default function Hero() {
const [email, setEmail] = useState("")
const [submitted, setSubmitted] = useState(false)
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault()
if (!email) return
setSubmitted(true)
toast.success("You're on the list", {
description: `We'll reach out to ${email} when your spot is ready.`,
})
}
return (
<section className="relative isolate flex w-full items-center justify-center overflow-hidden px-6 py-16 sm:py-24">
<div
aria-hidden="true"
className={cn(
"pointer-events-none absolute inset-0 -z-10",
"bg-[linear-gradient(to_right,var(--color-border)_1px,transparent_1px),linear-gradient(to_bottom,var(--color-border)_1px,transparent_1px)]",
"bg-[size:56px_56px] opacity-40",
"[mask-image:radial-gradient(ellipse_70%_60%_at_50%_40%,black,transparent)]"
)}
/>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(ellipse_60%_50%_at_50%_0%,var(--color-primary)/0.12,transparent)]"
/>
<div className="mx-auto flex w-full max-w-2xl flex-col items-center text-center">
<Badge variant="secondary" className="px-3 py-1">
<IconPlaceholder
lucide="Sparkles"
tabler="IconSparkles"
hugeicons="SparklesIcon"
phosphor="Sparkle"
remixicon="RiSparkling2Line"
data-icon="inline-start"
className="size-3.5"
/>
Now in public beta
</Badge>
<h1 className="mt-6 font-heading text-4xl font-bold tracking-tight text-balance sm:text-5xl md:text-6xl">
Ship your next idea with Acme
</h1>
<p className="mt-5 max-w-xl text-base text-balance text-muted-foreground sm:text-lg">
The all-in-one platform that turns rough sketches into
production-ready apps. Build faster, launch sooner, and scale without
the busywork.
</p>
<form
onSubmit={handleSubmit}
className="mt-9 flex w-full max-w-md flex-col gap-3 sm:flex-row"
>
<div className="flex-1">
<Label htmlFor="hero-email" className="sr-only">
Email address
</Label>
<Input
id="hero-email"
type="email"
required
placeholder="you@acme.com"
value={email}
onChange={(event) => setEmail(event.target.value)}
className="h-11"
/>
</div>
<Button type="submit" size="lg" className="h-11 shrink-0">
{submitted ? "You're on the list" : "Get Started"}
{!submitted && (
<IconPlaceholder
lucide="ArrowRight"
tabler="IconArrowRight"
hugeicons="ArrowRightIcon"
phosphor="ArrowRight"
remixicon="RiArrowRightLine"
data-icon="inline-end"
className="size-4"
/>
)}
</Button>
</form>
<p className="mt-4 flex items-center justify-center gap-1.5 text-xs text-muted-foreground">
<IconPlaceholder
lucide="ShieldCheck"
tabler="IconShieldCheck"
hugeicons="Shield01Icon"
phosphor="ShieldCheck"
remixicon="RiShieldCheckLine"
className="size-3.5"
/>
No credit card required. Unsubscribe anytime.
</p>
</div>
</section>
)
}
registry/templates/startup/components/how-it-works.tsx
import { Badge } from "@/components/ui/badge"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
type IconProps = { className?: string; size?: number | string }
const steps = [
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="UserPlus"
tabler="IconUserPlus"
hugeicons="UserAddIcon"
phosphor="UserPlus"
remixicon="RiUserAddLine"
{...p}
/>
),
title: "Create your account",
copy: "Sign up in under two minutes, no credit card required. Your workspace is ready the moment you confirm your email.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="Settings"
tabler="IconSettings"
hugeicons="SettingsIcon"
phosphor="GearSix"
remixicon="RiSettings4Line"
{...p}
/>
),
title: "Configure your workflow",
copy: "Choose from pre-built templates or define your own pipeline. Acme adapts to how your team already works.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="Users"
tabler="IconUsersGroup"
hugeicons="UserGroupIcon"
phosphor="UsersThree"
remixicon="RiTeamLine"
{...p}
/>
),
title: "Invite your team",
copy: "Send role-based invites in bulk. Colleagues join with a single click and inherit the right permissions automatically.",
},
{
icon: (p: IconProps) => (
<IconPlaceholder
lucide="Rocket"
tabler="IconRocket"
hugeicons="RocketIcon"
phosphor="Rocket"
remixicon="RiRocketLine"
{...p}
/>
),
title: "Ship with confidence",
copy: "Run automated checks, review the audit trail, and deploy, knowing Acme has your back at every stage.",
},
]
export default function HowItWorks() {
return (
<section className="flex w-full items-center justify-center px-6 py-16 sm:py-24">
<div className="mx-auto grid w-full max-w-5xl grid-cols-1 gap-12 md:grid-cols-[1fr_1.3fr] md:gap-16">
<div className="md:sticky md:top-24 md:self-start">
<Badge variant="secondary" className="mb-4 tracking-widest uppercase">
How It Works
</Badge>
<h2 className="font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl">
Up and running in four steps
</h2>
<p className="mt-4 text-muted-foreground">
Acme is designed for momentum. Go from sign-up to full team
collaboration without a single support ticket.
</p>
</div>
<ol className="flex flex-col">
{steps.map(({ icon: Icon, title, copy }, index) => {
const isLast = index === steps.length - 1
return (
<li key={title} className="flex gap-6">
<div className="flex flex-col items-center">
<span className="flex size-10 shrink-0 items-center justify-center rounded-lg border border-border bg-muted">
<Icon
className="size-4 text-foreground"
aria-hidden="true"
/>
</span>
{!isLast && <span className="mt-1 w-px flex-1 bg-border" />}
</div>
<div className={isLast ? "pb-0" : "pb-10"}>
<h3 className="font-heading text-base font-semibold">
{title}
</h3>
<p className="mt-1.5 text-sm text-muted-foreground">{copy}</p>
</div>
</li>
)
})}
</ol>
</div>
</section>
)
}
registry/templates/startup/components/newsletter.tsx
"use client"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { Input } from "@/components/ui/input"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
export default function Newsletter() {
return (
<section className="flex w-full items-center justify-center px-6 py-16 sm:py-24">
<div className="mx-auto w-full max-w-5xl rounded-xl border border-border bg-card px-8 py-10 sm:px-12 sm:py-14">
<div className="flex flex-col gap-8 md:flex-row md:items-center md:justify-between md:gap-16">
<div className="flex flex-col gap-4 md:max-w-sm">
<Badge variant="secondary" className="tracking-widest uppercase">
Acme Weekly
</Badge>
<h2 className="font-heading text-3xl leading-tight font-bold tracking-tight text-balance sm:text-4xl">
Insights that move your work forward
</h2>
<p className="text-sm text-muted-foreground">
Product deep-dives, industry trends, and practical guides from the
Acme team, landing in your inbox every Tuesday morning.
</p>
</div>
<div className="flex flex-col gap-3 md:max-w-md md:min-w-0 md:flex-1">
<form
className="flex flex-col gap-3"
onSubmit={(e) => {
e.preventDefault()
toast.success("You're subscribed. See you Tuesday!")
}}
>
<div className="flex flex-col gap-2 sm:flex-row">
<Input
type="email"
placeholder="work@company.com"
aria-label="Email address"
className="flex-1 border-border bg-background"
/>
<Button type="submit" className="shrink-0">
Subscribe
<IconPlaceholder
lucide="ArrowRight"
tabler="IconArrowRight"
hugeicons="ArrowRightIcon"
phosphor="ArrowRight"
remixicon="RiArrowRightLine"
data-icon="inline-end"
aria-hidden="true"
/>
</Button>
</div>
<div className="flex items-center gap-2">
<Checkbox id="newsletter-consent" name="consent" />
<label
htmlFor="newsletter-consent"
className="text-sm font-normal text-muted-foreground"
>
I agree to receive the Acme Weekly newsletter.
</label>
</div>
</form>
<p className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconPlaceholder
lucide="Lock"
tabler="IconLock"
hugeicons="LockIcon"
phosphor="Lock"
remixicon="RiLockLine"
aria-hidden="true"
className="shrink-0"
size={12}
/>
Your data stays private. Unsubscribe any time, no questions asked.
</p>
</div>
</div>
</div>
</section>
)
}
registry/templates/startup/components/stats.tsx
import { Badge } from "@/components/ui/badge"
const stats = [
{ value: "$2.4B", label: "Revenue processed" },
{ value: "38 ms", label: "Median latency" },
{ value: "99.98%", label: "Uptime last 12 mo" },
{ value: "6,200+", label: "Businesses onboarded" },
]
export default function Stats() {
return (
<section className="flex w-full items-center justify-center px-6 py-16 sm:py-24">
<div className="mx-auto w-full max-w-5xl">
<div className="mb-12 text-center">
<Badge variant="secondary" className="mb-4 tracking-widest uppercase">
By The Numbers
</Badge>
<h2 className="font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl">
Acme by the numbers
</h2>
</div>
<dl className="grid grid-cols-2 gap-y-10 md:grid-cols-4 md:gap-y-0">
{stats.map(({ value, label }) => (
<div
key={label}
className="flex flex-col items-center gap-2 text-center"
>
<dt className="text-5xl font-bold tracking-tight tabular-nums sm:text-6xl">
{value}
</dt>
<dd className="text-sm text-muted-foreground">{label}</dd>
</div>
))}
</dl>
</div>
</section>
)
}
registry/templates/startup/components/testimonials.tsx
import { Badge } from "@/components/ui/badge"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Separator } from "@/components/ui/separator"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"
const testimonial = {
quote:
"Acme's platform compressed what used to be a six-week integration cycle down to a single sprint. Our engineers finally have breathing room to work on things that matter, and our customers felt the difference immediately.",
name: "Isabelle Fontaine",
role: "Chief Product Officer",
company: "Meridian Labs",
initials: "IF",
avatar: "https://i.pravatar.cc/150?img=45",
}
const metrics = [
{ value: "6×", label: "faster integrations" },
{ value: "40%", label: "less engineer toil" },
{ value: "1 sprint", label: "to full deployment" },
]
export default function Testimonials() {
return (
<section className="flex w-full items-center justify-center px-6 py-16 sm:py-24">
<div className="mx-auto w-full max-w-5xl">
<Badge variant="secondary" className="mb-4 tracking-widest uppercase">
Customer Story
</Badge>
<div className="relative rounded-xl border border-border bg-card p-10 sm:p-14">
<div
className="absolute top-10 left-0 h-16 w-[3px] bg-foreground"
aria-hidden="true"
/>
<IconPlaceholder
lucide="Quote"
tabler="IconQuotes"
hugeicons="QuotesIcon"
phosphor="Quotes"
remixicon="RiDoubleQuotesR"
className="mb-8 size-8 text-muted-foreground"
aria-hidden="true"
/>
<blockquote className="max-w-3xl text-xl leading-[1.65] font-medium tracking-tight text-foreground sm:text-2xl">
“{testimonial.quote}”
</blockquote>
<Separator className="my-10" />
<div className="flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-4">
<Avatar className="size-14 border border-border">
<AvatarImage
src={testimonial.avatar}
alt={testimonial.name}
className="grayscale"
/>
<AvatarFallback className="text-sm font-semibold">
{testimonial.initials}
</AvatarFallback>
</Avatar>
<div className="flex flex-col gap-1">
<span className="text-sm leading-tight font-semibold text-foreground">
{testimonial.name}
</span>
<span className="text-xs leading-tight text-muted-foreground">
{testimonial.role},{" "}
<span className="font-medium text-foreground">
{testimonial.company}
</span>
</span>
</div>
</div>
<div className="flex items-center gap-6 sm:gap-8">
{metrics.map((m, i) => (
<div
key={i}
className="flex flex-col items-center gap-0.5 text-center"
>
<span className="text-lg leading-none font-bold tracking-tight text-foreground">
{m.value}
</span>
<span className="text-[11px] leading-tight text-muted-foreground">
{m.label}
</span>
</div>
))}
</div>
</div>
</div>
</div>
</section>
)
}