← HeroOpen in v0
Hero 03 — Swiss Ledger
Minimal editorial hero on a Swiss grid: indexed caption bar, headline with action rail, and a single golden-ratio proof strip pairing a 3D-tilt conversion panel with one live metric over an interactive shader flow field.
$ npx shadcn@latest add @ludusvibe/hero-03Code
Installed to components/sections/hero-03.tsx — it's yours to edit.
"use client"
import * as React from "react"
import { motion } from "motion/react"
import { ArrowRight, Star } from "lucide-react"
import { buttonVariants } from "@/components/ui/button"
import { AnimatedNumber } from "@/components/ludus/animated-number"
import { Grain } from "@/components/ludus/grain"
import { ShaderBackground } from "@/components/ludus/shader-background"
import { TiltCard } from "@/components/ludus/tilt-card"
import { fadeUp, stagger, viewport } from "@/lib/motion"
import { cn } from "@/lib/utils"
type Cta = { label: string; href: string }
export type Hero03Props = {
index?: string
label?: string
note?: string
title?: React.ReactNode
description?: string
primaryCta?: Cta
secondaryCta?: Cta
proof?: string
rating?: string
/** Heading element — use "h1" when this is the page's main heading. */
as?: "h1" | "h2"
className?: string
}
export function Hero03({
index = "01",
label = "Platform",
note = "Made for teams that ship",
title = (
<>
Turn traffic into{" "}
<span className="underline decoration-primary/60 decoration-4 underline-offset-[10px]">
revenue
</span>
, systematically.
</>
),
description = "Lumen finds the leaks in your funnel and fixes them with you — checkout, onboarding, pricing. Teams see their first lift inside two weeks.",
primaryCta = { label: "Start free — fix your funnel", href: "#" },
secondaryCta = { label: "See pricing", href: "#" },
proof = "No credit card · Cancel anytime",
rating = "4.9 from 2,400+ teams",
as: Heading = "h1",
className,
}: Hero03Props) {
return (
<section className={cn("relative overflow-hidden bg-background", className)}>
<ShaderBackground intensity={0.3} className="[mask-image:linear-gradient(to_bottom,black,transparent_85%)]" />
<Grain />
<motion.div
initial="hidden"
whileInView="visible"
viewport={viewport}
variants={stagger(0.09)}
className="relative mx-auto max-w-6xl px-6 py-20 md:py-28"
>
{/* Swiss index bar */}
<motion.div
variants={fadeUp}
className="flex items-baseline justify-between border-b pb-3 text-xs tracking-[0.2em] text-muted-foreground uppercase"
>
<span>
<span className="text-primary">{index}</span> — {label}
</span>
<span className="hidden sm:block">{note}</span>
</motion.div>
{/* Headline / action rail */}
<div className="mt-10 grid grid-cols-12 gap-x-8 gap-y-10">
<motion.div variants={fadeUp} className="col-span-12 lg:col-span-7">
<Heading className="text-[clamp(2.5rem,6.5vw,4.75rem)] leading-[0.98] font-medium tracking-tight text-balance">
{title}
</Heading>
</motion.div>
<motion.div
variants={fadeUp}
className="col-span-12 flex flex-col justify-between gap-8 lg:col-span-5 lg:border-l lg:pl-8"
>
<p className="max-w-[42ch] text-pretty text-muted-foreground md:text-lg">
{description}
</p>
<div className="flex flex-col gap-3">
<a
href={primaryCta.href}
className={cn(buttonVariants({ size: "lg" }), "group w-full justify-between")}
>
{primaryCta.label}
<ArrowRight className="transition-transform group-hover:translate-x-0.5" />
</a>
<div className="flex flex-wrap items-center justify-between gap-x-3 gap-y-2">
<a
href={secondaryCta.href}
className={cn(buttonVariants({ size: "lg", variant: "ghost" }), "px-0 hover:bg-transparent hover:underline")}
>
{secondaryCta.label} →
</a>
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Star className="size-3.5 fill-current text-primary" aria-hidden />
{rating}
</span>
</div>
<p className="border-t pt-3 text-xs tracking-wide text-muted-foreground/70 uppercase">
{proof}
</p>
</div>
</motion.div>
</div>
{/* Golden-ratio proof strip */}
<motion.div
variants={fadeUp}
className="mt-16 grid gap-px border bg-border lg:grid-cols-[1.618fr_1fr]"
>
<TiltCard maxTilt={4} className="bg-background">
<div className="p-6 md:p-8">
<div className="flex items-baseline justify-between text-xs tracking-[0.2em] text-muted-foreground uppercase">
<span>Checkout conversion</span>
<span className="flex items-center gap-1.5">
<span className="size-1.5 animate-pulse rounded-full bg-primary" />
Live
</span>
</div>
<p className="mt-6 font-heading text-5xl font-medium tracking-tight md:text-6xl">
<AnimatedNumber value={38} suffix="%" />
<span className="ml-3 align-middle text-sm font-normal text-primary">
↑ vs last quarter
</span>
</p>
<div
aria-hidden
className="mt-8 flex h-24 items-end gap-1.5 border-t pt-4"
>
{[28, 34, 30, 42, 38, 52, 47, 61, 58, 72, 69, 84, 80, 96].map((h, i) => (
<div
key={i}
style={{ height: `${h}%` }}
className={cn(
"flex-1",
i >= 10 ? "bg-primary" : "bg-primary/25"
)}
/>
))}
</div>
</div>
</TiltCard>
<div className="flex flex-col justify-between bg-background p-6 md:p-8">
<p className="text-xs tracking-[0.2em] text-muted-foreground uppercase">
Recovered revenue
</p>
<div>
<p className="mt-4 font-heading text-4xl font-medium tracking-tight md:text-5xl">
<AnimatedNumber
value={1200000}
prefix="$"
format={{ notation: "compact", maximumFractionDigits: 1 }}
/>
</p>
<p className="mt-2 text-sm text-muted-foreground">this quarter, across customers</p>
</div>
</div>
</motion.div>
</motion.div>
</section>
)
}