176 lines
7.0 KiB
TypeScript
176 lines
7.0 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useState } from "react";
|
|
import { motion } from "framer-motion";
|
|
import { HeroActions } from "./hero-actions";
|
|
|
|
const heroVariants = {
|
|
hidden: { opacity: 0, y: 24 },
|
|
visible: {
|
|
opacity: 1,
|
|
y: 0,
|
|
transition: {
|
|
duration: 0.8,
|
|
ease: [0.16, 1, 0.3, 1] as const,
|
|
when: "beforeChildren",
|
|
staggerChildren: 0.08,
|
|
},
|
|
},
|
|
};
|
|
|
|
const heroChild = {
|
|
hidden: { opacity: 0, y: 16 },
|
|
visible: { opacity: 1, y: 0 },
|
|
};
|
|
|
|
export function LandingHero() {
|
|
const [range, setRange] = useState<"30" | "90">("30");
|
|
|
|
return (
|
|
<motion.section
|
|
initial="hidden"
|
|
animate="visible"
|
|
variants={heroVariants}
|
|
className="relative overflow-hidden pt-16 pb-12 lg:pt-20 lg:pb-16"
|
|
>
|
|
<div className="relative z-10 mx-auto flex max-w-6xl flex-col gap-12 px-6 lg:flex-row lg:items-center lg:px-8">
|
|
{/* Left: Copy */}
|
|
<div className="max-w-xl">
|
|
<motion.div variants={heroChild} className="space-y-8">
|
|
<motion.div variants={heroChild} className="badge-pill">
|
|
<span className="badge-pill-dot" />
|
|
<span className="uppercase tracking-[0.18em] text-[10px] text-emerald-500">
|
|
AI-native · Live predictions
|
|
</span>
|
|
</motion.div>
|
|
|
|
<motion.div variants={heroChild} className="space-y-5">
|
|
<h1 className="heading-hero">
|
|
Know Your Money{" "}
|
|
<span className="heading-hero-accent">Before You Spend It.</span>
|
|
</h1>
|
|
<p className="body-lead">
|
|
AI-powered insights, forecasts, and real-time financial control—without spreadsheets.
|
|
LedgerOne watches every account, predicts risk, and tells you what's safe to
|
|
spend before you click "checkout".
|
|
</p>
|
|
</motion.div>
|
|
|
|
<motion.div variants={heroChild} className="flex flex-wrap items-center gap-4">
|
|
<motion.div whileHover={{ y: -2, scale: 1.01 }} whileTap={{ scale: 0.98 }}>
|
|
<Link href="/register" className="btn-primary">
|
|
Get started in 2 minutes
|
|
</Link>
|
|
</motion.div>
|
|
<motion.div whileHover={{ y: -1, scale: 1.01 }} whileTap={{ scale: 0.98 }}>
|
|
<Link href="/book-demo" className="btn-secondary">
|
|
Watch product walkthrough
|
|
</Link>
|
|
</motion.div>
|
|
</motion.div>
|
|
|
|
<motion.div variants={heroChild} className="feature-bullets">
|
|
<div className="feature-bullet">
|
|
<span className="feature-bullet-dot" />
|
|
<span>Instant Plaid connections</span>
|
|
</div>
|
|
<div className="feature-bullet">
|
|
<span className="feature-bullet-dot animate-pulse" />
|
|
<span>Bank-grade security</span>
|
|
</div>
|
|
<div className="feature-bullet">
|
|
<span className="feature-bullet-dot" />
|
|
<span>14-day free trial</span>
|
|
</div>
|
|
</motion.div>
|
|
|
|
<motion.div variants={heroChild} className="mt-4">
|
|
<HeroActions />
|
|
</motion.div>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* Right: single focused product video with glow + AI insight */}
|
|
<motion.div
|
|
variants={heroChild}
|
|
className="relative mx-auto flex w-full max-w-xl items-center justify-center lg:max-w-xl"
|
|
>
|
|
{/* Depth: gradient glow behind video */}
|
|
<motion.div
|
|
className="pointer-events-none absolute -inset-10 rounded-[36px] bg-gradient-to-r from-blue-500/20 via-purple-500/20 to-green-400/20 blur-3xl"
|
|
animate={{ opacity: [0.4, 0.6, 0.4] }}
|
|
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut" }}
|
|
/>
|
|
|
|
{/* Primary product video card */}
|
|
<motion.div
|
|
className="relative z-10 w-full overflow-hidden rounded-2xl border border-white/10 shadow-2xl"
|
|
initial={{ opacity: 0, scale: 0.96, y: 10 }}
|
|
animate={{ opacity: 1, scale: 1.04, y: 0 }}
|
|
transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] as const }}
|
|
whileHover={{ scale: 1.08 }}
|
|
>
|
|
<div className="relative aspect-[16/9] w-full">
|
|
<video
|
|
className="h-full w-full object-cover"
|
|
autoPlay
|
|
muted
|
|
loop
|
|
playsInline
|
|
preload="none"
|
|
poster="/images/dashboard-hero.png"
|
|
>
|
|
<source src="/videos/hero.mp4" type="video/mp4" />
|
|
</video>
|
|
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-slate-950/70 via-slate-950/10 to-transparent" />
|
|
|
|
{/* Forecast toggle inside video */}
|
|
<div className="absolute left-4 top-4 inline-flex items-center gap-2 rounded-full bg-slate-950/80 px-2 py-1 text-[10px] text-slate-100 ring-1 ring-emerald-400/60 backdrop-blur-md">
|
|
<span className="inline-flex items-center gap-1">
|
|
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />
|
|
Cashflow outlook
|
|
</span>
|
|
<div className="inline-flex items-center gap-1 rounded-full bg-white/5 p-0.5">
|
|
<button
|
|
type="button"
|
|
onClick={() => setRange("30")}
|
|
className={`px-2 py-0.5 rounded-full transition-colors ${
|
|
range === "30" ? "bg-emerald-400/25 text-emerald-100" : "text-slate-200"
|
|
}`}
|
|
>
|
|
30d
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => setRange("90")}
|
|
className={`px-2 py-0.5 rounded-full transition-colors ${
|
|
range === "90" ? "bg-emerald-400/25 text-emerald-100" : "text-slate-200"
|
|
}`}
|
|
>
|
|
90d
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Floating AI insight card */}
|
|
<motion.div
|
|
className="absolute right-4 top-4 mt-10 w-64 rounded-xl border border-emerald-300/50 bg-white/80 px-4 py-2 text-xs text-slate-900 shadow-lg backdrop-blur-md dark:border-emerald-400/60 dark:bg-slate-900/90 dark:text-slate-50"
|
|
animate={{ y: [-2, 2, -2] }}
|
|
transition={{ duration: 7, repeat: Infinity, ease: "easeInOut", delay: 0.4 }}
|
|
>
|
|
<p className="text-[11px] leading-relaxed">
|
|
You're likely to overspend{" "}
|
|
<span className="font-semibold text-emerald-600 dark:text-emerald-300">$120</span>{" "}
|
|
this week based on upcoming bills and historical spending.
|
|
</p>
|
|
</motion.div>
|
|
</div>
|
|
</motion.div>
|
|
</motion.div>
|
|
</div>
|
|
</motion.section>
|
|
);
|
|
}
|
|
|