Agent Terminal Hero
A terminal types a prompt and streams an agent's plan while the generated dashboard assembles itself beside it.
A photoreal CSS-3D metal card that tilts to the cursor, then flips and docks on scroll while spend stats count up.
Browser support · All evergreen browsers. Glass panel uses backdrop-filter (opaque fallback with prefers-reduced-transparency).
npx shadcn@latest add https://freedesignmd.com/r/hero-fintech-card.json1/**2 * HeroFintechCard — an Apple-clean hero for a corporate card. A CSS-3D metal3 * card (front, back and a stacked edge for real thickness) floats, tilts4 * toward the cursor on a spring and catches a specular highlight. As the5 * section scrolls, a sticky stage scrubs the card through a full flip and docks6 * it into a spend panel while the stats count up with the scroll.7 *8 * Props: eyebrow, title (ReactNode), lede, primaryCta, secondaryCta,9 * holder, company, last4, stats ({ label, value, prefix?, suffix?, decimals? }[]).10 * CSS vars on the root: --fd-ldg-bg, --fd-ldg-ink, --fd-ldg-accent, --fd-ldg-card-w.11 *12 * Browser support: all evergreen browsers (CSS 3D transforms, clip-path).13 * Motion: pointer tilt (spring k=380, c=30), ambient float, scroll scrub via14 * rAF + getBoundingClientRect (transforms/opacity only). The loop pauses when15 * off-screen or when the tab is hidden. prefers-reduced-motion renders the16 * composed final state without a scroll scene.17 * Accessibility: the card is decorative (aria-hidden) and its details are18 * repeated in text; stats are a <dl>; CTAs are real links with focus rings.19 */20import { useEffect, useRef } from "react";21import type { ReactNode } from "react";22 23export type LedgerStat = { label: string; value: number; prefix?: string; suffix?: string; decimals?: number };24 25export interface HeroFintechCardProps {26 eyebrow?: ReactNode;27 title?: ReactNode;28 lede?: ReactNode;29 primaryCta?: { label: string; href: string };30 secondaryCta?: { label: string; href: string };31 holder?: string;32 company?: string;33 last4?: string;34 stats?: LedgerStat[];35 dockTitle?: ReactNode;36}37 38const clamp = (v: number, a = 0, b = 1) => Math.min(b, Math.max(a, v));39const ease = (t: number) => 1 - Math.pow(1 - t, 3);40const easeIO = (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);41const seg = (p: number, a: number, b: number) => clamp((p - a) / (b - a));42 43function offsetIn(el: HTMLElement, stop: HTMLElement) {44 let x = 0;45 let y = 0;46 let n: HTMLElement | null = el;47 while (n && n !== stop) {48 x += n.offsetLeft;49 y += n.offsetTop;50 n = n.offsetParent as HTMLElement | null;51 }52 return { x, y, w: el.offsetWidth, h: el.offsetHeight };53}54 55const fmt = (v: number, d = 0) => v.toLocaleString("en-US", { minimumFractionDigits: d, maximumFractionDigits: d });56 57const DEFAULT_STATS: LedgerStat[] = [58 { label: "Spend under policy this month", value: 1284610, prefix: "$" },59 { label: "Receipts matched automatically", value: 14920 },60 { label: "Days to close the books", value: 1.6, decimals: 1 },61 { label: "Cashback earned", value: 30830, prefix: "$" },62];63 64export function HeroFintechCard({65 eyebrow = (66 <>67 <b>New</b> 2.4% back on every SaaS invoice68 </>69 ),70 title = (71 <>72 <span className="fd-ldg-line"><span>The corporate</span></span>{" "}73 <span className="fd-ldg-line"><span>card that closes</span></span>{" "}74 <span className="fd-ldg-line"><span><em>your books.</em></span></span>75 </>76 ),77 lede = "Metal cards for every employee, policy enforced at the swipe, and every receipt reconciled to your general ledger before the month is out.",78 primaryCta = { label: "Open an account", href: "#open" },79 secondaryCta = { label: "Watch the 3-min tour", href: "#tour" },80 holder = "Amara Okonkwo",81 company = "Halden Robotics",82 last4 = "4021",83 stats = DEFAULT_STATS,84 dockTitle = "Every swipe, already reconciled.",85}: HeroFintechCardProps) {86 const root = useRef<HTMLElement>(null);87 const stage = useRef<HTMLDivElement>(null);88 const home = useRef<HTMLDivElement>(null);89 const slot = useRef<HTMLDivElement>(null);90 const anchor = useRef<HTMLDivElement>(null);91 const card = useRef<HTMLDivElement>(null);92 const shadow = useRef<HTMLDivElement>(null);93 const copy = useRef<HTMLDivElement>(null);94 const panel = useRef<HTMLDivElement>(null);95 const nums = useRef<(HTMLElement | null)[]>([]);96 97 useEffect(() => {98 const el = root.current;99 const st = stage.current;100 if (!el || !st) return;101 const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;102 let geo = { hx: 0, hy: 0, hw: 0, hh: 0, dx: 0, dy: 0, ds: 1 };103 const measure = () => {104 if (!home.current || !slot.current || !anchor.current) return;105 const h = offsetIn(home.current, st);106 const s = offsetIn(slot.current, st);107 anchor.current.style.left = `${h.x}px`;108 anchor.current.style.top = `${h.y}px`;109 anchor.current.style.width = `${h.w}px`;110 anchor.current.style.height = `${h.w / 1.586}px`;111 const hh = h.w / 1.586;112 if (shadow.current) {113 shadow.current.style.left = `${h.x + h.w * 0.05}px`;114 shadow.current.style.top = `${h.y + hh * 0.98}px`;115 }116 geo = {117 hx: h.x, hy: h.y, hw: h.w, hh,118 dx: s.x + s.w / 2 - (h.x + h.w / 2),119 dy: s.y + s.h / 2 - (h.y + hh / 2),120 ds: s.w / h.w,121 };122 };123 if (reduced) el.setAttribute("data-static", "");124 measure();125 const ro = new ResizeObserver(measure);126 ro.observe(st);127 if (reduced) {128 nums.current.forEach((n, i) => n && (n.textContent = fmt(stats[i].value, stats[i].decimals)));129 return () => ro.disconnect();130 }131 132 // springs for tilt133 const sp = { x: 0, y: 0, vx: 0, vy: 0, tx: 0, ty: 0 };134 const K = 380;135 const C = 30;136 const onMove = (e: PointerEvent) => {137 if (e.pointerType === "touch") return;138 const r = st.getBoundingClientRect();139 sp.tx = clamp(((e.clientX - r.left) / r.width) * 2 - 1, -1, 1);140 sp.ty = clamp(((e.clientY - r.top) / r.height) * 2 - 1, -1, 1);141 };142 const onLeave = () => {143 sp.tx = 0;144 sp.ty = 0;145 };146 el.addEventListener("pointermove", onMove);147 el.addEventListener("pointerleave", onLeave);148 149 let raf = 0;150 let last = 0;151 let visible = true;152 const t0 = performance.now();153 const lastShown: number[] = [];154 155 const frame = (now: number) => {156 raf = 0;157 const dt = Math.min((now - last) / 1000 || 0.016, 0.032);158 last = now;159 for (let i = 0; i < 2; i++) {160 const h = dt / 2;161 sp.vx += (-K * (sp.x - sp.tx) - C * sp.vx) * h;162 sp.vy += (-K * (sp.y - sp.ty) - C * sp.vy) * h;163 sp.x += sp.vx * h;164 sp.y += sp.vy * h;165 }166 const r = el.getBoundingClientRect();167 const vh = window.innerHeight;168 const travel = Math.max(1, r.height - st.offsetHeight);169 const p = clamp(-r.top / travel);170 const t = (now - t0) / 1000;171 172 // phases173 const flip = easeIO(seg(p, 0.06, 0.78));174 const dock = easeIO(seg(p, 0.12, 0.8));175 const settle = 1 - dock;176 const floatY = Math.sin(t * 1.1) * 7 * settle;177 const floatR = Math.sin(t * 0.7) * 1.2 * settle;178 const tiltX = (-sp.y * 14 + 9) * settle + 0 * dock;179 const tiltY = sp.x * 20 * settle - 14 * settle;180 const rotY = tiltY + flip * 360;181 const rotX = tiltX + Math.sin(flip * Math.PI) * -12;182 const sc = 1 + (geo.ds - 1) * dock;183 if (card.current) {184 card.current.style.transform = `translate3d(${(geo.dx * dock).toFixed(2)}px, ${(geo.dy * dock + floatY).toFixed(2)}px, 0) scale(${sc.toFixed(4)}) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg) rotateZ(${(floatR - 4 * settle).toFixed(2)}deg)`;185 // specular follows the light, which sits up-left of the pointer186 const facing = Math.cos((rotY * Math.PI) / 180);187 card.current.style.setProperty("--sx", `${(50 + sp.x * 38 - (rotY % 360) * 0.12).toFixed(1)}%`);188 card.current.style.setProperty("--sy", `${(35 + sp.y * 30).toFixed(1)}%`);189 card.current.style.setProperty("--gl", `${(0.55 + Math.abs(sp.x) * 0.35 + (1 - Math.abs(facing)) * 0.4).toFixed(3)}`);190 card.current.style.setProperty("--band", `${(sp.x * 30 + rotY * 0.18).toFixed(1)}%`);191 }192 if (shadow.current) {193 const lift = 1 - floatY / 30;194 shadow.current.style.transform = `translate3d(${(geo.dx * dock + sp.x * -18 * settle).toFixed(1)}px, ${(geo.dy * dock).toFixed(1)}px,0) scale(${(sc * lift).toFixed(3)}, ${(sc * lift * 0.9).toFixed(3)})`;195 shadow.current.style.opacity = `${(0.85 - dock * 0.55).toFixed(3)}`;196 }197 if (copy.current) {198 const c = seg(p, 0.02, 0.4);199 copy.current.style.transform = `translate3d(0, ${(-c * vh * 0.16).toFixed(1)}px, 0) scale(${(1 - c * 0.04).toFixed(4)})`;200 copy.current.style.opacity = `${(1 - ease(c)).toFixed(3)}`;201 }202 if (panel.current) {203 const q = ease(seg(p, 0.42, 0.78));204 panel.current.style.setProperty("--q", q.toFixed(4));205 }206 const cnt = ease(seg(p, 0.5, 0.92));207 nums.current.forEach((n, i) => {208 if (!n) return;209 const v = stats[i].value * cnt;210 const d = stats[i].decimals ?? 0;211 const key = Math.round(v * Math.pow(10, d));212 if (lastShown[i] === key) return;213 lastShown[i] = key;214 n.textContent = fmt(v, d);215 });216 if (visible && !document.hidden) raf = requestAnimationFrame(frame);217 };218 const start = () => {219 if (!raf && visible && !document.hidden) {220 last = performance.now();221 raf = requestAnimationFrame(frame);222 }223 };224 const io = new IntersectionObserver(([e]) => {225 visible = e.isIntersecting;226 if (visible) start();227 });228 io.observe(el);229 const onVis = () => start();230 document.addEventListener("visibilitychange", onVis);231 start();232 return () => {233 cancelAnimationFrame(raf);234 io.disconnect();235 ro.disconnect();236 document.removeEventListener("visibilitychange", onVis);237 el.removeEventListener("pointermove", onMove);238 el.removeEventListener("pointerleave", onLeave);239 };240 }, [stats]);241 242 const name = holder.toUpperCase();243 244 return (245 <section ref={root} className="fd-ldg" aria-label="Ledger corporate card">246 <style>{css}</style>247 <div ref={stage} className="fd-ldg-stage">248 <div className="fd-ldg-bgglow" aria-hidden="true" />249 <div className="fd-ldg-grid">250 <div ref={copy} className="fd-ldg-copy">251 <p className="fd-ldg-eyebrow">252 <span className="fd-ldg-pill">{eyebrow}</span>253 </p>254 <h1 className="fd-ldg-h1">{title}</h1>255 <p className="fd-ldg-lede">{lede}</p>256 <div className="fd-ldg-ctas">257 <a className="fd-ldg-btn" href={primaryCta.href}>258 {primaryCta.label}259 </a>260 <a className="fd-ldg-link" href={secondaryCta.href}>261 <span className="fd-ldg-play" aria-hidden="true">262 <svg viewBox="0 0 12 12" width="10" height="10"><path d="M3 1.8v8.4L10 6z" fill="currentColor" /></svg>263 </span>264 {secondaryCta.label}265 </a>266 </div>267 <p className="fd-ldg-fine">SOC 2 Type II · Issued by Calder Trust Bank, N.A., Member FDIC</p>268 </div>269 <div className="fd-ldg-visual">270 <div ref={home} className="fd-ldg-home" aria-hidden="true" />271 </div>272 </div>273 274 <div ref={panel} className="fd-ldg-panel">275 <div className="fd-ldg-panel-in">276 <div className="fd-ldg-slotwrap">277 <div ref={slot} className="fd-ldg-slot" aria-hidden="true" />278 <p className="fd-ldg-slotcap">279 {holder} · Corporate •••• {last4}280 </p>281 </div>282 <div className="fd-ldg-panel-copy">283 <p className="fd-ldg-panel-k">October · {company}</p>284 <h2 className="fd-ldg-h2">{dockTitle}</h2>285 <dl className="fd-ldg-stats">286 {stats.map((s, i) => (287 <div key={s.label} className="fd-ldg-stat" style={{ ["--i" as string]: i }}>288 <dt>{s.label}</dt>289 <dd>290 {s.prefix}291 <span ref={(n) => { nums.current[i] = n; }}>0</span>292 {s.suffix}293 </dd>294 </div>295 ))}296 </dl>297 </div>298 </div>299 </div>300 301 <div ref={shadow} className="fd-ldg-shadow-anchor" aria-hidden="true">302 <div className="fd-ldg-shadow" />303 </div>304 <div ref={anchor} className="fd-ldg-anchor" aria-hidden="true">305 <div className="fd-ldg-enter">306 <div ref={card} className="fd-ldg-card">307 {Array.from({ length: 7 }, (_, i) => (308 <div key={i} className="fd-ldg-edge" style={{ transform: `translateZ(${-(i + 1) * 0.55}px)` }} />309 ))}310 <div className="fd-ldg-face fd-ldg-front">311 <div className="fd-ldg-metal" />312 <div className="fd-ldg-band" />313 <div className="fd-ldg-sheen" />314 <div className="fd-ldg-fc">315 <div className="fd-ldg-row">316 <span className="fd-ldg-wm">LEDGER</span>317 <svg className="fd-ldg-nfc" viewBox="0 0 24 24" width="22" height="22">318 <path d="M7.5 8.5a5 5 0 0 1 0 7M11 6a9 9 0 0 1 0 12M14.5 3.5a13 13 0 0 1 0 17" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />319 </svg>320 </div>321 <div className="fd-ldg-chip">322 <i /><i /><i /><i />323 </div>324 <div className="fd-ldg-row fd-ldg-bottom">325 <div>326 <span className="fd-ldg-name">{name}</span>327 <span className="fd-ldg-co">{company}</span>328 </div>329 <div className="fd-ldg-right">330 <span className="fd-ldg-num">•••• {last4}</span>331 <span className="fd-ldg-net">332 <b /> CORPORATE333 </span>334 </div>335 </div>336 </div>337 </div>338 <div className="fd-ldg-face fd-ldg-back">339 <div className="fd-ldg-metal" />340 <div className="fd-ldg-stripe" />341 <div className="fd-ldg-band" />342 <div className="fd-ldg-sheen" />343 <div className="fd-ldg-bc">344 <div className="fd-ldg-sig">345 <span>{holder}</span>346 <b>CVV •••</b>347 </div>348 <p>349 This card is property of Calder Trust Bank, N.A. and is issued under licence to {company}. Lost or stolen: +1 (415) 555-0142 · ledger.example/help350 </p>351 <span className="fd-ldg-wm fd-ldg-wm-s">LEDGER</span>352 </div>353 </div>354 </div>355 </div>356 </div>357 </div>358 </section>359 );360}361 362const noise = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .22 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E")`;363 364const css = `365.fd-ldg, .fd-ldg *, .fd-ldg *::before, .fd-ldg *::after { box-sizing: border-box; }366.fd-ldg {367 --fd-ease-out: cubic-bezier(0.22, 1, 0.36, 1);368 --fd-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);369 --fd-spring: cubic-bezier(0.34, 1.56, 0.64, 1);370 --fd-dur-1: 120ms; --fd-dur-2: 240ms; --fd-dur-3: 420ms; --fd-dur-4: 700ms;371 --fd-ldg-bg: #F5F5F7;372 --fd-ldg-ink: #0B0B0F;373 --fd-ldg-slate: #6B6B76;374 --fd-ldg-accent: #007AFF;375 --fd-ldg-card-w: min(440px, 34vw);376 --fd-ldg-sans: "SF Pro Display", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif;377 position: relative; display: block; margin: 0; padding: 0;378 height: 185vh; min-height: 1200px;379 background: var(--fd-ldg-bg); color: var(--fd-ldg-ink);380 font: 400 1rem/1.5 var(--fd-ldg-sans);381 isolation: isolate;382}383.fd-ldg-stage {384 position: sticky; top: 0; height: 100vh; min-height: 640px; overflow: hidden;385 perspective: 1600px;386}387.fd-ldg-bgglow {388 position: absolute; inset: -10% -10% auto auto; width: 70%; height: 110%; pointer-events: none;389 background:390 radial-gradient(40% 38% at 62% 46%, rgba(160, 182, 255, 0.38), transparent 70%),391 radial-gradient(30% 30% at 78% 66%, rgba(255, 196, 168, 0.32), transparent 70%),392 radial-gradient(28% 26% at 52% 22%, rgba(196, 236, 255, 0.5), transparent 70%);393 filter: blur(10px);394 animation: fd-ldg-fade 1400ms var(--fd-ease-out) both;395}396.fd-ldg-grid {397 position: relative; z-index: 2; height: 100%;398 max-width: 1240px; margin: 0 auto; padding: 120px 40px 64px;399 display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); align-items: center; gap: 40px;400}401.fd-ldg-copy { will-change: transform, opacity; }402.fd-ldg-eyebrow { margin: 0 0 28px; padding: 0; }403.fd-ldg-pill {404 display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 6px 14px 6px 6px;405 border-radius: 9999px; background: #fff; border: 1px solid rgba(11, 11, 15, 0.06);406 box-shadow: 0 1px 2px rgba(11, 11, 15, 0.04), 0 8px 24px -12px rgba(11, 11, 15, 0.18);407 font: 500 0.8125rem/1.2 var(--fd-ldg-sans); letter-spacing: -0.005em; color: #2a2a31;408 animation: fd-ldg-rise var(--fd-dur-4) var(--fd-ease-out) 80ms both;409}410.fd-ldg-pill b {411 font: 600 0.75rem/1 var(--fd-ldg-sans); letter-spacing: 0.01em; color: #fff;412 background: linear-gradient(180deg, #1a8cff, #0063d6); padding: 5px 9px; border-radius: 9999px;413}414.fd-ldg-h1 {415 margin: 0; padding: 0; color: var(--fd-ldg-ink);416 font: 600 clamp(2.75rem, 5.1vw, 4.75rem)/1 var(--fd-ldg-sans);417 letter-spacing: -0.045em; text-wrap: balance;418}419.fd-ldg-line { display: block; overflow: hidden; padding: 0 0 0.08em; margin: 0 0 -0.08em; }420.fd-ldg-line > span { display: inline-block; animation: fd-ldg-mask var(--fd-dur-4) var(--fd-ease-out) both; }421.fd-ldg-line:nth-child(2) > span { animation-delay: 90ms; }422.fd-ldg-line:nth-child(3) > span { animation-delay: 180ms; }423.fd-ldg-h1 em {424 font-style: normal;425 background: linear-gradient(100deg, #0B0B0F 0%, #4a4a57 40%, #8d8d9a 100%);426 -webkit-background-clip: text; background-clip: text; color: transparent;427}428.fd-ldg-lede {429 margin: 28px 0 0; padding: 0; max-width: 30rem; color: var(--fd-ldg-slate);430 font: 400 clamp(1.0625rem, 1.25vw, 1.25rem)/1.5 var(--fd-ldg-sans); letter-spacing: -0.012em; text-wrap: pretty;431 animation: fd-ldg-rise var(--fd-dur-4) var(--fd-ease-out) 260ms both;432}433.fd-ldg-ctas { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; margin: 36px 0 0; animation: fd-ldg-rise var(--fd-dur-4) var(--fd-ease-out) 360ms both; }434.fd-ldg-btn {435 display: inline-flex; align-items: center; margin: 0; padding: 0 24px; height: 50px; border-radius: 9999px;436 background: var(--fd-ldg-ink); color: #fff; text-decoration: none; border: 0;437 font: 500 1rem/1 var(--fd-ldg-sans); letter-spacing: -0.01em;438 box-shadow: 0 1px 0 rgba(255,255,255,.12) inset, 0 10px 30px -10px rgba(11, 11, 15, 0.55);439 transition: transform var(--fd-dur-2) var(--fd-spring), background var(--fd-dur-1);440}441.fd-ldg-btn:hover { background: #24242b; }442.fd-ldg-btn:active { transform: scale(0.96); transition-duration: var(--fd-dur-1); transition-timing-function: var(--fd-ease-out); }443.fd-ldg-link {444 display: inline-flex; align-items: center; gap: 10px; margin: 0; padding: 0; color: var(--fd-ldg-ink); text-decoration: none;445 font: 500 1rem/1 var(--fd-ldg-sans); letter-spacing: -0.01em;446}447.fd-ldg-play {448 display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 9999px; padding-left: 2px;449 background: #fff; color: var(--fd-ldg-ink); box-shadow: 0 0 0 1px rgba(11,11,15,.08), 0 4px 12px -4px rgba(11,11,15,.2);450 transition: transform var(--fd-dur-2) var(--fd-spring);451}452.fd-ldg-play svg { display: block; }453.fd-ldg-link:hover .fd-ldg-play { transform: scale(1.1); }454.fd-ldg-btn:focus-visible, .fd-ldg-link:focus-visible { outline: 2px solid rgba(0, 122, 255, 0.7); outline-offset: 2px; }455.fd-ldg-fine { margin: 40px 0 0; padding: 0; color: #8a8a95; font: 400 0.8125rem/1.4 var(--fd-ldg-sans); letter-spacing: 0; animation: fd-ldg-fade var(--fd-dur-4) var(--fd-ease-out) 520ms both; }456 457.fd-ldg-visual { position: relative; height: 100%; display: grid; place-items: center; }458.fd-ldg-home { width: var(--fd-ldg-card-w); aspect-ratio: 1.586; margin: 0 0 0 4%; }459 460.fd-ldg-anchor { position: absolute; left: 0; top: 0; z-index: 5; perspective: 1400px; pointer-events: none; }461.fd-ldg-enter { width: 100%; height: 100%; transform-style: preserve-3d; animation: fd-ldg-cardin 1100ms var(--fd-ease-out) 120ms both; }462.fd-ldg-card {463 position: relative; width: 100%; height: 100%; transform-style: preserve-3d; will-change: transform;464 transform: rotateX(9deg) rotateY(-14deg) rotateZ(-4deg);465 --sx: 40%; --sy: 30%; --gl: .6; --band: 0%;466}467.fd-ldg-face, .fd-ldg-edge {468 position: absolute; inset: 0; border-radius: 4.6% / 7.3%; overflow: hidden;469 backface-visibility: hidden; -webkit-backface-visibility: hidden;470}471.fd-ldg-edge { background: linear-gradient(90deg, #4c4d55, #9a9ba4 30%, #3b3c43 60%, #8e8f98); backface-visibility: visible; -webkit-backface-visibility: visible; }472.fd-ldg-back { transform: translateZ(-4.4px) rotateY(180deg); }473.fd-ldg-metal {474 position: absolute; inset: 0;475 background:476 ${noise},477 repeating-linear-gradient(90deg, rgba(255,255,255,0.035) 0 1px, rgba(0,0,0,0.04) 1px 2px, transparent 2px 4px),478 linear-gradient(160deg, rgba(255,255,255,0.10), transparent 35%, transparent 70%, rgba(255,255,255,0.05)),479 radial-gradient(120% 140% at 0% 0%, #2c2d34 0%, #16171b 48%, #0b0b0e 100%);480 background-size: 160px 160px, auto, auto, auto;481 box-shadow: inset 0 0 0 1px rgba(255,255,255,0.09), inset 0 1px 0 rgba(255,255,255,0.18);482}483.fd-ldg-band {484 position: absolute; inset: -40%; pointer-events: none; mix-blend-mode: screen; opacity: .9;485 background: linear-gradient(115deg, transparent 34%, rgba(120,160,255,0.12) 42%, rgba(255,255,255,0.30) 49%, rgba(255,255,255,0.08) 52%, rgba(255,180,150,0.12) 58%, transparent 66%);486 transform: translateX(var(--band));487}488.fd-ldg-sheen {489 position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; opacity: var(--gl);490 background: radial-gradient(50% 70% at var(--sx) var(--sy), rgba(255,255,255,0.26), rgba(255,255,255,0.05) 45%, transparent 70%);491}492.fd-ldg-fc, .fd-ldg-bc { position: absolute; inset: 0; padding: 7% 7.5%; display: flex; flex-direction: column; justify-content: space-between; color: #e9e9ef; }493.fd-ldg-row { display: flex; justify-content: space-between; align-items: center; }494.fd-ldg-bottom { align-items: flex-end; }495.fd-ldg-wm {496 font: 600 clamp(0.75rem, 1.05vw, 0.9375rem)/1 var(--fd-ldg-sans); letter-spacing: 0.34em;497 background: linear-gradient(180deg, #ffffff, #b9bac4 60%, #8c8d97); -webkit-background-clip: text; background-clip: text; color: transparent;498 filter: drop-shadow(0 1px 0 rgba(0,0,0,0.5));499}500.fd-ldg-nfc { display: block; color: rgba(235,235,242,0.75); width: 9%; height: auto; }501.fd-ldg-chip {502 position: relative; width: 15%; aspect-ratio: 1.3; border-radius: 18%; margin: -2% 0 0;503 background: linear-gradient(135deg, #f3e2b4 0%, #c9a65e 35%, #f7e7bd 55%, #a8853f 100%);504 box-shadow: inset 0 0 0 1px rgba(80,55,10,0.35), 0 1px 1px rgba(0,0,0,0.4);505}506.fd-ldg-chip i { position: absolute; display: block; background: rgba(90,62,15,0.38); }507.fd-ldg-chip i:nth-child(1) { left: 0; right: 0; top: 33%; height: 1px; }508.fd-ldg-chip i:nth-child(2) { left: 0; right: 0; top: 66%; height: 1px; }509.fd-ldg-chip i:nth-child(3) { top: 0; bottom: 0; left: 36%; width: 1px; }510.fd-ldg-chip i:nth-child(4) { top: 22%; bottom: 22%; left: 36%; right: 36%; width: auto; background: transparent; border: 1px solid rgba(90,62,15,0.38); border-radius: 3px; }511.fd-ldg-name, .fd-ldg-co, .fd-ldg-num { display: block; margin: 0; }512.fd-ldg-name { font: 500 clamp(0.6875rem, 0.95vw, 0.875rem)/1.2 var(--fd-ldg-sans); letter-spacing: 0.14em; color: #ececf2; text-shadow: 0 1px 0 rgba(0,0,0,0.6); }513.fd-ldg-co { margin-top: 4px; font: 400 clamp(0.5625rem, 0.75vw, 0.6875rem)/1.2 var(--fd-ldg-sans); letter-spacing: 0.04em; color: #9d9ea9; }514.fd-ldg-right { text-align: right; }515.fd-ldg-num { font: 500 clamp(0.6875rem, 0.95vw, 0.875rem)/1.2 ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 0.1em; color: #d6d6de; }516.fd-ldg-net { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font: 600 clamp(0.5rem, 0.62vw, 0.5625rem)/1 var(--fd-ldg-sans); letter-spacing: 0.22em; color: #a4a5b0; }517.fd-ldg-net b { display: block; width: 14px; height: 14px; border-radius: 4px; background: conic-gradient(from 210deg, #8fb4ff, #f4c2ff, #ffd5a8, #8fb4ff); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.4); }518.fd-ldg-stripe { position: absolute; left: 0; right: 0; top: 11%; height: 19%; background: linear-gradient(180deg, #070708, #17171b); }519.fd-ldg-bc { justify-content: flex-end; gap: 7%; }520.fd-ldg-sig { display: flex; align-items: center; justify-content: space-between; gap: 12px; height: 18%; padding: 0 4%; border-radius: 4px; background: repeating-linear-gradient(-45deg, #e9e6dd 0 4px, #dcd8cc 4px 8px); }521.fd-ldg-sig span { font: italic 400 clamp(0.75rem, 1.1vw, 1rem)/1 ui-serif, "New York", "Iowan Old Style", Georgia, serif; color: #2b2b33; }522.fd-ldg-sig b { font: 600 clamp(0.5rem, 0.7vw, 0.625rem)/1 ui-monospace, "SF Mono", Menlo, monospace; color: #2b2b33; letter-spacing: 0.08em; }523.fd-ldg-bc p { margin: 0; padding: 0; max-width: 88%; font: 400 clamp(0.4375rem, 0.58vw, 0.5625rem)/1.45 var(--fd-ldg-sans); color: #8e8f9a; letter-spacing: 0.01em; }524.fd-ldg-wm-s { font-size: clamp(0.5625rem, 0.75vw, 0.6875rem); align-self: flex-end; }525 526.fd-ldg-shadow-anchor { position: absolute; z-index: 1; left: 0; top: 0; width: 0; height: 0; pointer-events: none; will-change: transform; }527.fd-ldg-shadow {528 position: absolute; width: calc(var(--fd-ldg-card-w) * 0.9); height: calc(var(--fd-ldg-card-w) * 0.2); left: 0; top: 0;529 border-radius: 50%; background: radial-gradient(closest-side, rgba(20, 22, 40, 0.34), rgba(20,22,40,0.12) 60%, transparent);530 filter: blur(14px); animation: fd-ldg-fade 1200ms var(--fd-ease-out) 300ms both;531}532 533.fd-ldg-panel {534 --q: 0;535 position: absolute; z-index: 3; left: 0; right: 0; bottom: 7vh; width: min(1040px, calc(100% - 48px)); margin: 0 auto;536 transform: translate3d(0, calc((1 - var(--q)) * 48px), 0) scale(calc(0.96 + var(--q) * 0.04));537 opacity: var(--q); pointer-events: none;538}539.fd-ldg-panel-in {540 display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr); gap: 40px; align-items: center;541 padding: 28px; border-radius: 28px;542 background: rgba(255,255,255,0.72); border: 1px solid rgba(255,255,255,0.9);543 box-shadow: 0 1px 0 rgba(255,255,255,0.9) inset, 0 30px 80px -30px rgba(30, 34, 60, 0.28), 0 0 0 1px rgba(11,11,15,0.04);544 -webkit-backdrop-filter: blur(24px) saturate(1.6); backdrop-filter: blur(24px) saturate(1.6);545}546.fd-ldg-slotwrap { margin: 0; }547.fd-ldg-slot { width: 100%; aspect-ratio: 1.586; border-radius: 4.6% / 7.3%; background: linear-gradient(180deg, #ececf1, #f6f6f9); box-shadow: inset 0 2px 6px rgba(11,11,15,0.08), inset 0 0 0 1px rgba(11,11,15,0.05); }548.fd-ldg-slotcap { margin: 14px 0 0; padding: 0; font: 500 0.8125rem/1.3 var(--fd-ldg-sans); color: var(--fd-ldg-slate); letter-spacing: 0; }549.fd-ldg-panel-k { margin: 0; padding: 0; font: 600 0.75rem/1 var(--fd-ldg-sans); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fd-ldg-accent); }550.fd-ldg-h2 { margin: 10px 0 0; padding: 0; font: 600 clamp(1.5rem, 2.4vw, 2rem)/1.1 var(--fd-ldg-sans); letter-spacing: -0.03em; color: var(--fd-ldg-ink); text-wrap: balance; }551.fd-ldg-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 28px; margin: 22px 0 0; padding: 0; }552.fd-ldg-stat { margin: 0; padding: 14px 0 0; border-top: 1px solid rgba(11,11,15,0.08); }553.fd-ldg-stat dt { margin: 0; padding: 0; font: 400 0.8125rem/1.3 var(--fd-ldg-sans); color: var(--fd-ldg-slate); letter-spacing: 0; }554.fd-ldg-stat dd { margin: 6px 0 0; padding: 0; font: 600 clamp(1.5rem, 2.3vw, 2rem)/1 var(--fd-ldg-sans); letter-spacing: -0.03em; color: var(--fd-ldg-ink); font-variant-numeric: tabular-nums; }555 556@keyframes fd-ldg-mask { from { transform: translateY(105%); } to { transform: none; } }557@keyframes fd-ldg-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }558@keyframes fd-ldg-fade { from { opacity: 0; } to { opacity: 1; } }559@keyframes fd-ldg-cardin {560 from { opacity: 0; transform: translate3d(40px, 80px, -260px) rotateY(-38deg) rotateX(18deg); filter: blur(10px); }561 60% { filter: blur(0); }562 to { opacity: 1; transform: none; filter: none; }563}564 565@media (max-width: 820px) {566 .fd-ldg { --fd-ldg-card-w: min(340px, 78vw); height: 175vh; min-height: 1300px; }567 .fd-ldg-grid { grid-template-columns: 1fr; grid-template-rows: auto 1fr; padding: 96px 20px 32px; gap: 8px; align-content: start; }568 .fd-ldg-visual { min-height: 260px; }569 .fd-ldg-home { margin: 0; }570 .fd-ldg-fine { display: none; }571 .fd-ldg-ctas { margin-top: 28px; gap: 18px; }572 .fd-ldg-lede { margin-top: 20px; }573 .fd-ldg-eyebrow { margin-bottom: 20px; }574 .fd-ldg-panel { bottom: 20px; width: calc(100% - 32px); }575 .fd-ldg-panel-in { grid-template-columns: 1fr; gap: 18px; padding: 18px; border-radius: 24px; }576 .fd-ldg-slotwrap { width: 52%; margin: 0 auto; }577 .fd-ldg-slotcap { display: none; }578 .fd-ldg-stats { gap: 12px 18px; margin-top: 14px; }579 .fd-ldg-stat { padding-top: 10px; }580 .fd-ldg-stat dd { font-size: 1.375rem; }581 .fd-ldg-stat dt { font-size: 0.75rem; }582 .fd-ldg-h2 { font-size: 1.375rem; }583}584 585.fd-ldg[data-static] { height: auto; min-height: 0; }586.fd-ldg[data-static] .fd-ldg-stage { position: relative; height: auto; min-height: 100vh; overflow: hidden; display: flex; flex-direction: column; }587.fd-ldg[data-static] .fd-ldg-grid { height: auto; min-height: 88vh; }588.fd-ldg[data-static] .fd-ldg-enter { animation: none; }589.fd-ldg[data-static] .fd-ldg-panel { position: relative; left: auto; bottom: auto; transform: none; opacity: 1; margin: 0 auto 64px; }590.fd-ldg[data-static] .fd-ldg-slotwrap { display: none; }591.fd-ldg[data-static] .fd-ldg-panel-in { grid-template-columns: 1fr; }592@media (prefers-reduced-motion: reduce) {593 .fd-ldg *, .fd-ldg *::before { animation: none !important; transition-duration: 1ms !important; }594}595@media (prefers-reduced-transparency: reduce) {596 .fd-ldg-panel-in { background: #fff; -webkit-backdrop-filter: none; backdrop-filter: none; }597}598`;599 600/* ───────────────────────── Demo ───────────────────────── */601 602export function Demo() {603 return (604 <div className="fd-ldg-demo">605 <style>{demoCss}</style>606 <header className="fd-ldg-demo-nav">607 <a className="fd-ldg-demo-logo" href="#top" aria-label="Ledger home">608 <svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true">609 <rect x="1" y="4" width="18" height="12" rx="3" fill="#0B0B0F" />610 <rect x="1" y="7" width="18" height="2.4" fill="#fff" opacity=".9" />611 </svg>612 Ledger613 </a>614 <nav aria-label="Primary">615 <a href="#cards">Cards</a>616 <a href="#spend">Spend</a>617 <a href="#bills">Bill pay</a>618 <a href="#treasury">Treasury</a>619 <a href="#pricing">Pricing</a>620 </nav>621 <div className="fd-ldg-demo-actions">622 <a href="#signin">Sign in</a>623 <a className="fd-ldg-demo-cta" href="#open">Get started</a>624 </div>625 </header>626 <HeroFintechCard />627 <section className="fd-ldg-demo-after" aria-label="Customers">628 <p>Running finance at 38,000 companies — from seed to IPO</p>629 <ul>630 <li>Halden Robotics</li>631 <li>Northwind Bio</li>632 <li>Kestrel Air</li>633 <li>Oslo Freight</li>634 <li>Marlow & Finch</li>635 <li>Tidewater</li>636 </ul>637 </section>638 </div>639 );640}641 642const demoCss = `643.fd-ldg-demo { position: relative; margin: 0; padding: 0; min-height: 100vh; background: #F5F5F7; color: #0B0B0F; font: 400 1rem/1.5 ui-sans-serif, -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif; }644.fd-ldg-demo *, .fd-ldg-demo *::before, .fd-ldg-demo *::after { box-sizing: border-box; }645.fd-ldg-demo-nav {646 position: absolute; z-index: 20; top: 0; left: 0; right: 0; height: 72px; margin: 0 auto; max-width: 1240px; padding: 0 40px;647 display: flex; align-items: center; justify-content: space-between; gap: 24px;648 animation: fd-ldg-demo-in 700ms cubic-bezier(0.22, 1, 0.36, 1) both;649}650.fd-ldg-demo-nav .fd-ldg-demo-logo { display: inline-flex; align-items: center; gap: 9px; margin: 0; color: #0B0B0F; text-decoration: none; font: 600 1.0625rem/1 "SF Pro Display", ui-sans-serif, -apple-system, "Inter", sans-serif; letter-spacing: -0.02em; }651.fd-ldg-demo-logo svg { display: block; }652.fd-ldg-demo-nav nav { display: flex; gap: 30px; margin: 0; padding: 0; }653.fd-ldg-demo-nav a { color: #3a3a42; text-decoration: none; font: 500 0.875rem/1 ui-sans-serif, -apple-system, "Inter", sans-serif; letter-spacing: -0.005em; }654.fd-ldg-demo-nav nav a:hover, .fd-ldg-demo-actions a:hover { color: #0B0B0F; }655.fd-ldg-demo-actions { display: flex; align-items: center; gap: 20px; }656.fd-ldg-demo-actions .fd-ldg-demo-cta { display: inline-flex; align-items: center; height: 34px; padding: 0 16px; border-radius: 9999px; background: #fff; color: #0B0B0F; box-shadow: 0 0 0 1px rgba(11,11,15,.1), 0 2px 6px -2px rgba(11,11,15,.15); }657.fd-ldg-demo-nav a:focus-visible { outline: 2px solid rgba(0,122,255,.7); outline-offset: 2px; border-radius: 6px; }658.fd-ldg-demo-after { margin: 0; padding: 72px 24px 120px; text-align: center; background: #F5F5F7; }659.fd-ldg-demo-after p { margin: 0; padding: 0; color: #6B6B76; font: 500 0.875rem/1.4 ui-sans-serif, -apple-system, "Inter", sans-serif; }660.fd-ldg-demo-after ul { display: flex; flex-wrap: wrap; justify-content: center; gap: 18px 48px; margin: 28px auto 0; padding: 0; list-style: none; max-width: 980px; }661.fd-ldg-demo-after li { margin: 0; padding: 0; color: #9a9aa4; font: 600 1.25rem/1 "SF Pro Display", ui-sans-serif, -apple-system, "Inter", sans-serif; letter-spacing: -0.03em; }662@keyframes fd-ldg-demo-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }663@media (max-width: 820px) {664 .fd-ldg-demo-nav { padding: 0 20px; height: 64px; }665 .fd-ldg-demo-nav nav, .fd-ldg-demo-actions a:not(.fd-ldg-demo-cta) { display: none; }666}667@media (prefers-reduced-motion: reduce) { .fd-ldg-demo-nav { animation: none; } }668`;A terminal types a prompt and streams an agent's plan while the generated dashboard assembles itself beside it.
A giant serif masthead and procedural duotone fabric frames revealed by clip-path wipes, drifting apart on scroll.
A layered SVG landscape with deep pointer and scroll parallax, a mirrored lake and golden hour fading to dusk.