navui
blockhero-section-foursource: ok · hit
Hero Section Four
A complete expense-workflow hero with responsive header, lead form, logo cloud, and supporting illustrations.
npx shadcn add "https://ui.navdeepsingh.dev/r/hero-section-four.json"free
Where it goes
heronavbarlogo-cloud
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · mediumiconslucide-react
animationmotion
Registry dependencies
https://ui.navdeepsingh.dev/r/header-three.jsonhttps://ui.navdeepsingh.dev/r/logo-cloud-five.jsonbuttonlabel
Files2 · source cached 10/8/2026, 5:56:04 PM
src/registry/blocks/hero/hero-section-four/hero-section-four-illustration.tsx
'use client'
import { type ReactNode, useRef } from 'react'
import { ArrowRight, Coffee, Mail, NfcIcon, User } from 'lucide-react'
import {
motion,
type Variants,
useInView,
useMotionValue,
useReducedMotion,
useSpring,
useTransform,
} from 'motion/react'
import { cn } from '@/lib/utils'
const ENTRANCE_EASE: [number, number, number, number] = [0.22, 1, 0.36, 1]
const PANEL_ENTRANCE_START = 0.62
const PANEL_STAGGER = 0.12
const cardEntranceVariants: Variants = {
hidden: {
opacity: 0,
y: 52,
scale: 0.97,
},
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: {
delay: 0.05,
duration: 0.72,
ease: ENTRANCE_EASE,
},
},
}
const panelEntranceVariants: Variants = {
hidden: {
opacity: 0,
y: 32,
scale: 0.97,
filter: 'blur(12px)',
},
visible: (order: number = 0) => ({
opacity: 1,
y: 0,
scale: 1,
filter: 'blur(0px)',
transition: {
delay: PANEL_ENTRANCE_START + order * PANEL_STAGGER,
duration: 0.64,
ease: ENTRANCE_EASE,
},
}),
}
type WorkflowStage = 'receipt' | 'policy' | 'category' | 'approval'
type WorkflowPanelProps = {
children: ReactNode
className?: string
isActive: boolean
order: number
shouldReduceMotion: boolean
stage: WorkflowStage
title: string
}
function WorkflowPanel({
children,
className,
isActive,
order,
shouldReduceMotion,
stage,
title,
}: WorkflowPanelProps) {
return (
<motion.div
variants={panelEntranceVariants}
custom={order}
initial={shouldReduceMotion ? false : 'hidden'}
animate={shouldReduceMotion ? undefined : isActive ? 'visible' : 'hidden'}
whileHover={
shouldReduceMotion
? undefined
: {
y: -5,
transition: {
duration: 0.22,
ease: 'easeOut',
},
}
}
style={{
willChange: shouldReduceMotion ? undefined : 'transform, opacity, filter',
}}
className={cn(
'absolute transform-gpu border border-border/70',
'bg-background/95 p-2.5 text-foreground backdrop-blur-[2px]',
'shadow-[0_12px_34px_rgba(15,23,42,0.07)]',
'transition-shadow duration-300',
'hover:shadow-[0_18px_42px_rgba(15,23,42,0.1)]',
'sm:p-4',
'dark:border-white/10 dark:bg-zinc-950/95',
'dark:shadow-[0_14px_36px_rgba(0,0,0,0.34)]',
'dark:hover:shadow-[0_20px_48px_rgba(0,0,0,0.48)]',
className,
)}
data-workflow-panel={stage}
>
<PanelCornerMarkers />
<p className="text-[8px] font-semibold tracking-wide text-muted-foreground uppercase sm:text-[10px]">
{title}
</p>
{children}
</motion.div>
)
}
function PanelCornerMarkers() {
const positions = [
'-top-1 -left-1',
'-top-1 -right-1',
'-bottom-1 -left-1',
'-bottom-1 -right-1',
] as const
return (
<div aria-hidden="true" className="pointer-events-none">
{positions.map((position) => (
<span
key={position}
className={cn('absolute size-1.5 rounded-full bg-muted-foreground', position)}
/>
))}
</div>
)
}
function PanelInset({ children, className }: { children: ReactNode; className?: string }) {
return (
<div
className={cn(
'mt-2.5 rounded-sm border border-border/60 bg-muted/80 p-2',
'sm:mt-3 sm:p-2.5',
className,
)}
>
{children}
</div>
)
}
function PaymentCard({
isActive,
shouldReduceMotion,
}: {
isActive: boolean
shouldReduceMotion: boolean
}) {
const pointerX = useMotionValue(0)
const pointerY = useMotionValue(0)
const springX = useSpring(pointerX, {
stiffness: 160,
damping: 22,
mass: 0.4,
})
const springY = useSpring(pointerY, {
stiffness: 160,
damping: 22,
mass: 0.4,
})
const rotateY = useTransform(springX, [-1, 1], [-12, 12])
const rotateX = useTransform(springY, [-1, 1], [12, -12])
const resetTilt = () => {
pointerX.set(0)
pointerY.set(0)
}
return (
// Positioning layer
<div
className={cn(
'absolute top-1/2 left-1/2 z-30',
'h-60 w-38 -translate-x-1/2 -translate-y-1/2',
'sm:h-72 sm:w-46',
'lg:h-82 lg:w-52',
)}
>
{/* Entrance layer */}
<motion.div
variants={cardEntranceVariants}
initial={shouldReduceMotion ? false : 'hidden'}
animate={shouldReduceMotion ? undefined : isActive ? 'visible' : 'hidden'}
style={{
willChange: shouldReduceMotion ? undefined : 'transform, opacity',
}}
className="size-full transform-gpu"
>
{/* Interaction layer */}
<motion.div
onPointerMove={(event) => {
const hasFinePointer = window.matchMedia('(hover: hover) and (pointer: fine)').matches
if (shouldReduceMotion || !hasFinePointer) {
return
}
const rect = event.currentTarget.getBoundingClientRect()
pointerX.set(((event.clientX - rect.left) / rect.width - 0.5) * 2)
pointerY.set(((event.clientY - rect.top) / rect.height - 0.5) * 2)
}}
onPointerLeave={resetTilt}
onPointerCancel={resetTilt}
style={{
rotateX: shouldReduceMotion ? 0 : rotateX,
rotateY: shouldReduceMotion ? 0 : rotateY,
transformPerspective: 750,
transformStyle: 'preserve-3d',
}}
className={cn(
'relative size-full transform-gpu overflow-hidden',
'rounded-[1.2rem] border border-white/10 bg-zinc-950',
'shadow-[0_28px_70px_rgba(15,23,42,0.2),0_10px_24px_rgba(15,23,42,0.14)]',
'sm:rounded-[1.35rem]',
'dark:shadow-[0_30px_80px_rgba(0,0,0,0.52)]',
)}
>
<CardDecoration />
<CardChip />
<div className="absolute top-5 left-5 z-10 flex items-center gap-1 text-white sm:top-7 sm:left-6">
<NfcIcon aria-hidden="true" className="size-4 sm:size-5" />
<span className="text-[10px] font-semibold tracking-wide sm:text-xs">Payflow</span>
</div>
<div className="absolute bottom-5 left-5 z-10 text-[8px] font-medium tracking-[0.16em] text-white/50 uppercase sm:bottom-6 sm:left-6 sm:text-[10px] sm:tracking-[0.18em]">
4821 •••• 8830
</div>
</motion.div>
</motion.div>
</div>
)
}
function CardDecoration() {
return (
<>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]"
>
{Array.from({ length: 16 }).map((_, index) => (
<span
key={index}
className="absolute rounded-full border border-white/10"
style={{
right: `${index * 9 - 48}px`,
bottom: `${index * -2 - 58}px`,
width: `${160 + index * 22}px`,
height: `${120 + index * 22}px`,
}}
/>
))}
</div>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 z-20 rounded-[inherit] border border-white/5"
/>
</>
)
}
function CardChip() {
return (
<div
aria-hidden="true"
className={cn(
'absolute top-5 right-5 z-10 aspect-square w-8 overflow-hidden',
'rounded-[22%] bg-[#9d9580]',
'shadow-[0_5px_12px_rgba(0,0,0,0.3),inset_1px_1px_2px_rgba(255,255,255,0.45),inset_-1px_-1px_2px_rgba(47,43,34,0.28)]',
'sm:top-6 sm:right-6 sm:w-9',
)}
>
<div className="relative z-10 grid size-full grid-cols-3 grid-rows-3 overflow-hidden rounded-[15%]">
<div className="col-span-2 border-r border-b border-neutral-500/60" />
<div className="border-b border-neutral-500/60" />
<div className="border-r border-b border-neutral-500/60" />
<div className="col-span-2 border-b border-neutral-500/60" />
<div className="col-span-2 border-r border-neutral-500/60" />
</div>
</div>
)
}
const receiptItems = [
{
name: '1 × Coffee',
price: '$2.30',
},
{
name: '1 × Classic Donut',
price: '$3.59',
},
] as const
function ReceiptItem({ name, price }: { name: string; price: string }) {
return (
<div className="flex w-full items-center justify-between gap-3">
<p>{name}</p>
<p>{price}</p>
</div>
)
}
function ReceiptPanelContent() {
return (
<PanelInset>
<div className="flex flex-col items-center">
<div className="flex w-full flex-col items-center gap-2 border-b border-dashed border-border pb-4">
<Coffee aria-hidden="true" className="size-4 text-muted-foreground" />
<div className="text-center text-[10px] leading-3 tracking-tight text-muted-foreground">
<p>CAFE</p>
<p>123 Roadhouse Ave</p>
<p>M9A 4XZ, CA</p>
</div>
</div>
<div className="flex w-full flex-col gap-2 pt-4 font-mono text-[9px] tracking-tight">
{receiptItems.map((item) => (
<ReceiptItem key={item.name} name={item.name} price={item.price} />
))}
<div className="border-t border-muted-foreground/60 pt-1">
<div className="flex justify-between font-semibold text-foreground">
<p>TOTAL</p>
<p>$5.89</p>
</div>
</div>
</div>
</div>
</PanelInset>
)
}
function MatchingPanelContent({
isActive,
shouldReduceMotion,
}: {
isActive: boolean
shouldReduceMotion: boolean
}) {
return (
<PanelInset>
<div className="flex flex-col gap-2 text-[7px] sm:text-[8px]">
<ProgressRow label="Office supplies" width="42%" />
<div className="flex flex-col gap-1">
<p>Business travel</p>
<div className="relative h-1 overflow-hidden rounded-full bg-border">
<motion.span
initial={false}
animate={{
width: shouldReduceMotion || isActive ? '60%' : '2%',
}}
transition={
shouldReduceMotion
? { duration: 0 }
: {
delay: PANEL_ENTRANCE_START + PANEL_STAGGER + 0.24,
duration: 0.65,
ease: ENTRANCE_EASE,
}
}
className="absolute inset-y-0 left-0 rounded-full bg-blue-500/80"
/>
</div>
</div>
<ProgressRow label="WFH stipend" width="52%" />
</div>
</PanelInset>
)
}
function ProgressRow({ label, width }: { label: string; width: string }) {
return (
<div className="flex flex-col gap-1">
<p>{label}</p>
<div className="relative h-1 overflow-hidden rounded-full bg-border">
<span
className="absolute inset-y-0 left-0 rounded-full bg-muted-foreground/30"
style={{ width }}
/>
</div>
</div>
)
}
const reportItems = [
{
label: 'Action required',
highlighted: false,
},
{
label: 'Expense report 1084',
highlighted: true,
},
{
label: 'Missing receipt',
highlighted: false,
},
{
label: 'Report 1280',
highlighted: false,
},
] as const
function ReportPanelContent() {
return (
<div className="mt-3 space-y-2.5 sm:mt-4 sm:space-y-3">
{reportItems.map((item) => (
<div
key={item.label}
className={cn(
'flex min-w-0 items-center gap-2',
item.highlighted ? 'text-foreground' : 'text-muted-foreground/35',
)}
>
<Mail aria-hidden="true" className="size-4 shrink-0 sm:size-4.5" />
<p
className={cn('truncate text-[9px] sm:text-[11px]', item.highlighted && 'font-medium')}
>
{item.label}
</p>
</div>
))}
</div>
)
}
function ApprovalPanelContent() {
return (
<PanelInset>
<div className="flex items-center gap-2 sm:gap-3">
<div className="grid size-8 shrink-0 place-items-center rounded-full bg-zinc-900 text-white sm:size-9 dark:bg-white dark:text-zinc-950">
<User aria-hidden="true" className="size-3.5 sm:size-4" />
</div>
<div className="min-w-0 flex-1">
<p className="truncate text-[10px] font-semibold uppercase sm:text-xs">John Doe</p>
<p className="mt-0.5 truncate text-[8px] text-muted-foreground sm:text-[10px]">
Finance Manager
</p>
</div>
<div
aria-hidden="true"
className="grid size-7 shrink-0 place-items-center rounded-full border border-border/60 bg-background sm:size-8"
>
<ArrowRight className="size-3.5 text-muted-foreground sm:size-4" />
</div>
</div>
</PanelInset>
)
}
type SpendWorkflowIllustrationProps = {
className?: string
'aria-label'?: string
}
type StandaloneIllustrationProps = {
className?: string
}
function StandalonePanelFrame({
children,
className,
title,
stage,
}: {
children: ReactNode
className?: string
title: string
stage: WorkflowStage
}) {
const shouldReduceMotion = Boolean(useReducedMotion())
return (
<div
role="img"
aria-label={title}
className={cn('relative h-48 w-64 text-left sm:h-54 sm:w-72', className)}
>
<WorkflowPanel
stage={stage}
title={title}
order={0}
isActive={true}
shouldReduceMotion={shouldReduceMotion}
className="inset-0 w-full"
>
{children}
</WorkflowPanel>
</div>
)
}
export function PaymentCardIllustration({ className }: StandaloneIllustrationProps) {
const shouldReduceMotion = Boolean(useReducedMotion())
return (
<div
role="img"
aria-label="Payment card"
className={cn('relative h-88 w-56 sm:h-96 sm:w-64', className)}
>
<PaymentCard isActive={true} shouldReduceMotion={shouldReduceMotion} />
</div>
)
}
export function ReceiptPanelIllustration({ className }: StandaloneIllustrationProps) {
return (
<StandalonePanelFrame title="Receipt captured" stage="receipt" className={className}>
<ReceiptPanelContent />
</StandalonePanelFrame>
)
}
export function MatchingPanelIllustration({ className }: StandaloneIllustrationProps) {
const shouldReduceMotion = Boolean(useReducedMotion())
return (
<StandalonePanelFrame title="Matching..." stage="policy" className={className}>
<MatchingPanelContent isActive={true} shouldReduceMotion={shouldReduceMotion} />
</StandalonePanelFrame>
)
}
export function ReportPanelIllustration({ className }: StandaloneIllustrationProps) {
return (
<StandalonePanelFrame title="Fetching report..." stage="category" className={className}>
<ReportPanelContent />
</StandalonePanelFrame>
)
}
export function ApprovalPanelIllustration({ className }: StandaloneIllustrationProps) {
return (
<StandalonePanelFrame title="Approval routed" stage="approval" className={className}>
<ApprovalPanelContent />
</StandalonePanelFrame>
)
}
export function SpendWorkflowIllustration({
className,
'aria-label': ariaLabel = 'Automated expense processing workflow',
}: SpendWorkflowIllustrationProps) {
const illustrationRef = useRef<HTMLDivElement>(null)
const shouldReduceMotion = Boolean(useReducedMotion())
const isInView = useInView(illustrationRef, {
once: true,
amount: 0.2,
margin: '0px 0px -10% 0px',
})
const isActive = isInView || shouldReduceMotion
return (
<div
ref={illustrationRef}
role="img"
aria-label={ariaLabel}
data-slot="spend-workflow-illustration"
className={cn(
'relative isolate mx-auto h-130 w-full max-w-160',
'shrink-0 overflow-hidden sm:h-140 lg:h-150',
className,
)}
style={{
maskImage:
'linear-gradient(to right, transparent 0%, black 1%, black 99%, transparent 100%), linear-gradient(to bottom, transparent 0%, black 1%, black 99%, transparent 100%)',
WebkitMaskImage:
'linear-gradient(to right, transparent 0%, black 1%, black 99%, transparent 100%), linear-gradient(to bottom, transparent 0%, black 1%, black 99%, transparent 100%)',
maskComposite: 'intersect',
WebkitMaskComposite: 'source-in',
}}
>
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 opacity-55 dark:opacity-25"
style={{
backgroundImage: 'radial-gradient(circle, rgba(15,23,42,0.16) 1px, transparent 1px)',
backgroundSize: '18px 18px',
}}
/>
<PaymentCard isActive={isActive} shouldReduceMotion={shouldReduceMotion} />
<WorkflowPanel
stage="receipt"
title="Receipt captured"
order={0}
isActive={isActive}
shouldReduceMotion={shouldReduceMotion}
className="top-5 left-0 z-40 w-[46%] max-w-58 sm:top-[6%] sm:left-[4%]"
>
<ReceiptPanelContent />
</WorkflowPanel>
<WorkflowPanel
stage="policy"
title="Matching..."
order={1}
isActive={isActive}
shouldReduceMotion={shouldReduceMotion}
className="top-[10%] right-0 z-10 w-[46%] max-w-58 sm:top-[13%] sm:right-[3%]"
>
<MatchingPanelContent isActive={isActive} shouldReduceMotion={shouldReduceMotion} />
</WorkflowPanel>
<WorkflowPanel
stage="category"
title="Fetching report..."
order={2}
isActive={isActive}
shouldReduceMotion={shouldReduceMotion}
className="bottom-[7%] left-0 z-10 w-[46%] max-w-58 sm:bottom-[9%] sm:left-[3%]"
>
<ReportPanelContent />
</WorkflowPanel>
<WorkflowPanel
stage="approval"
title="Approval routed"
order={3}
isActive={isActive}
shouldReduceMotion={shouldReduceMotion}
className="top-[50%] right-0 z-40 w-[47%] max-w-60 sm:top-[49%] sm:right-[1%]"
>
<ApprovalPanelContent />
</WorkflowPanel>
</div>
)
}
src/registry/blocks/hero/hero-section-four/hero-section-four.tsx
'use client'
import { useEffect, useRef, useState } from 'react'
import { animate, motion, useMotionValue, useReducedMotion } from 'motion/react'
import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'
import HeaderThree from '@/components/blocks/header/header-three'
import LogoCloudFive from '@/components/blocks/logo-cloud/logo-cloud-five'
import { Label } from '@/components/ui/label'
import { SpendWorkflowIllustration } from './hero-section-four-illustration'
const stats = [
{
label: 'TOTAL AI ACTIONS',
value: '2,109,875',
},
{
label: 'RECEIPTS MATCHED',
value: '1,326,672',
},
{
label: 'FIELDS CODED',
value: '805,266',
},
{
label: 'APPROVALS ROUTED',
value: '58,419',
},
{
label: 'EXPENSES REVIEWED',
value: '137,486',
},
{
label: 'SPEND ALLOCATED',
value: '$18.6M',
},
{
label: 'POLICIES CHECKED',
value: '294,706',
},
]
function StatItem({ item }: { item: { label: string; value: string } }) {
return (
<div className="group flex shrink-0 items-center gap-2.5 border-r border-border/60 px-6 py-2.5">
<span className="text-[10px] font-medium tracking-[0.14em] text-muted-foreground uppercase select-none">
{item.label}:
</span>
<span className="rounded bg-muted px-2 py-1 font-mono text-[11px] font-semibold text-foreground tabular-nums transition-colors select-none group-hover:bg-muted/80">
{item.value}
</span>
</div>
)
}
function MarqueeTrack() {
const x = useMotionValue(0)
const shouldReduceMotion = useReducedMotion()
const firstGroupRef = useRef<HTMLDivElement>(null)
const controlsRef = useRef<ReturnType<typeof animate> | null>(null)
const [groupWidth, setGroupWidth] = useState(0)
useEffect(() => {
const group = firstGroupRef.current
if (!group) return
const updateWidth = () => {
setGroupWidth(group.scrollWidth)
}
updateWidth()
const observer = new ResizeObserver(updateWidth)
observer.observe(group)
return () => observer.disconnect()
}, [])
useEffect(() => {
if (!groupWidth || shouldReduceMotion) return
controlsRef.current?.stop()
x.set(0)
controlsRef.current = animate(x, -groupWidth, {
duration: 32,
ease: 'linear',
repeat: Infinity,
repeatType: 'loop',
})
return () => controlsRef.current?.stop()
}, [groupWidth, shouldReduceMotion, x])
return (
<div
className="relative min-w-0 flex-1 overflow-hidden"
style={{
maskImage: 'linear-gradient(to right, transparent, black 8%, black 92%, transparent)',
WebkitMaskImage: 'linear-gradient(to right, transparent, black 8%, black 92%, transparent)',
}}
onMouseEnter={() => controlsRef.current?.pause()}
onMouseLeave={() => controlsRef.current?.play()}
>
<motion.div style={{ x }} className="flex w-max items-center">
<div ref={firstGroupRef} className="flex shrink-0 items-center">
{stats.map((item) => (
<StatItem key={item.label} item={item} />
))}
</div>
<div aria-hidden="true" className="flex shrink-0 items-center">
{stats.map((item) => (
<StatItem key={`${item.label}-duplicate-1`} item={item} />
))}
</div>
<div aria-hidden="true" className="flex shrink-0 items-center">
{stats.map((item) => (
<StatItem key={`${item.label}-duplicate-2`} item={item} />
))}
</div>
</motion.div>
</div>
)
}
function StatsDock() {
const slotRef = useRef<HTMLDivElement>(null)
const barRef = useRef<HTMLDivElement>(null)
const [isDocked, setIsDocked] = useState(true)
const [barHeight, setBarHeight] = useState(48)
useEffect(() => {
const updateHeight = () => {
if (!barRef.current) return
setBarHeight(barRef.current.offsetHeight)
}
updateHeight()
const observer = new ResizeObserver(updateHeight)
if (barRef.current) {
observer.observe(barRef.current)
}
window.addEventListener('resize', updateHeight)
return () => {
observer.disconnect()
window.removeEventListener('resize', updateHeight)
}
}, [])
useEffect(() => {
let previousY = window.scrollY
let ticking = false
const updateDockState = () => {
const slot = slotRef.current
if (!slot) return
const rect = slot.getBoundingClientRect()
const currentY = window.scrollY
const scrollingUp = currentY < previousY
const bottomDockPoint = window.innerHeight - barHeight
const slotIsBelowViewport = rect.top > bottomDockPoint
const slotIsAboveViewport = rect.bottom < 0
const shouldDock = slotIsBelowViewport || (scrollingUp && slotIsAboveViewport)
setIsDocked(shouldDock)
previousY = currentY
ticking = false
}
const onScroll = () => {
if (ticking) return
ticking = true
window.requestAnimationFrame(updateDockState)
}
updateDockState()
window.addEventListener('scroll', onScroll, { passive: true })
window.addEventListener('resize', updateDockState)
return () => {
window.removeEventListener('scroll', onScroll)
window.removeEventListener('resize', updateDockState)
}
}, [barHeight])
return (
<div
ref={slotRef}
className="mt-6"
style={{
height: isDocked ? barHeight : undefined,
}}
>
<div
ref={barRef}
className={cn(
'z-50 border-y border-border/70 bg-background/95 backdrop-blur-md',
isDocked
? 'fixed right-0 bottom-0 left-0 shadow-[0_-8px_30px_rgba(0,0,0,0.05)]'
: 'relative w-full',
)}
>
<div className="mx-auto flex max-w-360 items-center px-6 sm:px-8 lg:px-12">
<div className="relative z-20 flex shrink-0 items-center gap-2 border-r border-border/70 bg-background py-3 pr-5 text-[10px] font-medium tracking-[0.14em] text-foreground uppercase">
<span className="absolute inset-x-0 size-2 animate-ping place-items-center rounded-full bg-green-500/90 motion-reduce:animate-none" />
<span className="grid size-2 place-items-center rounded-full bg-green-400/90" />
<span className="hidden sm:inline">Live:</span>
<span className="font-mono font-semibold">356</span>
</div>
<MarqueeTrack />
</div>
</div>
</div>
)
}
export default function HeroSectionFour() {
return (
<section className="relative overflow-x-hidden bg-background text-foreground">
<div className="relative z-10">
<HeaderThree />
<div className="mx-auto grid max-w-7xl items-center gap-10 px-6 pt-32 sm:px-8 lg:grid-cols-[minmax(0,0.9fr)_minmax(460px,1fr)] lg:gap-4 lg:px-12 lg:pt-48">
<div>
<div className="max-w-4xl">
<h1 className="max-w-2xl font-geist text-4xl font-semibold tracking-tight text-foreground sm:text-5xl md:text-6xl">
Spend smarter. <br />
<span className="text-muted-foreground">Close faster.</span>
</h1>
<p className="font-inter mt-4 max-w-xl text-base leading-7 text-muted-foreground sm:text-lg">
Automate receipts, approvals, cards, and bill payments in one clean workflow built
for teams that move fast.
</p>
<form className="mt-8 flex max-w-lg flex-col gap-3 sm:flex-row">
<Label className="flex min-h-12 flex-1 items-center rounded-md border border-border/50 bg-background px-1 pl-2 shadow-xs ring-border in-focus-within:ring-1">
<span className="sr-only">Work email</span>
<input
type="email"
name="email"
autoComplete="email"
placeholder="Enter your work email"
className="w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring/50"
/>
<Button type="submit" variant="default" className="h-10">
Start free
</Button>
</Label>
</form>
<p className="mt-3 text-xs text-muted-foreground">
No credit card required. Get your workspace ready in minutes.
</p>
</div>
</div>
<div className="relative min-w-0 lg:-mr-10">
<SpendWorkflowIllustration />
</div>
</div>
<StatsDock />
</div>
<div>
<LogoCloudFive />
</div>
</section>
)
}