1/**
2 * Vault — monochrome business-banking landing page.
3 *
4 * A complete, self-contained single page: React is the only import and every
5 * style lives in the <style> block at the bottom of this file (classes are
6 * prefixed `fd-vlt-`). Drop it into any React 18+ project and render <Page />.
7 *
8 * Motion: CSS-keyframe headline mask reveal, live balance odometer, pointer
9 * tilt driven by a small spring integrator, a sticky scene where a dashboard
10 * assembles from scroll progress, a pinned horizontal capability rail,
11 * count-up stats, compliance marquee, segmented pricing with a spring thumb
12 * and grid-row FAQ accordions.
13 *
14 * Browser support: evergreen browsers. Uses position: sticky, CSS custom
15 * properties, IntersectionObserver and requestAnimationFrame.
16 * Accessibility: semantic landmarks, real buttons, radiogroup pricing switch,
17 * aria-expanded accordions, visible focus rings, prefers-reduced-motion and
18 * prefers-contrast fallbacks. SSR-safe (no window access during render).
19 */
20import { useEffect, useId, useRef, useState, type CSSProperties, type ReactNode } from "react";
21
22/* ─────────────────────────── helpers ─────────────────────────── */
23
24const prefersReducedMotion = () =>
25 typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
26
27const clamp01 = (n: number) => (n < 0 ? 0 : n > 1 ? 1 : n);
28const easeOut = (t: number) => 1 - Math.pow(1 - t, 3);
29
30/** Adds `data-in` to every [data-reveal] descendant as it enters the viewport. */
31function useReveal(root: React.RefObject<HTMLElement | null>) {
32 useEffect(() => {
33 const el = root.current;
34 if (!el) return;
35 el.setAttribute("data-js", "");
36 const items = Array.from(el.querySelectorAll<HTMLElement>("[data-reveal]"));
37 if (typeof IntersectionObserver === "undefined" || prefersReducedMotion()) {
38 items.forEach((i) => i.setAttribute("data-in", ""));
39 return;
40 }
41 const io = new IntersectionObserver(
42 (entries) => {
43 for (const e of entries) {
44 if (e.isIntersecting) {
45 e.target.setAttribute("data-in", "");
46 io.unobserve(e.target);
47 }
48 }
49 },
50 { rootMargin: "0px 0px -8% 0px", threshold: 0 },
51 );
52 items.forEach((i) => io.observe(i));
53 return () => io.disconnect();
54 }, [root]);
55}
56
57/**
58 * Calls `fn` on every animation frame while `ref` is near the viewport and the
59 * page scrolls or resizes. `fn` reads layout and writes transforms/vars only.
60 */
61function useScrollFrame(ref: React.RefObject<HTMLElement | null>, fn: () => void) {
62 const fnRef = useRef(fn);
63 fnRef.current = fn;
64 useEffect(() => {
65 const el = ref.current;
66 if (!el) return;
67 let raf = 0;
68 let active = true;
69 const run = () => {
70 raf = 0;
71 if (active) fnRef.current();
72 };
73 const queue = () => {
74 if (!raf) raf = requestAnimationFrame(run);
75 };
76 const io =
77 typeof IntersectionObserver !== "undefined"
78 ? new IntersectionObserver(
79 ([e]) => {
80 active = e.isIntersecting;
81 if (active) queue();
82 },
83 { rootMargin: "200px 0px" },
84 )
85 : undefined;
86 io?.observe(el);
87 queue();
88 window.addEventListener("scroll", queue, { passive: true });
89 window.addEventListener("resize", queue);
90 return () => {
91 io?.disconnect();
92 window.removeEventListener("scroll", queue);
93 window.removeEventListener("resize", queue);
94 if (raf) cancelAnimationFrame(raf);
95 };
96 }, [ref]);
97}
98
99/** Progress (0→1) of a tall sticky section: 0 when its top hits the viewport top, 1 when its bottom does. */
100function pinnedProgress(el: HTMLElement) {
101 const r = el.getBoundingClientRect();
102 const vh = window.innerHeight;
103 const travel = r.height - vh;
104 if (travel <= 1) return clamp01((vh * 0.9 - r.top) / (vh * 0.7));
105 return clamp01(-r.top / travel);
106}
107
108/* ─────────────────────────── odometer ─────────────────────────── */
109
110const DIGITS = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
111
112function Odometer({ value, className = "" }: { value: string; className?: string }) {
113 const chars = value.split("");
114 return (
115 <span className={`fd-vlt-odo ${className}`}>
116 <span className="fd-vlt-sr">{value}</span>
117 {chars.map((c, i) => {
118 const fromRight = chars.length - i;
119 if (!/\d/.test(c)) {
120 return (
121 <span key={`s${fromRight}${c}`} className="fd-vlt-odo-sep" aria-hidden="true">
122 {c}
123 </span>
124 );
125 }
126 return (
127 <span key={`d${fromRight}`} className="fd-vlt-odo-col" aria-hidden="true">
128 <span
129 className="fd-vlt-odo-strip"
130 style={{ transform: `translateY(-${Number(c) * 10}%)`, transitionDelay: `${fromRight * 22}ms` }}
131 >
132 {DIGITS.map((d) => (
133 <span key={d}>{d}</span>
134 ))}
135 </span>
136 </span>
137 );
138 })}
139 </span>
140 );
141}
142
143const usd = (n: number) =>
144 n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
145
146/* ─────────────────────────── icons ─────────────────────────── */
147
148function Logo() {
149 return (
150 <svg className="fd-vlt-logo" viewBox="0 0 24 24" width="22" height="22" aria-hidden="true">
151 <rect x="1.5" y="1.5" width="21" height="21" fill="none" stroke="currentColor" strokeWidth="1.5" />
152 <path d="M6 7l6 10 6-10" fill="none" stroke="currentColor" strokeWidth="1.5" />
153 </svg>
154 );
155}
156
157function Arrow() {
158 return (
159 <svg className="fd-vlt-arrow" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
160 <path d="M3 8h9.5M8.5 3.5L13 8l-4.5 4.5" fill="none" stroke="currentColor" strokeWidth="1.5" />
161 </svg>
162 );
163}
164
165function Check() {
166 return (
167 <svg className="fd-vlt-check" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
168 <path d="M3 8.5l3.2 3L13 4.5" fill="none" stroke="currentColor" strokeWidth="1.6" />
169 </svg>
170 );
171}
172
173/* ─────────────────────────── nav ─────────────────────────── */
174
175const NAV = [
176 { href: "#platform", label: "Platform" },
177 { href: "#capabilities", label: "Capabilities" },
178 { href: "#security", label: "Security" },
179 { href: "#pricing", label: "Pricing" },
180 { href: "#faq", label: "FAQ" },
181];
182
183function Nav() {
184 const [condensed, setCondensed] = useState(false);
185 const [open, setOpen] = useState(false);
186 useEffect(() => {
187 const on = () => setCondensed(window.scrollY > 16);
188 on();
189 window.addEventListener("scroll", on, { passive: true });
190 return () => window.removeEventListener("scroll", on);
191 }, []);
192 return (
193 <header className="fd-vlt-nav" data-condensed={condensed || undefined} data-open={open || undefined}>
194 <div className="fd-vlt-nav-in">
195 <a className="fd-vlt-brand" href="#top" aria-label="Vault home">
196 <Logo />
197 <span>Vault</span>
198 </a>
199 <nav className="fd-vlt-nav-links" aria-label="Primary">
200 {NAV.map((n) => (
201 <a key={n.href} href={n.href}>
202 {n.label}
203 </a>
204 ))}
205 </nav>
206 <div className="fd-vlt-nav-cta">
207 <a className="fd-vlt-nav-signin" href="#top">
208 Sign in
209 </a>
210 <a className="fd-vlt-btn fd-vlt-btn-sm" href="#pricing">
211 Open account
212 </a>
213 <button
214 type="button"
215 className="fd-vlt-burger"
216 aria-label={open ? "Close menu" : "Open menu"}
217 aria-expanded={open}
218 onClick={() => setOpen((o) => !o)}
219 >
220 <span />
221 <span />
222 </button>
223 </div>
224 </div>
225 <div className="fd-vlt-sheet" hidden={!open}>
226 {NAV.map((n) => (
227 <a key={n.href} href={n.href} onClick={() => setOpen(false)}>
228 {n.label}
229 </a>
230 ))}
231 <a className="fd-vlt-btn" href="#pricing" onClick={() => setOpen(false)}>
232 Open account <Arrow />
233 </a>
234 </div>
235 </header>
236 );
237}
238
239/* ─────────────────────────── hero ─────────────────────────── */
240
241type Txn = { id: number; who: string; memo: string; amount: number };
242const INCOMING: Omit<Txn, "id">[] = [
243 { who: "Northwind Freight", memo: "Invoice 4471 · ACH", amount: 18400 },
244 { who: "AWS", memo: "Card ••3391", amount: -2316.48 },
245 { who: "Halcyon Health", memo: "Wire · SWIFT", amount: 62250 },
246 { who: "Gusto Payroll", memo: "Batch 10/31", amount: -41880.12 },
247 { who: "Lumen Bio", memo: "Invoice 4473 · RTP", amount: 9120 },
248 { who: "Figma", memo: "Card ••0815", amount: -1440 },
249];
250
251function BalanceCard() {
252 const cardRef = useRef<HTMLDivElement>(null);
253 const [balance, setBalance] = useState(4812390.22);
254 const [txns, setTxns] = useState<Txn[]>([
255 { id: -1, who: "Atlas Robotics", memo: "Invoice 4470 · Wire", amount: 120000 },
256 { id: -2, who: "Ramp Lease Co.", memo: "Rent · ACH", amount: -28500 },
257 { id: -3, who: "Parcel & Co", memo: "Invoice 4468 · RTP", amount: 7310.5 },
258 ]);
259
260 // Live feed: a new settlement lands every few seconds while visible.
261 useEffect(() => {
262 if (prefersReducedMotion()) return;
263 let i = 0;
264 let visible = true;
265 const el = cardRef.current;
266 const io =
267 el && typeof IntersectionObserver !== "undefined"
268 ? new IntersectionObserver(([e]) => (visible = e.isIntersecting))
269 : undefined;
270 if (el) io?.observe(el);
271 const id = window.setInterval(() => {
272 if (!visible || document.hidden) return;
273 const t = INCOMING[i % INCOMING.length];
274 i += 1;
275 setBalance((b) => Math.round((b + t.amount) * 100) / 100);
276 setTxns((list) => [{ ...t, id: i }, ...list].slice(0, 3));
277 }, 2800);
278 return () => {
279 window.clearInterval(id);
280 io?.disconnect();
281 };
282 }, []);
283
284 // Pointer tilt — spring integrator (k 380, c 30, m 1).
285 useEffect(() => {
286 const card = cardRef.current;
287 if (!card || prefersReducedMotion()) return;
288 const zone = card.closest<HTMLElement>(".fd-vlt-hero") ?? card;
289 const s = { x: 0, y: 0, vx: 0, vy: 0, tx: 0, ty: 0, gx: 50, gy: 30 };
290 let raf = 0;
291 let last = 0;
292 const step = (now: number) => {
293 const dt = Math.min(0.032, (now - (last || now)) / 1000 || 0.016);
294 last = now;
295 const k = 380;
296 const c = 30;
297 s.vx += (k * (s.tx - s.x) - c * s.vx) * dt;
298 s.vy += (k * (s.ty - s.y) - c * s.vy) * dt;
299 s.x += s.vx * dt;
300 s.y += s.vy * dt;
301 card.style.setProperty("--rx", `${s.y.toFixed(3)}deg`);
302 card.style.setProperty("--ry", `${s.x.toFixed(3)}deg`);
303 card.style.setProperty("--gx", `${s.gx}%`);
304 card.style.setProperty("--gy", `${s.gy}%`);
305 const settled =
306 Math.abs(s.tx - s.x) < 0.01 && Math.abs(s.ty - s.y) < 0.01 && Math.abs(s.vx) < 0.01 && Math.abs(s.vy) < 0.01;
307 raf = settled ? 0 : requestAnimationFrame(step);
308 };
309 const kick = () => {
310 if (!raf) {
311 last = 0;
312 raf = requestAnimationFrame(step);
313 }
314 };
315 const move = (e: PointerEvent) => {
316 if (e.pointerType === "touch") return;
317 const r = card.getBoundingClientRect();
318 const px = (e.clientX - (r.left + r.width / 2)) / (r.width / 2);
319 const py = (e.clientY - (r.top + r.height / 2)) / (r.height / 2);
320 s.tx = Math.max(-1, Math.min(1, px)) * 9;
321 s.ty = Math.max(-1, Math.min(1, py)) * -7;
322 s.gx = Math.round(clamp01((e.clientX - r.left) / r.width) * 100);
323 s.gy = Math.round(clamp01((e.clientY - r.top) / r.height) * 100);
324 kick();
325 };
326 const leave = () => {
327 s.tx = 0;
328 s.ty = 0;
329 s.gx = 50;
330 s.gy = 30;
331 kick();
332 };
333 zone.addEventListener("pointermove", move);
334 zone.addEventListener("pointerleave", leave);
335 return () => {
336 zone.removeEventListener("pointermove", move);
337 zone.removeEventListener("pointerleave", leave);
338 if (raf) cancelAnimationFrame(raf);
339 };
340 }, []);
341
342 return (
343 <div className="fd-vlt-card-wrap">
344 <span className="fd-vlt-fig" aria-hidden="true">
345 Fig. 01 — Operating account, live
346 </span>
347 <div ref={cardRef} className="fd-vlt-card" aria-label="Example operating account">
348 <div className="fd-vlt-card-glare" aria-hidden="true" />
349 <div className="fd-vlt-card-top">
350 <span className="fd-vlt-mono">Operating · USD</span>
351 <span className="fd-vlt-live">
352 <i aria-hidden="true" /> Live
353 </span>
354 </div>
355 <div className="fd-vlt-card-bal" aria-live="polite">
356 <span className="fd-vlt-card-cur">$</span>
357 <Odometer value={usd(balance)} />
358 </div>
359 <div className="fd-vlt-card-meta">
360 <span>Acct ••••4417</span>
361 <span>Routing 026 073 150</span>
362 </div>
363 <svg className="fd-vlt-spark" viewBox="0 0 320 64" preserveAspectRatio="none" aria-hidden="true">
364 <path
365 d="M0 52 L20 50 L40 46 L60 48 L80 40 L100 42 L120 36 L140 38 L160 30 L180 33 L200 26 L220 28 L240 20 L260 22 L280 14 L300 16 L320 8"
366 fill="none"
367 stroke="currentColor"
368 strokeWidth="1.5"
369 />
370 <path
371 d="M0 52 L20 50 L40 46 L60 48 L80 40 L100 42 L120 36 L140 38 L160 30 L180 33 L200 26 L220 28 L240 20 L260 22 L280 14 L300 16 L320 8 L320 64 L0 64Z"
372 fill="currentColor"
373 opacity="0.06"
374 />
375 </svg>
376 <ul className="fd-vlt-txns">
377 {txns.map((t) => (
378 <li key={t.id} className="fd-vlt-txn">
379 <span className="fd-vlt-txn-dot" data-in={t.amount > 0 || undefined} aria-hidden="true" />
380 <span className="fd-vlt-txn-who">
381 <b>{t.who}</b>
382 <small>{t.memo}</small>
383 </span>
384 <span className="fd-vlt-txn-amt">
385 {t.amount > 0 ? "+" : "−"}${usd(Math.abs(t.amount))}
386 </span>
387 </li>
388 ))}
389 </ul>
390 </div>
391 <span className="fd-vlt-dim fd-vlt-dim-x" aria-hidden="true">
392 <i />
393 440
394 <i />
395 </span>
396 </div>
397 );
398}
399
400function Hero() {
401 return (
402 <section className="fd-vlt-hero fd-vlt-grid-bg" id="top">
403 <div className="fd-vlt-wrap fd-vlt-hero-in">
404 <div className="fd-vlt-hero-copy">
405 <p className="fd-vlt-eyebrow fd-vlt-rise" style={{ "--d": "0ms" } as CSSProperties}>
406 <span className="fd-vlt-tag">New</span> Treasury sweeps into T-bills, daily
407 </p>
408 <h1 className="fd-vlt-h1">
409 <span className="fd-vlt-mask">
410 <span style={{ "--d": "80ms" } as CSSProperties}>Money that</span>
411 </span>
412 <span className="fd-vlt-mask">
413 <span style={{ "--d": "170ms" } as CSSProperties}>holds its</span>
414 </span>
415 <span className="fd-vlt-mask">
416 <span style={{ "--d": "260ms" } as CSSProperties}>
417 line<span className="fd-vlt-dot">.</span>
418 </span>
419 </span>
420 </h1>
421 <p className="fd-vlt-lede fd-vlt-rise" style={{ "--d": "420ms" } as CSSProperties}>
422 Operating accounts, corporate cards, global payments and treasury — one ledger, eleven currencies,
423 zero spreadsheets. Built for companies from seed to IPO.
424 </p>
425 <div className="fd-vlt-ctas fd-vlt-rise" style={{ "--d": "520ms" } as CSSProperties}>
426 <a className="fd-vlt-btn" href="#pricing">
427 Open an account <Arrow />
428 </a>
429 <a className="fd-vlt-btn fd-vlt-btn-ghost" href="#platform">
430 See the platform
431 </a>
432 </div>
433 <p className="fd-vlt-fine fd-vlt-rise" style={{ "--d": "600ms" } as CSSProperties}>
434 Approved in 1 business day · FDIC pass-through to $125M per entity
435 </p>
436 </div>
437 <div className="fd-vlt-hero-card fd-vlt-rise" style={{ "--d": "300ms" } as CSSProperties}>
438 <BalanceCard />
439 </div>
440 </div>
441 <div className="fd-vlt-wrap">
442 <dl className="fd-vlt-ticker">
443 {[
444 ["$38.2B", "settled, trailing 12 months"],
445 ["41,000+", "companies banking"],
446 ["99.998%", "platform uptime"],
447 ["11", "settlement currencies"],
448 ].map(([k, v], i) => (
449 <div key={k} className="fd-vlt-rise" style={{ "--d": `${680 + i * 70}ms` } as CSSProperties}>
450 <dt>{k}</dt>
451 <dd>{v}</dd>
452 </div>
453 ))}
454 </dl>
455 </div>
456 <span className="fd-vlt-reg fd-vlt-reg-tl" aria-hidden="true" />
457 <span className="fd-vlt-reg fd-vlt-reg-tr" aria-hidden="true" />
458 <span className="fd-vlt-spec" aria-hidden="true">
459 GRID 12 · COL 80 · GUTTER 24 · BASE 8
460 </span>
461 </section>
462 );
463}
464
465/* ─────────────────────────── logos ─────────────────────────── */
466
467const LOGOS = [
468 { name: "Northwind", style: "fd-vlt-wm-1" },
469 { name: "HALCYON", style: "fd-vlt-wm-2" },
470 { name: "lumen bio", style: "fd-vlt-wm-3" },
471 { name: "Kestrel", style: "fd-vlt-wm-4" },
472 { name: "PARCEL&CO", style: "fd-vlt-wm-5" },
473 { name: "Atlas Robotics", style: "fd-vlt-wm-6" },
474 { name: "ouro", style: "fd-vlt-wm-7" },
475];
476
477function Logos() {
478 return (
479 <section className="fd-vlt-logos" aria-label="Customers">
480 <div className="fd-vlt-wrap">
481 <p className="fd-vlt-label" data-reveal="">
482 Finance teams that moved their operating cash to Vault
483 </p>
484 <ul className="fd-vlt-logo-row">
485 {LOGOS.map((l, i) => (
486 <li key={l.name} className={l.style} data-reveal="" style={{ "--i": i } as CSSProperties}>
487 {l.name}
488 </li>
489 ))}
490 </ul>
491 </div>
492 </section>
493 );
494}
495
496/* ─────────────────────────── platform (sticky assembly) ─────────────────────────── */
497
498const STEPS = [
499 {
500 k: "01",
501 t: "Every balance, one number.",
502 d: "Operating, payroll, tax and reserve accounts roll up across 11 currencies — converted at the mid-market rate, refreshed on every settlement.",
503 },
504 {
505 k: "02",
506 t: "Cash flow you can read.",
507 d: "Inflows and outflows by week, with runway projected from the last 90 days of actuals — not last quarter’s board deck.",
508 },
509 {
510 k: "03",
511 t: "Cards with a conscience.",
512 d: "Issue virtual cards in seconds. Lock each one to a vendor, a category or a monthly ceiling, and freeze it from Slack.",
513 },
514 {
515 k: "04",
516 t: "Payments that wait for two.",
517 d: "Every wire over $50,000 routes for dual approval with a hardware key. Everything else clears same-day on ACH, RTP or SWIFT.",
518 },
519];
520
521/** [start, end] of each dashboard piece within the scene progress. */
522const PIECES: Record<string, [number, number]> = {
523 side: [0.02, 0.16],
524 bal: [0.06, 0.22],
525 flow: [0.26, 0.44],
526 card: [0.5, 0.66],
527 txns: [0.72, 0.86],
528 appr: [0.78, 0.92],
529};
530
531function Platform() {
532 const outer = useRef<HTMLElement>(null);
533 const readout = useRef<HTMLSpanElement>(null);
534 const reduced = useRef(false);
535 useEffect(() => {
536 reduced.current = prefersReducedMotion();
537 }, []);
538 useScrollFrame(outer, () => {
539 const el = outer.current;
540 if (!el) return;
541 const p = reduced.current ? 1 : pinnedProgress(el);
542 el.querySelectorAll<HTMLElement>("[data-piece]").forEach((n) => {
543 const [a, b] = PIECES[n.dataset.piece ?? ""] ?? [0, 1];
544 n.style.setProperty("--t", easeOut(clamp01((p - a) / (b - a))).toFixed(3));
545 });
546 const idx = p < 0.24 ? 0 : p < 0.48 ? 1 : p < 0.7 ? 2 : 3;
547 el.querySelectorAll<HTMLElement>("[data-step]").forEach((n, i) => {
548 if (i === idx) n.setAttribute("data-active", "");
549 else n.removeAttribute("data-active");
550 });
551 el.style.setProperty("--p", p.toFixed(3));
552 if (readout.current) readout.current.textContent = `${String(Math.round(p * 100)).padStart(3, "0")}%`;
553 });
554
555 return (
556 <section ref={outer} className="fd-vlt-plat" id="platform">
557 <div className="fd-vlt-plat-stick">
558 <div className="fd-vlt-wrap fd-vlt-plat-grid">
559 <div className="fd-vlt-plat-copy">
560 <p className="fd-vlt-label">02 — Platform</p>
561 <h2 className="fd-vlt-h2">
562 One screen for
563 <br />
564 every dollar.
565 </h2>
566 <ol className="fd-vlt-steps">
567 {STEPS.map((s, i) => (
568 <li key={s.k} data-step="" data-active={i === 0 || undefined}>
569 <span className="fd-vlt-step-k">{s.k}</span>
570 <div>
571 <h3>{s.t}</h3>
572 <p>{s.d}</p>
573 </div>
574 </li>
575 ))}
576 </ol>
577 <div className="fd-vlt-plat-bar" aria-hidden="true">
578 <i />
579 <span ref={readout}>000%</span>
580 </div>
581 </div>
582
583 <div className="fd-vlt-dash-wrap" aria-label="Vault dashboard preview" role="img">
584 <div className="fd-vlt-dash">
585 <div className="fd-vlt-dash-chrome">
586 <span />
587 <span />
588 <span />
589 <em>app.vault.co/overview</em>
590 </div>
591 <div className="fd-vlt-dash-body">
592 {(["side", "bal", "flow", "card", "txns", "appr"] as const).map((k, i) => (
593 <div key={k} className={`fd-vlt-slot fd-vlt-slot-${k}`} aria-hidden="true">
594 <span>{String.fromCharCode(65 + i)}</span>
595 </div>
596 ))}
597
598 <div className="fd-vlt-piece fd-vlt-slot-side" data-piece="side" style={{ "--dx": "-80px", "--dy": "0px" } as CSSProperties}>
599 <div className="fd-vlt-side">
600 <b>
601 <Logo /> Kestrel Aerospace
602 </b>
603 {["Overview", "Accounts", "Cards", "Payments", "Treasury", "Ledger"].map((n, i) => (
604 <span key={n} data-on={i === 0 || undefined}>
605 {n}
606 </span>
607 ))}
608 </div>
609 </div>
610
611 <div className="fd-vlt-piece fd-vlt-slot-bal" data-piece="bal" style={{ "--dx": "0px", "--dy": "-60px" } as CSSProperties}>
612 <div className="fd-vlt-tile">
613 <small>Total cash · 11 currencies</small>
614 <strong>$12,904,118.40</strong>
615 <span className="fd-vlt-delta">▲ 2.4% vs. 30 days</span>
616 <div className="fd-vlt-split">
617 <i style={{ width: "54%" }} />
618 <i style={{ width: "21%" }} />
619 <i style={{ width: "15%" }} />
620 <i style={{ width: "10%" }} />
621 </div>
622 <div className="fd-vlt-legend">
623 <span>Operating 54%</span>
624 <span>Treasury 21%</span>
625 <span>Payroll 15%</span>
626 <span>Reserve 10%</span>
627 </div>
628 </div>
629 </div>
630
631 <div className="fd-vlt-piece fd-vlt-slot-flow" data-piece="flow" style={{ "--dx": "90px", "--dy": "40px" } as CSSProperties}>
632 <div className="fd-vlt-tile">
633 <small>Cash flow · last 12 weeks</small>
634 <div className="fd-vlt-bars">
635 {[62, 48, 71, 55, 80, 66, 74, 58, 88, 70, 92, 84].map((h, i) => (
636 <span key={i}>
637 <i style={{ height: `${h}%` }} />
638 <i style={{ height: `${Math.round(h * 0.62)}%` }} />
639 </span>
640 ))}
641 </div>
642 <span className="fd-vlt-runway">Runway 31 mo · at current burn</span>
643 </div>
644 </div>
645
646 <div className="fd-vlt-piece fd-vlt-slot-card" data-piece="card" style={{ "--dx": "120px", "--dy": "-30px" } as CSSProperties}>
647 <div className="fd-vlt-mini-card">
648 <div>
649 <Logo />
650 <span>Virtual</span>
651 </div>
652 <span className="fd-vlt-mini-pan">•••• •••• •••• 3391</span>
653 <div className="fd-vlt-mini-foot">
654 <span>Cloud infra</span>
655 <span>$18,240 / $25,000</span>
656 </div>
657 <i className="fd-vlt-mini-meter" style={{ "--m": "0.73" } as CSSProperties} />
658 </div>
659 </div>
660
661 <div className="fd-vlt-piece fd-vlt-slot-txns" data-piece="txns" style={{ "--dx": "0px", "--dy": "80px" } as CSSProperties}>
662 <div className="fd-vlt-tile fd-vlt-table">
663 <small>Recent activity</small>
664 {[
665 ["Oct 29", "Halcyon Health", "Wire in", "+$62,250.00"],
666 ["Oct 29", "AWS", "Card ••3391", "−$2,316.48"],
667 ["Oct 28", "Gusto Payroll", "ACH out", "−$41,880.12"],
668 ["Oct 28", "Northwind Freight", "RTP in", "+$18,400.00"],
669 ].map((r) => (
670 <div key={r[1]} className="fd-vlt-row">
671 <span>{r[0]}</span>
672 <span>{r[1]}</span>
673 <span>{r[2]}</span>
674 <span>{r[3]}</span>
675 </div>
676 ))}
677 </div>
678 </div>
679
680 <div className="fd-vlt-piece fd-vlt-slot-appr" data-piece="appr" style={{ "--dx": "60px", "--dy": "70px" } as CSSProperties}>
681 <div className="fd-vlt-tile fd-vlt-appr">
682 <small>Awaiting approval</small>
683 <strong>2 wires</strong>
684 <span>$184,000 · SWIFT · EUR</span>
685 <div className="fd-vlt-appr-btns">
686 <span>Review</span>
687 <span>Approve with key</span>
688 </div>
689 </div>
690 </div>
691 </div>
692 </div>
693 <span className="fd-vlt-fig fd-vlt-fig-b" aria-hidden="true">
694 Fig. 02 — Overview, assembled from six modules
695 </span>
696 </div>
697 </div>
698 </div>
699 </section>
700 );
701}
702
703/* ─────────────────────────── capability rail (pinned horizontal) ─────────────────────────── */
704
705const CAPS: { k: string; t: string; d: string; specs: [string, string][]; art: ReactNode }[] = [
706 {
707 k: "01",
708 t: "Accounts",
709 d: "Unlimited operating and sub-accounts per entity, each with its own routing details and statements.",
710 specs: [
711 ["Currencies", "11"],
712 ["Sub-accounts", "Unlimited"],
713 ["Opening time", "1 business day"],
714 ],
715 art: (
716 <svg viewBox="0 0 200 120" aria-hidden="true">
717 {[0, 1, 2, 3].map((i) => (
718 <g key={i} transform={`translate(${20 + i * 8} ${16 + i * 22})`}>
719 <rect width="150" height="16" fill="none" stroke="currentColor" />
720 <rect x="6" y="5" width={40 + i * 14} height="6" fill="currentColor" opacity={0.85 - i * 0.18} />
721 </g>
722 ))}
723 </svg>
724 ),
725 },
726 {
727 k: "02",
728 t: "Corporate cards",
729 d: "Physical and virtual cards with limits per merchant, category, team or geography — enforced at authorization.",
730 specs: [
731 ["Issue time", "< 4 seconds"],
732 ["Cashback", "1.75% flat"],
733 ["Networks", "Visa Signature"],
734 ],
735 art: (
736 <svg viewBox="0 0 200 120" aria-hidden="true">
737 <rect x="40" y="14" width="130" height="84" rx="8" fill="none" stroke="currentColor" />
738 <rect x="28" y="24" width="130" height="84" rx="8" fill="currentColor" opacity="0.92" />
739 <rect x="42" y="46" width="22" height="16" rx="3" fill="none" stroke="#fff" opacity="0.8" />
740 <path d="M42 90h60" stroke="#fff" opacity="0.7" />
741 </svg>
742 ),
743 },
744 {
745 k: "03",
746 t: "Global payments",
747 d: "ACH, RTP, FedNow, SEPA, Faster Payments and SWIFT from one form. FX at mid-market plus 0.25%.",
748 specs: [
749 ["Rails", "6"],
750 ["Same-day wires", "94%"],
751 ["FX spread", "0.25%"],
752 ],
753 art: (
754 <svg viewBox="0 0 200 120" aria-hidden="true">
755 <circle cx="100" cy="60" r="44" fill="none" stroke="currentColor" />
756 <ellipse cx="100" cy="60" rx="18" ry="44" fill="none" stroke="currentColor" opacity="0.5" />
757 <path d="M56 60h88M62 38h76M62 82h76" stroke="currentColor" opacity="0.5" />
758 <path d="M30 96 Q100 0 172 30" fill="none" stroke="currentColor" strokeDasharray="3 4" />
759 <circle cx="30" cy="96" r="4" fill="currentColor" />
760 <circle cx="172" cy="30" r="4" fill="currentColor" />
761 </svg>
762 ),
763 },
764 {
765 k: "04",
766 t: "Treasury",
767 d: "Sweep idle cash into US T-bills and government money-market funds daily, with same-day liquidity back to operating.",
768 specs: [
769 ["Yield, 7-day", "4.12%"],
770 ["Liquidity", "Same day"],
771 ["Minimum", "$0"],
772 ],
773 art: (
774 <svg viewBox="0 0 200 120" aria-hidden="true">
775 <path d="M20 100H184M20 100V14" stroke="currentColor" opacity="0.4" />
776 <path d="M20 92 C60 88 70 50 104 44 S160 30 184 22" fill="none" stroke="currentColor" strokeWidth="1.5" />
777 {[40, 72, 104, 136, 168].map((x) => (
778 <path key={x} d={`M${x} 100v-4`} stroke="currentColor" />
779 ))}
780 <circle cx="104" cy="44" r="4" fill="currentColor" />
781 </svg>
782 ),
783 },
784 {
785 k: "05",
786 t: "Spend controls",
787 d: "Policies written once, enforced everywhere: approval chains by amount, receipts required over $75, auto-freeze on anomalies.",
788 specs: [
789 ["Policy rules", "Unlimited"],
790 ["Receipt match", "Auto · 96%"],
791 ["Freeze", "From Slack"],
792 ],
793 art: (
794 <svg viewBox="0 0 200 120" aria-hidden="true">
795 {[28, 60, 92].map((y, i) => (
796 <g key={y}>
797 <path d={`M24 ${y}H176`} stroke="currentColor" opacity="0.35" />
798 <path d={`M24 ${y}H${70 + i * 34}`} stroke="currentColor" strokeWidth="2" />
799 <circle cx={70 + i * 34} cy={y} r="7" fill="#fff" stroke="currentColor" strokeWidth="1.5" />
800 </g>
801 ))}
802 </svg>
803 ),
804 },
805 {
806 k: "06",
807 t: "Ledger & sync",
808 d: "A double-entry ledger your auditor can read. Pushes coded transactions to NetSuite, Xero or QuickBooks every hour.",
809 specs: [
810 ["Sync", "Hourly"],
811 ["Close time", "−62%"],
812 ["Exports", "CSV · API · SFTP"],
813 ],
814 art: (
815 <svg viewBox="0 0 200 120" aria-hidden="true">
816 <path d="M30 24H170M100 24V104" stroke="currentColor" strokeWidth="1.5" />
817 <text x="62" y="18" textAnchor="middle" fontSize="9" fill="currentColor" fontFamily="ui-monospace, Menlo, monospace">DEBIT</text>
818 <text x="138" y="18" textAnchor="middle" fontSize="9" fill="currentColor" fontFamily="ui-monospace, Menlo, monospace">CREDIT</text>
819 {[40, 58, 76].map((y, i) => (
820 <g key={y}>
821 <rect x="40" y={y} width={44 - i * 8} height="6" fill="currentColor" opacity="0.8" />
822 <rect x="112" y={y} width={30 + i * 6} height="6" fill="currentColor" opacity="0.8" />
823 </g>
824 ))}
825 <path d="M40 94H90M112 94H162" stroke="currentColor" strokeDasharray="2 3" />
826 </svg>
827 ),
828 },
829];
830
831function Capabilities() {
832 const outer = useRef<HTMLElement>(null);
833 const track = useRef<HTMLDivElement>(null);
834 const count = useRef<HTMLSpanElement>(null);
835 const dist = useRef(0);
836 const reduced = useRef(false);
837
838 useEffect(() => {
839 reduced.current = prefersReducedMotion();
840 const o = outer.current;
841 const t = track.current;
842 if (!o || !t) return;
843 const measure = () => {
844 if (reduced.current) {
845 o.style.height = "";
846 return;
847 }
848 dist.current = Math.max(0, t.scrollWidth - t.clientWidth);
849 o.style.height = `${dist.current + window.innerHeight}px`;
850 };
851 measure();
852 const ro = new ResizeObserver(measure);
853 ro.observe(t);
854 window.addEventListener("resize", measure);
855 return () => {
856 ro.disconnect();
857 window.removeEventListener("resize", measure);
858 };
859 }, []);
860
861 useScrollFrame(outer, () => {
862 const o = outer.current;
863 const t = track.current;
864 if (!o || !t || reduced.current) return;
865 const r = o.getBoundingClientRect();
866 const p = dist.current > 0 ? clamp01(-r.top / dist.current) : 0;
867 t.style.setProperty("--x", `${(-p * dist.current).toFixed(1)}px`);
868 o.style.setProperty("--p", p.toFixed(4));
869 if (count.current) count.current.textContent = String(Math.min(CAPS.length, 1 + Math.floor(p * CAPS.length * 0.999))).padStart(2, "0");
870 });
871
872 return (
873 <section ref={outer} className="fd-vlt-caps" id="capabilities" aria-label="Capabilities">
874 <div className="fd-vlt-caps-stick">
875 <div className="fd-vlt-wrap fd-vlt-caps-head">
876 <div>
877 <p className="fd-vlt-label fd-vlt-on-dark">03 — Capabilities</p>
878 <h2 className="fd-vlt-h2">Six instruments. One ledger.</h2>
879 </div>
880 <p className="fd-vlt-caps-count" aria-hidden="true">
881 <span ref={count}>01</span> / {String(CAPS.length).padStart(2, "0")}
882 </p>
883 </div>
884 <div ref={track} className="fd-vlt-caps-track" tabIndex={0} aria-label="Capabilities, scroll horizontally">
885 {CAPS.map((c) => (
886 <article key={c.k} className="fd-vlt-cap">
887 <div className="fd-vlt-cap-top">
888 <span className="fd-vlt-mono">{c.k}</span>
889 <span className="fd-vlt-mono">Vault / {c.t}</span>
890 </div>
891 <div className="fd-vlt-cap-art">{c.art}</div>
892 <h3>{c.t}</h3>
893 <p>{c.d}</p>
894 <dl>
895 {c.specs.map(([a, b]) => (
896 <div key={a}>
897 <dt>{a}</dt>
898 <dd>{b}</dd>
899 </div>
900 ))}
901 </dl>
902 </article>
903 ))}
904 <div className="fd-vlt-cap-end" aria-hidden="true" />
905 </div>
906 <div className="fd-vlt-wrap">
907 <div className="fd-vlt-caps-progress" aria-hidden="true">
908 <i />
909 </div>
910 </div>
911 </div>
912 </section>
913 );
914}
915
916/* ─────────────────────────── stats (count-up) ─────────────────────────── */
917
918const STATS = [
919 { to: 38.2, dec: 1, pre: "$", suf: "B", label: "Settled through Vault in the last twelve months." },
920 { to: 41000, dec: 0, pre: "", suf: "+", label: "Companies run payroll, payables and cards on Vault." },
921 { to: 99.998, dec: 3, pre: "", suf: "%", label: "Platform uptime across all payment rails, trailing year." },
922 { to: 19, dec: 0, pre: "", suf: " hrs", label: "Median time from term-sheet wire to cash in T-bills." },
923];
924
925function CountUp({ to, dec, pre, suf }: { to: number; dec: number; pre: string; suf: string }) {
926 const ref = useRef<HTMLSpanElement>(null);
927 const fmt = (n: number) =>
928 pre + n.toLocaleString("en-US", { minimumFractionDigits: dec, maximumFractionDigits: dec }) + suf;
929 useEffect(() => {
930 const el = ref.current;
931 if (!el) return;
932 if (prefersReducedMotion() || typeof IntersectionObserver === "undefined") {
933 el.textContent = fmt(to);
934 return;
935 }
936 el.textContent = fmt(0);
937 let raf = 0;
938 const io = new IntersectionObserver(
939 ([e]) => {
940 if (!e.isIntersecting) return;
941 io.disconnect();
942 const start = performance.now();
943 const dur = 1600;
944 const tick = (now: number) => {
945 const t = clamp01((now - start) / dur);
946 const v = to * (1 - Math.pow(2, -10 * t));
947 el.textContent = fmt(t >= 1 ? to : v);
948 if (t < 1) raf = requestAnimationFrame(tick);
949 };
950 raf = requestAnimationFrame(tick);
951 },
952 { threshold: 0.6 },
953 );
954 io.observe(el);
955 return () => {
956 io.disconnect();
957 cancelAnimationFrame(raf);
958 };
959 // eslint-disable-next-line react-hooks/exhaustive-deps
960 }, [to]);
961 return (
962 <span ref={ref} className="fd-vlt-count">
963 {fmt(to)}
964 </span>
965 );
966}
967
968function Stats() {
969 return (
970 <section className="fd-vlt-stats" aria-label="Vault in numbers">
971 <div className="fd-vlt-wrap">
972 <div className="fd-vlt-stats-head" data-reveal="">
973 <p className="fd-vlt-label">04 — In numbers</p>
974 <h2 className="fd-vlt-h2">Measured, not marketed.</h2>
975 </div>
976 <div className="fd-vlt-stats-grid">
977 {STATS.map((s, i) => (
978 <div key={s.label} className="fd-vlt-stat" data-reveal="" style={{ "--i": i } as CSSProperties}>
979 <span className="fd-vlt-mono">({String.fromCharCode(97 + i)})</span>
980 <CountUp {...s} />
981 <p>{s.label}</p>
982 </div>
983 ))}
984 </div>
985 <p className="fd-vlt-footnote" data-reveal="">
986 Figures as of September 30, 2026. Treasury yield is variable and shown net of fees.
987 </p>
988 </div>
989 </section>
990 );
991}
992
993/* ─────────────────────────── security + marquee ─────────────────────────── */
994
995const BADGES = [
996 "SOC 1 Type II",
997 "SOC 2 Type II",
998 "PCI DSS Level 1",
999 "ISO/IEC 27001",
1000 "ISO/IEC 27701",
1001 "GDPR",
1002 "CCPA",
1003 "FDIC pass-through",
1004 "AES-256 at rest",
1005 "TLS 1.3",
1006 "FIDO2 keys",
1007 "Annual pen-test",
1008];
1009
1010function Security() {
1011 return (
1012 <section className="fd-vlt-sec" id="security">
1013 <div className="fd-vlt-wrap fd-vlt-sec-grid">
1014 <div data-reveal="">
1015 <p className="fd-vlt-label">05 — Security</p>
1016 <h2 className="fd-vlt-h2">
1017 Paranoid by
1018 <br />
1019 default.
1020 </h2>
1021 </div>
1022 <div className="fd-vlt-sec-cols">
1023 {[
1024 ["Dual control", "Wires above a threshold you set require two approvers and a FIDO2 hardware key. No exceptions for admins."],
1025 ["Partner banks", "Deposits are held at Harbor State Bank and Meridian Trust, Members FDIC, and swept across 14 program banks."],
1026 ["Audit trail", "Every login, permission change and payment is signed, timestamped and retained for seven years."],
1027 ].map(([t, d], i) => (
1028 <div key={t} className="fd-vlt-sec-col" data-reveal="" style={{ "--i": i } as CSSProperties}>
1029 <span className="fd-vlt-mono">0{i + 1}</span>
1030 <h3>{t}</h3>
1031 <p>{d}</p>
1032 </div>
1033 ))}
1034 </div>
1035 </div>
1036 <div className="fd-vlt-marquee" aria-label="Certifications and controls">
1037 {[0, 1].map((row) => (
1038 <div key={row} className="fd-vlt-marquee-row" data-dir={row === 1 ? "rev" : undefined}>
1039 <ul className="fd-vlt-marquee-track">
1040 {[...BADGES, ...BADGES].map((b, i) => (
1041 <li key={i} aria-hidden={i >= BADGES.length || row === 1 || undefined}>
1042 <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
1043 <path d="M8 1.5l5.5 2v4c0 3.3-2.3 6-5.5 7-3.2-1-5.5-3.7-5.5-7v-4z" fill="none" stroke="currentColor" />
1044 </svg>
1045 {row === 1 ? BADGES[(i + 5) % BADGES.length] : b}
1046 </li>
1047 ))}
1048 </ul>
1049 </div>
1050 ))}
1051 </div>
1052 </section>
1053 );
1054}
1055
1056/* ─────────────────────────── testimonial ─────────────────────────── */
1057
1058function Testimonial() {
1059 return (
1060 <section className="fd-vlt-quote" aria-label="Customer story">
1061 <div className="fd-vlt-wrap fd-vlt-quote-grid">
1062 <p className="fd-vlt-label" data-reveal="">
1063 06 — Customer
1064 </p>
1065 <figure data-reveal="">
1066 <blockquote>
1067 “We closed our Series B on a Tuesday. By Wednesday morning the wire had cleared, payroll was funded
1068 for 24 months and the rest was earning in T-bills. Nobody opened a spreadsheet.”
1069 </blockquote>
1070 <figcaption>
1071 <img className="fd-vlt-avatar" src="/img/people/p3.webp" alt="Maren Okafor, CFO of Kestrel Aerospace, a woman with braided hair in a black sweater" width={44} height={44} loading="lazy" decoding="async" />
1072 <span>
1073 <b>Maren Okafor</b>
1074 <small>CFO, Kestrel Aerospace · 212 employees</small>
1075 </span>
1076 </figcaption>
1077 </figure>
1078 <dl className="fd-vlt-quote-stats">
1079 {[
1080 ["19 hrs", "wire to treasury"],
1081 ["100%", "card spend auto-coded"],
1082 ["62 hrs", "saved every month-end"],
1083 ].map(([k, v], i) => (
1084 <div key={k} data-reveal="" style={{ "--i": i } as CSSProperties}>
1085 <dt>{k}</dt>
1086 <dd>{v}</dd>
1087 </div>
1088 ))}
1089 </dl>
1090 </div>
1091 </section>
1092 );
1093}
1094
1095/* ─────────────────────────── pricing ─────────────────────────── */
1096
1097const PLANS = [
1098 {
1099 name: "Launch",
1100 who: "For pre-seed and bootstrapped teams.",
1101 m: 0,
1102 y: 0,
1103 cta: "Open account",
1104 feats: ["1 operating account", "5 corporate cards", "ACH, RTP and domestic wires", "FDIC pass-through to $5M"],
1105 },
1106 {
1107 name: "Scale",
1108 who: "For Series A through C.",
1109 m: 299,
1110 y: 239,
1111 cta: "Start 30-day trial",
1112 featured: true,
1113 feats: [
1114 "Unlimited accounts and sub-ledgers",
1115 "Unlimited cards with policy engine",
1116 "SWIFT, SEPA, FedNow, Faster Payments",
1117 "Daily treasury sweeps to T-bills",
1118 "NetSuite, Xero and QuickBooks sync",
1119 ],
1120 },
1121 {
1122 name: "Enterprise",
1123 who: "For public companies and regulated entities.",
1124 m: 1800,
1125 y: 1440,
1126 cta: "Talk to sales",
1127 feats: ["Dedicated banking partner", "Custom approval chains and SSO/SCIM", "Quarterly compliance review", "99.99% uptime SLA"],
1128 },
1129];
1130
1131function Pricing() {
1132 const [annual, setAnnual] = useState(true);
1133 const groupId = useId();
1134 return (
1135 <section className="fd-vlt-pricing" id="pricing">
1136 <div className="fd-vlt-wrap">
1137 <div className="fd-vlt-pricing-head" data-reveal="">
1138 <div>
1139 <p className="fd-vlt-label">07 — Pricing</p>
1140 <h2 className="fd-vlt-h2">Priced like a utility.</h2>
1141 </div>
1142 <div className="fd-vlt-seg" role="radiogroup" aria-labelledby={groupId} data-annual={annual || undefined}>
1143 <span id={groupId} className="fd-vlt-sr">
1144 Billing period
1145 </span>
1146 <i className="fd-vlt-seg-thumb" aria-hidden="true" />
1147 <button type="button" role="radio" aria-checked={!annual} onClick={() => setAnnual(false)}>
1148 Monthly
1149 </button>
1150 <button type="button" role="radio" aria-checked={annual} onClick={() => setAnnual(true)}>
1151 Annual <span className="fd-vlt-save">−20%</span>
1152 </button>
1153 </div>
1154 </div>
1155 <div className="fd-vlt-plans">
1156 {PLANS.map((p, i) => (
1157 <article
1158 key={p.name}
1159 className="fd-vlt-plan"
1160 data-featured={p.featured || undefined}
1161 data-reveal=""
1162 style={{ "--i": i } as CSSProperties}
1163 >
1164 <div className="fd-vlt-plan-top">
1165 <h3>{p.name}</h3>
1166 {p.featured && <span className="fd-vlt-tag fd-vlt-tag-inv">Most chosen</span>}
1167 </div>
1168 <p className="fd-vlt-plan-who">{p.who}</p>
1169 <div className="fd-vlt-price">
1170 <span className="fd-vlt-price-cur">$</span>
1171 <Odometer value={(annual ? p.y : p.m).toLocaleString("en-US")} />
1172 <span className="fd-vlt-price-per">/ mo</span>
1173 </div>
1174 <p className="fd-vlt-plan-bill">{p.m === 0 ? "Free forever" : annual ? "Billed annually" : "Billed monthly"}</p>
1175 <a className={`fd-vlt-btn ${p.featured ? "fd-vlt-btn-inv" : "fd-vlt-btn-ghost"}`} href="#top">
1176 {p.cta} <Arrow />
1177 </a>
1178 <ul>
1179 {p.feats.map((f) => (
1180 <li key={f}>
1181 <Check />
1182 {f}
1183 </li>
1184 ))}
1185 </ul>
1186 </article>
1187 ))}
1188 </div>
1189 </div>
1190 </section>
1191 );
1192}
1193
1194/* ─────────────────────────── FAQ ─────────────────────────── */
1195
1196const FAQS = [
1197 {
1198 q: "Is Vault a bank?",
1199 a: "No. Vault is a financial technology company. Banking services are provided by Harbor State Bank and Meridian Trust, Members FDIC. Deposits are eligible for FDIC pass-through insurance up to $125M per entity through our program-bank network.",
1200 },
1201 {
1202 q: "How long does it take to open an account?",
1203 a: "Most companies are approved within one business day. You’ll need your EIN, formation documents and ID for each beneficial owner with 25% or more. Account and routing numbers are issued the moment you’re approved.",
1204 },
1205 {
1206 q: "Can I keep my existing bank?",
1207 a: "Yes. Many customers start by moving payables and cards, then migrate payroll once their first close on Vault is done. You can link external accounts for transfers and view their balances alongside Vault.",
1208 },
1209 {
1210 q: "How does treasury work?",
1211 a: "Set a target operating balance. Each night, cash above it sweeps into a portfolio of US Treasury bills and government money-market funds. Need it back? Redemptions settle to operating the same business day.",
1212 },
1213 {
1214 q: "Which accounting tools do you sync with?",
1215 a: "NetSuite, Xero, QuickBooks Online and Sage Intacct, with hourly sync of coded transactions, receipts and memos. Everything is also available through our REST API and daily SFTP exports.",
1216 },
1217 {
1218 q: "What happens if Vault goes away?",
1219 a: "Your funds are held at our partner banks in accounts titled for your benefit, not on Vault’s balance sheet. In a wind-down, partner banks return deposits directly to you.",
1220 },
1221];
1222
1223function Faq() {
1224 const [open, setOpen] = useState<number | null>(0);
1225 const base = useId();
1226 return (
1227 <section className="fd-vlt-faq" id="faq">
1228 <div className="fd-vlt-wrap fd-vlt-faq-grid">
1229 <div data-reveal="">
1230 <p className="fd-vlt-label">08 — FAQ</p>
1231 <h2 className="fd-vlt-h2">Fine print, in large print.</h2>
1232 </div>
1233 <div className="fd-vlt-faq-list">
1234 {FAQS.map((f, i) => {
1235 const isOpen = open === i;
1236 return (
1237 <div key={f.q} className="fd-vlt-faq-item" data-open={isOpen || undefined} data-reveal="" style={{ "--i": i } as CSSProperties}>
1238 <h3>
1239 <button
1240 type="button"
1241 aria-expanded={isOpen}
1242 aria-controls={`${base}-${i}`}
1243 id={`${base}-${i}-b`}
1244 onClick={() => setOpen(isOpen ? null : i)}
1245 >
1246 <span>{f.q}</span>
1247 <i aria-hidden="true" />
1248 </button>
1249 </h3>
1250 <div className="fd-vlt-faq-a" id={`${base}-${i}`} role="region" aria-labelledby={`${base}-${i}-b`}>
1251 <div>
1252 <p>{f.a}</p>
1253 </div>
1254 </div>
1255 </div>
1256 );
1257 })}
1258 </div>
1259 </div>
1260 </section>
1261 );
1262}
1263
1264/* ─────────────────────────── CTA + footer ─────────────────────────── */
1265
1266function Cta() {
1267 return (
1268 <section className="fd-vlt-cta fd-vlt-grid-bg fd-vlt-grid-dark">
1269 <div className="fd-vlt-wrap fd-vlt-cta-in" data-reveal="">
1270 <p className="fd-vlt-label fd-vlt-on-dark">09 — Begin</p>
1271 <h2 className="fd-vlt-cta-h">Start operating.</h2>
1272 <p className="fd-vlt-cta-p">Ten minutes to apply. One business day to approval. No minimums, no monthly fees on Launch.</p>
1273 <div className="fd-vlt-ctas">
1274 <a className="fd-vlt-btn fd-vlt-btn-inv" href="#pricing">
1275 Open an account <Arrow />
1276 </a>
1277 <a className="fd-vlt-btn fd-vlt-btn-ghost-inv" href="#faq">
1278 Talk to a banker
1279 </a>
1280 </div>
1281 </div>
1282 </section>
1283 );
1284}
1285
1286function Footer() {
1287 return (
1288 <footer className="fd-vlt-foot">
1289 <div className="fd-vlt-wrap">
1290 <div className="fd-vlt-foot-top">
1291 <a className="fd-vlt-brand" href="#top" aria-label="Vault home">
1292 <Logo />
1293 <span>Vault</span>
1294 </a>
1295 {[
1296 ["Product", ["Accounts", "Cards", "Payments", "Treasury", "API"]],
1297 ["Company", ["About", "Careers · 14 open", "Press", "Contact"]],
1298 ["Resources", ["Docs", "Status", "Security", "Changelog"]],
1299 ["Legal", ["Privacy", "Terms", "Deposit agreement", "Licenses"]],
1300 ].map(([h, items]) => (
1301 <div key={h as string} className="fd-vlt-foot-col">
1302 <h4>{h as string}</h4>
1303 <ul>
1304 {(items as string[]).map((it) => (
1305 <li key={it}>
1306 <a href="#top">{it}</a>
1307 </li>
1308 ))}
1309 </ul>
1310 </div>
1311 ))}
1312 </div>
1313 <p className="fd-vlt-legal">
1314 Vault is a financial technology company, not a bank. Banking services provided by Harbor State Bank and
1315 Meridian Trust, Members FDIC. The Vault Visa® Signature Card is issued by Harbor State Bank pursuant to a
1316 license from Visa U.S.A. Inc. Treasury products are offered through Vault Advisers LLC, an SEC-registered
1317 investment adviser; investments are not FDIC-insured, not bank-guaranteed and may lose value.
1318 </p>
1319 <div className="fd-vlt-foot-bot">
1320 <span>© 2026 Vault Financial, Inc.</span>
1321 <span>New York · Berlin</span>
1322 <span className="fd-vlt-mono">v4.12.0 · All systems normal</span>
1323 </div>
1324 </div>
1325 <div className="fd-vlt-giant" aria-hidden="true">
1326 VAULT
1327 </div>
1328 </footer>
1329 );
1330}
1331
1332/* ─────────────────────────── page ─────────────────────────── */
1333
1334export function Page() {
1335 const root = useRef<HTMLDivElement>(null);
1336 useReveal(root);
1337 return (
1338 <div ref={root} className="fd-vlt">
1339 <style>{css}</style>
1340 <Nav />
1341 <main>
1342 <Hero />
1343 <Logos />
1344 <Platform />
1345 <Capabilities />
1346 <Stats />
1347 <Security />
1348 <Testimonial />
1349 <Pricing />
1350 <Faq />
1351 <Cta />
1352 </main>
1353 <Footer />
1354 </div>
1355 );
1356}
1357
1358export default Page;
1359
1360/* ─────────────────────────── styles ─────────────────────────── */
1361
1362const css = `
1363.fd-vlt {
1364 --fd-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
1365 --fd-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
1366 --fd-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
1367 --fd-dur-1: 120ms;
1368 --fd-dur-2: 240ms;
1369 --fd-dur-3: 420ms;
1370 --fd-dur-4: 700ms;
1371
1372 --fd-vlt-ink: #0b0b0c;
1373 --fd-vlt-ink-2: #1c1c1f;
1374 --fd-vlt-paper: #ffffff;
1375 --fd-vlt-canvas: #f4f4f5;
1376 --fd-vlt-mute: #5e5e66;
1377 --fd-vlt-mute-dark: #a1a1aa;
1378 --fd-vlt-line: rgba(11, 11, 12, 0.1);
1379 --fd-vlt-line-2: rgba(11, 11, 12, 0.2);
1380 --fd-vlt-line-dark: rgba(255, 255, 255, 0.12);
1381 --fd-vlt-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter Variable", "Inter", "Helvetica Neue", "Segoe UI", Roboto, Arial, sans-serif;
1382 --fd-vlt-mono: ui-monospace, "SF Mono", "JetBrains Mono Variable", "JetBrains Mono", Menlo, Consolas, monospace;
1383 --fd-vlt-nav-h: 64px;
1384
1385 position: relative;
1386 display: block;
1387 margin: 0;
1388 padding: 0;
1389 background: var(--fd-vlt-paper);
1390 color: var(--fd-vlt-ink);
1391 font: 400 1rem/1.5 var(--fd-vlt-sans);
1392 letter-spacing: -0.005em;
1393 text-align: left;
1394 -webkit-font-smoothing: antialiased;
1395 -moz-osx-font-smoothing: grayscale;
1396 overflow-x: clip;
1397}
1398.fd-vlt, .fd-vlt *, .fd-vlt *::before, .fd-vlt *::after { box-sizing: border-box; }
1399.fd-vlt :where(h1, h2, h3, h4, h5, h6, p, ul, ol, li, dl, dt, dd, figure, figcaption, blockquote, main, header, footer, section, nav, article) {
1400 margin: 0; padding: 0; border: 0; font: inherit; color: inherit; letter-spacing: inherit; background: none;
1401}
1402.fd-vlt :where(ul, ol) { list-style: none; }
1403.fd-vlt :where(a) { color: inherit; text-decoration: none; }
1404.fd-vlt :where(button) {
1405 appearance: none; -webkit-appearance: none; margin: 0; padding: 0; border: 0; background: none;
1406 font: inherit; color: inherit; letter-spacing: inherit; text-align: inherit; cursor: pointer; line-height: inherit;
1407}
1408.fd-vlt :where(svg) { display: block; overflow: visible; }
1409.fd-vlt :where(b, strong) { font-weight: 600; }
1410.fd-vlt :where(small) { font-size: inherit; }
1411.fd-vlt :where(a, button, [tabindex]):focus-visible { outline: 2px solid rgba(11, 11, 12, 0.7); outline-offset: 2px; }
1412.fd-vlt-sr { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1413
1414.fd-vlt-wrap { width: 100%; max-width: 1280px; margin: 0 auto; padding: 0 32px; }
1415.fd-vlt-mono { font: 500 0.6875rem/1.4 var(--fd-vlt-mono); letter-spacing: 0.08em; text-transform: uppercase; }
1416.fd-vlt-label { font: 500 0.75rem/1.4 var(--fd-vlt-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fd-vlt-mute); }
1417.fd-vlt-on-dark { color: var(--fd-vlt-mute-dark); }
1418.fd-vlt-h2 { margin-top: 18px; font: 600 clamp(2rem, 4.6vw, 4rem)/1 var(--fd-vlt-sans); letter-spacing: -0.04em; }
1419
1420/* blueprint grid */
1421.fd-vlt-grid-bg { position: relative; isolation: isolate; }
1422.fd-vlt-grid-bg::before {
1423 content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
1424 background-image:
1425 linear-gradient(to right, rgba(11,11,12,0.07) 1px, transparent 1px),
1426 linear-gradient(to bottom, rgba(11,11,12,0.07) 1px, transparent 1px),
1427 linear-gradient(to right, rgba(11,11,12,0.03) 1px, transparent 1px),
1428 linear-gradient(to bottom, rgba(11,11,12,0.03) 1px, transparent 1px);
1429 background-size: 96px 96px, 96px 96px, 24px 24px, 24px 24px;
1430 background-position: center top;
1431 -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 40%, transparent 100%);
1432 mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 40%, transparent 100%);
1433}
1434.fd-vlt-grid-dark::before {
1435 background-image:
1436 linear-gradient(to right, rgba(255,255,255,0.08) 1px, transparent 1px),
1437 linear-gradient(to bottom, rgba(255,255,255,0.08) 1px, transparent 1px),
1438 linear-gradient(to right, rgba(255,255,255,0.03) 1px, transparent 1px),
1439 linear-gradient(to bottom, rgba(255,255,255,0.03) 1px, transparent 1px);
1440}
1441
1442/* buttons */
1443.fd-vlt-btn {
1444 display: inline-flex; align-items: center; gap: 10px; height: 48px; padding: 0 22px;
1445 border: 1px solid var(--fd-vlt-ink); border-radius: 0; background: var(--fd-vlt-ink); color: var(--fd-vlt-paper);
1446 font: 500 0.9375rem/1 var(--fd-vlt-sans); letter-spacing: -0.005em; text-decoration: none; white-space: nowrap;
1447 transition: transform var(--fd-dur-1) var(--fd-ease-out), background-color var(--fd-dur-2) var(--fd-ease-out), color var(--fd-dur-2) var(--fd-ease-out);
1448}
1449.fd-vlt-btn:hover { background: var(--fd-vlt-ink-2); }
1450.fd-vlt-btn:active { transform: scale(0.96); transition: transform var(--fd-dur-1) var(--fd-ease-out); }
1451.fd-vlt-btn .fd-vlt-arrow { transition: transform var(--fd-dur-2) var(--fd-spring); }
1452.fd-vlt-btn:hover .fd-vlt-arrow { transform: translateX(3px); }
1453.fd-vlt-btn-sm { height: 36px; padding: 0 14px; font-size: 0.8125rem; }
1454.fd-vlt-btn-ghost { background: transparent; color: var(--fd-vlt-ink); border-color: var(--fd-vlt-line-2); }
1455.fd-vlt-btn-ghost:hover { background: var(--fd-vlt-canvas); border-color: var(--fd-vlt-ink); }
1456.fd-vlt-btn-inv { background: var(--fd-vlt-paper); color: var(--fd-vlt-ink); border-color: var(--fd-vlt-paper); }
1457.fd-vlt-btn-inv:hover { background: #e9e9ec; }
1458.fd-vlt-btn-ghost-inv { background: transparent; color: var(--fd-vlt-paper); border-color: rgba(255,255,255,0.3); }
1459.fd-vlt-btn-ghost-inv:hover { background: rgba(255,255,255,0.08); border-color: #fff; }
1460.fd-vlt-tag {
1461 display: inline-flex; align-items: center; height: 20px; padding: 0 7px; border: 1px solid var(--fd-vlt-ink);
1462 font: 600 0.625rem/1 var(--fd-vlt-mono); letter-spacing: 0.08em; text-transform: uppercase;
1463}
1464.fd-vlt-tag-inv { background: var(--fd-vlt-paper); color: var(--fd-vlt-ink); border-color: var(--fd-vlt-paper); }
1465
1466/* nav */
1467.fd-vlt-nav {
1468 position: sticky; top: 0; z-index: 50; display: block;
1469 background: rgba(255,255,255,0); border-bottom: 1px solid transparent;
1470 transition: background-color var(--fd-dur-3) var(--fd-ease-out), border-color var(--fd-dur-3) var(--fd-ease-out), backdrop-filter var(--fd-dur-3) var(--fd-ease-out);
1471}
1472.fd-vlt-nav[data-condensed], .fd-vlt-nav[data-open] {
1473 background: rgba(255,255,255,0.86); border-bottom-color: var(--fd-vlt-line);
1474 -webkit-backdrop-filter: saturate(180%) blur(16px); backdrop-filter: saturate(180%) blur(16px);
1475}
1476.fd-vlt-nav-in {
1477 display: flex; align-items: center; gap: 32px; max-width: 1280px; margin: 0 auto; padding: 0 32px;
1478 height: var(--fd-vlt-nav-h); transition: height var(--fd-dur-3) var(--fd-ease-out);
1479}
1480.fd-vlt-nav[data-condensed] .fd-vlt-nav-in { height: 52px; }
1481.fd-vlt-brand { display: inline-flex; align-items: center; gap: 10px; font: 600 1.0625rem/1 var(--fd-vlt-sans); letter-spacing: -0.02em; color: var(--fd-vlt-ink); }
1482.fd-vlt-nav-links { display: flex; gap: 28px; margin-right: auto; }
1483.fd-vlt-nav-links a, .fd-vlt-nav-signin { font: 450 0.875rem/1 var(--fd-vlt-sans); color: var(--fd-vlt-mute); transition: color var(--fd-dur-1) linear; }
1484.fd-vlt-nav-links a:hover, .fd-vlt-nav-signin:hover { color: var(--fd-vlt-ink); }
1485.fd-vlt-nav-cta { display: flex; align-items: center; gap: 18px; margin-left: auto; }
1486.fd-vlt-burger { display: none; width: 40px; height: 40px; position: relative; }
1487.fd-vlt-burger span { position: absolute; left: 11px; right: 11px; height: 1.5px; background: var(--fd-vlt-ink); transition: transform var(--fd-dur-3) var(--fd-spring); }
1488.fd-vlt-burger span:first-child { top: 16px; }
1489.fd-vlt-burger span:last-child { top: 23px; }
1490.fd-vlt-nav[data-open] .fd-vlt-burger span:first-child { transform: translateY(3.5px) rotate(45deg); }
1491.fd-vlt-nav[data-open] .fd-vlt-burger span:last-child { transform: translateY(-3.5px) rotate(-45deg); }
1492.fd-vlt-sheet { display: grid; gap: 4px; padding: 8px 20px 20px; border-top: 1px solid var(--fd-vlt-line); }
1493.fd-vlt-sheet[hidden] { display: none; }
1494.fd-vlt-sheet a:not(.fd-vlt-btn) { display: block; padding: 14px 0; border-bottom: 1px solid var(--fd-vlt-line); font: 500 1.25rem/1.2 var(--fd-vlt-sans); letter-spacing: -0.02em; }
1495.fd-vlt-sheet .fd-vlt-btn { margin-top: 14px; justify-content: center; }
1496
1497/* hero */
1498.fd-vlt-hero { padding: 72px 0 0; margin-top: calc(var(--fd-vlt-nav-h) * -1); padding-top: calc(var(--fd-vlt-nav-h) + 72px); min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
1499.fd-vlt-hero-in { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: 48px; align-items: center; }
1500.fd-vlt-eyebrow { display: inline-flex; align-items: center; gap: 12px; font: 500 0.875rem/1.3 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1501.fd-vlt-h1 { margin-top: 28px; font: 600 clamp(3.25rem, 8.4vw, 7.75rem)/0.92 var(--fd-vlt-sans); letter-spacing: -0.055em; color: var(--fd-vlt-ink); }
1502.fd-vlt-mask { display: block; overflow: hidden; padding-bottom: 0.06em; margin-bottom: -0.06em; }
1503.fd-vlt-mask > span { display: block; animation: fd-vlt-mask var(--fd-dur-4) var(--fd-ease-out) both; animation-delay: var(--d, 0ms); animation-duration: 1000ms; }
1504.fd-vlt-dot { color: var(--fd-vlt-mute); }
1505@keyframes fd-vlt-mask { from { transform: translateY(105%); } to { transform: none; } }
1506.fd-vlt-rise { animation: fd-vlt-rise 900ms var(--fd-ease-out) both; animation-delay: var(--d, 0ms); }
1507@keyframes fd-vlt-rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
1508.fd-vlt-lede { margin-top: 28px; max-width: 34em; font: 400 clamp(1.0625rem, 1.4vw, 1.25rem)/1.5 var(--fd-vlt-sans); letter-spacing: -0.012em; color: var(--fd-vlt-mute); }
1509.fd-vlt-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }
1510.fd-vlt-fine { margin-top: 18px; font: 400 0.8125rem/1.4 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1511.fd-vlt-hero-card { justify-self: end; width: 100%; max-width: 440px; }
1512.fd-vlt-ticker { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 88px; border-top: 1px solid var(--fd-vlt-ink); }
1513.fd-vlt-ticker > div { padding: 18px 20px 28px 0; border-right: 1px solid var(--fd-vlt-line); }
1514.fd-vlt-ticker > div + div { padding-left: 20px; }
1515.fd-vlt-ticker > div:last-child { border-right: 0; }
1516.fd-vlt-ticker dt { font: 600 1.5rem/1.1 var(--fd-vlt-sans); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
1517.fd-vlt-ticker dd { margin-top: 6px; font: 400 0.8125rem/1.4 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1518.fd-vlt-reg { position: absolute; width: 18px; height: 18px; pointer-events: none; }
1519.fd-vlt-reg::before, .fd-vlt-reg::after { content: ""; position: absolute; background: var(--fd-vlt-ink); }
1520.fd-vlt-reg::before { left: 8.5px; top: 0; width: 1px; height: 18px; }
1521.fd-vlt-reg::after { top: 8.5px; left: 0; height: 1px; width: 18px; }
1522.fd-vlt-reg-tl { top: calc(var(--fd-vlt-nav-h) + 24px); left: 24px; }
1523.fd-vlt-reg-tr { top: calc(var(--fd-vlt-nav-h) + 24px); right: 24px; }
1524.fd-vlt-spec { position: absolute; right: 32px; bottom: 16px; font: 500 0.625rem/1 var(--fd-vlt-mono); letter-spacing: 0.12em; color: var(--fd-vlt-mute); }
1525
1526/* balance card */
1527.fd-vlt-card-wrap { position: relative; perspective: 1100px; padding: 28px 0 32px; }
1528.fd-vlt-fig { position: absolute; top: 0; left: 0; font: 500 0.6875rem/1 var(--fd-vlt-mono); letter-spacing: 0.06em; color: var(--fd-vlt-mute); }
1529.fd-vlt-fig-b { top: auto; bottom: -28px; }
1530.fd-vlt-card {
1531 --rx: 0deg; --ry: 0deg; --gx: 50%; --gy: 30%;
1532 position: relative; overflow: hidden; padding: 26px 26px 10px;
1533 background: var(--fd-vlt-paper); color: var(--fd-vlt-ink); border: 1px solid var(--fd-vlt-ink);
1534 box-shadow: 14px 14px 0 -1px var(--fd-vlt-canvas), 14px 14px 0 0 var(--fd-vlt-line-2);
1535 transform: rotateX(var(--rx)) rotateY(var(--ry)); transform-style: preserve-3d; will-change: transform;
1536}
1537.fd-vlt-card-glare { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(420px circle at var(--gx) var(--gy), rgba(11,11,12,0.05), transparent 60%); }
1538.fd-vlt-card-top { display: flex; justify-content: space-between; align-items: center; color: var(--fd-vlt-mute); }
1539.fd-vlt-live { display: inline-flex; align-items: center; gap: 6px; font: 500 0.6875rem/1 var(--fd-vlt-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fd-vlt-ink); }
1540.fd-vlt-live i { width: 6px; height: 6px; border-radius: 50%; background: var(--fd-vlt-ink); animation: fd-vlt-pulse 1.6s var(--fd-ease-in-out) infinite; }
1541@keyframes fd-vlt-pulse { 50% { opacity: 0.25; } }
1542.fd-vlt-card-bal { display: flex; align-items: flex-start; gap: 4px; margin-top: 22px; font: 600 clamp(2rem, 3.3vw, 2.75rem)/1.1 var(--fd-vlt-sans); letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
1543.fd-vlt-card-cur { font-size: 0.55em; margin-top: 0.18em; color: var(--fd-vlt-mute); letter-spacing: 0; }
1544.fd-vlt-card-meta { display: flex; gap: 18px; margin-top: 10px; font: 500 0.6875rem/1.3 var(--fd-vlt-mono); letter-spacing: 0.04em; color: var(--fd-vlt-mute); }
1545.fd-vlt-spark { width: 100%; height: 64px; margin-top: 20px; color: var(--fd-vlt-ink); }
1546.fd-vlt-txns { margin-top: 14px; border-top: 1px solid var(--fd-vlt-line); }
1547.fd-vlt-txn { display: grid; grid-template-columns: 10px 1fr auto; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--fd-vlt-line); animation: fd-vlt-txn 600ms var(--fd-ease-out) both; }
1548.fd-vlt-txn:last-child { border-bottom: 0; }
1549@keyframes fd-vlt-txn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
1550.fd-vlt-txn-dot { width: 7px; height: 7px; border: 1px solid var(--fd-vlt-ink); }
1551.fd-vlt-txn-dot[data-in] { background: var(--fd-vlt-ink); }
1552.fd-vlt-txn-who { display: grid; gap: 2px; min-width: 0; }
1553.fd-vlt-txn-who b { font: 500 0.875rem/1.2 var(--fd-vlt-sans); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1554.fd-vlt-txn-who small { font: 400 0.75rem/1.2 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1555.fd-vlt-txn-amt { font: 500 0.875rem/1 var(--fd-vlt-sans); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
1556.fd-vlt-dim { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: 8px; font: 500 0.625rem/1 var(--fd-vlt-mono); letter-spacing: 0.1em; color: var(--fd-vlt-mute); }
1557.fd-vlt-dim i { flex: 1; height: 7px; border-left: 1px solid var(--fd-vlt-line-2); border-right: 1px solid var(--fd-vlt-line-2); position: relative; }
1558.fd-vlt-dim i::after { content: ""; position: absolute; left: 0; right: 0; top: 3px; height: 1px; background: var(--fd-vlt-line-2); }
1559.fd-vlt-dim i:first-child { border-right: 0; }
1560.fd-vlt-dim i:last-child { border-left: 0; }
1561
1562/* odometer */
1563.fd-vlt-odo { position: relative; display: inline-flex; overflow: hidden; line-height: 1.1; height: 1.1em; }
1564.fd-vlt-odo-col { display: inline-block; height: 1.1em; overflow: hidden; }
1565.fd-vlt-odo-strip { display: flex; flex-direction: column; transition: transform 900ms var(--fd-ease-out); will-change: transform; }
1566.fd-vlt-odo-strip > span { display: block; height: 1.1em; line-height: 1.1em; text-align: center; }
1567.fd-vlt-odo-sep { display: inline-block; }
1568
1569/* logos */
1570.fd-vlt-logos { padding: 64px 0 72px; border-bottom: 1px solid var(--fd-vlt-line); }
1571.fd-vlt-logo-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 28px 40px; margin-top: 28px; color: var(--fd-vlt-ink); }
1572.fd-vlt-logo-row li { opacity: 0.86; font-size: 1.375rem; line-height: 1; }
1573.fd-vlt-wm-1 { font: 700 1.375rem/1 var(--fd-vlt-sans); letter-spacing: -0.04em; }
1574.fd-vlt-wm-2 { font: 500 1.0625rem/1 var(--fd-vlt-sans); letter-spacing: 0.32em; }
1575.fd-vlt-wm-3 { font: 300 1.5rem/1 var(--fd-vlt-sans); letter-spacing: -0.02em; }
1576.fd-vlt-wm-4 { font: italic 600 1.375rem/1 Georgia, "Times New Roman", serif; letter-spacing: -0.01em; }
1577.fd-vlt-wm-5 { font: 600 1rem/1 var(--fd-vlt-mono); letter-spacing: 0.04em; }
1578.fd-vlt-wm-6 { font: 500 1.1875rem/1 var(--fd-vlt-sans); letter-spacing: -0.03em; }
1579.fd-vlt-wm-7 { font: 800 1.625rem/1 var(--fd-vlt-sans); letter-spacing: -0.06em; }
1580
1581/* platform */
1582.fd-vlt-plat { position: relative; height: 340vh; background: var(--fd-vlt-canvas); border-bottom: 1px solid var(--fd-vlt-line); --p: 0; }
1583.fd-vlt-plat-stick { position: sticky; top: 0; height: 100vh; display: flex; align-items: center; overflow: hidden; }
1584.fd-vlt-plat-grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 64px; align-items: center; }
1585.fd-vlt-steps { margin-top: 36px; border-top: 1px solid var(--fd-vlt-line-2); }
1586.fd-vlt-steps li { display: grid; grid-template-columns: 40px 1fr; gap: 12px; padding: 16px 0; border-bottom: 1px solid var(--fd-vlt-line); opacity: 0.38; transition: opacity var(--fd-dur-3) var(--fd-ease-out); }
1587.fd-vlt-steps li[data-active] { opacity: 1; }
1588.fd-vlt-step-k { font: 500 0.75rem/1.6 var(--fd-vlt-mono); color: var(--fd-vlt-mute); }
1589.fd-vlt-steps h3 { font: 600 1.0625rem/1.3 var(--fd-vlt-sans); letter-spacing: -0.015em; }
1590.fd-vlt-steps p { margin-top: 6px; font: 400 0.9375rem/1.5 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1591.fd-vlt-plat-bar { display: flex; align-items: center; gap: 12px; margin-top: 24px; }
1592.fd-vlt-plat-bar i { position: relative; flex: 1; height: 1px; background: var(--fd-vlt-line-2); overflow: hidden; }
1593.fd-vlt-plat-bar i::after { content: ""; position: absolute; inset: 0; background: var(--fd-vlt-ink); transform-origin: left; transform: scaleX(var(--p)); }
1594.fd-vlt-plat-bar span { font: 500 0.6875rem/1 var(--fd-vlt-mono); font-variant-numeric: tabular-nums; color: var(--fd-vlt-mute); }
1595
1596.fd-vlt-dash-wrap { position: relative; }
1597.fd-vlt-dash { background: var(--fd-vlt-paper); border: 1px solid var(--fd-vlt-ink); box-shadow: 18px 18px 0 -1px var(--fd-vlt-paper), 18px 18px 0 0 var(--fd-vlt-line-2); }
1598.fd-vlt-dash-chrome { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; border-bottom: 1px solid var(--fd-vlt-line); }
1599.fd-vlt-dash-chrome span { width: 8px; height: 8px; border: 1px solid var(--fd-vlt-line-2); border-radius: 50%; }
1600.fd-vlt-dash-chrome em { margin-left: 12px; font: 500 0.6875rem/1 var(--fd-vlt-mono); font-style: normal; color: var(--fd-vlt-mute); letter-spacing: 0.02em; }
1601.fd-vlt-dash-body {
1602 position: relative; display: grid; gap: 10px; padding: 12px; height: 470px;
1603 grid-template-columns: 150px repeat(6, minmax(0, 1fr));
1604 grid-template-rows: 1.05fr 1fr 1fr;
1605 grid-template-areas:
1606 "side bal bal bal flow flow flow"
1607 "side card card txns txns txns txns"
1608 "side appr appr txns txns txns txns";
1609}
1610.fd-vlt-slot-side { grid-area: side; }
1611.fd-vlt-slot-bal { grid-area: bal; }
1612.fd-vlt-slot-flow { grid-area: flow; }
1613.fd-vlt-slot-card { grid-area: card; }
1614.fd-vlt-slot-txns { grid-area: txns; }
1615.fd-vlt-dash-body > .fd-vlt-slot-appr { grid-area: appr; }
1616.fd-vlt-slot { border: 1px dashed var(--fd-vlt-line-2); display: flex; align-items: flex-start; justify-content: flex-start; padding: 8px; }
1617.fd-vlt-slot span { font: 500 0.625rem/1 var(--fd-vlt-mono); color: var(--fd-vlt-mute); letter-spacing: 0.1em; }
1618.fd-vlt-piece {
1619 --t: 0; --dx: 0px; --dy: 0px; position: relative; z-index: 1; min-width: 0; min-height: 0;
1620 opacity: var(--t);
1621 transform: translate3d(calc(var(--dx) * (1 - var(--t))), calc(var(--dy) * (1 - var(--t))), 0) scale(calc(0.94 + 0.06 * var(--t)));
1622 will-change: transform, opacity;
1623}
1624.fd-vlt-piece > * { height: 100%; }
1625.fd-vlt-tile { display: flex; flex-direction: column; gap: 6px; height: 100%; padding: 12px 14px; background: var(--fd-vlt-paper); border: 1px solid var(--fd-vlt-ink); overflow: hidden; }
1626.fd-vlt-tile small { font: 500 0.625rem/1.2 var(--fd-vlt-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fd-vlt-mute); }
1627.fd-vlt-tile strong { font: 600 1.5rem/1.1 var(--fd-vlt-sans); letter-spacing: -0.035em; font-variant-numeric: tabular-nums; }
1628.fd-vlt-delta { font: 500 0.75rem/1 var(--fd-vlt-sans); color: var(--fd-vlt-ink); }
1629.fd-vlt-split { display: flex; gap: 2px; height: 8px; margin-top: auto; }
1630.fd-vlt-split i { display: block; height: 100%; background: var(--fd-vlt-ink); }
1631.fd-vlt-split i:nth-child(2) { opacity: 0.6; }
1632.fd-vlt-split i:nth-child(3) { opacity: 0.35; }
1633.fd-vlt-split i:nth-child(4) { opacity: 0.16; }
1634.fd-vlt-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; font: 400 0.625rem/1.2 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1635.fd-vlt-bars { flex: 1; display: flex; align-items: flex-end; gap: 5px; min-height: 0; padding-top: 6px; }
1636.fd-vlt-bars span { flex: 1; display: flex; align-items: flex-end; gap: 1px; height: 100%; }
1637.fd-vlt-bars i { flex: 1; display: block; background: var(--fd-vlt-ink); }
1638.fd-vlt-bars i + i { background: transparent; border: 1px solid var(--fd-vlt-ink); }
1639.fd-vlt-runway { font: 500 0.6875rem/1 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1640.fd-vlt-side { display: flex; flex-direction: column; gap: 2px; height: 100%; padding: 10px; border: 1px solid var(--fd-vlt-ink); background: var(--fd-vlt-paper); }
1641.fd-vlt-side b { display: flex; align-items: center; gap: 6px; margin-bottom: 12px; font: 600 0.75rem/1.2 var(--fd-vlt-sans); letter-spacing: -0.01em; }
1642.fd-vlt-side b svg { width: 14px; height: 14px; }
1643.fd-vlt-side span { padding: 7px 8px; font: 450 0.75rem/1 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1644.fd-vlt-side span[data-on] { background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); }
1645.fd-vlt-mini-card { position: relative; display: flex; flex-direction: column; justify-content: space-between; height: 100%; padding: 12px; background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); overflow: hidden; }
1646.fd-vlt-mini-card > div:first-child { display: flex; justify-content: space-between; align-items: center; font: 500 0.625rem/1 var(--fd-vlt-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fd-vlt-mute-dark); }
1647.fd-vlt-mini-card svg { width: 16px; height: 16px; color: #fff; }
1648.fd-vlt-mini-pan { font: 500 0.75rem/1 var(--fd-vlt-mono); letter-spacing: 0.04em; white-space: nowrap; overflow: hidden; text-overflow: clip; }
1649.fd-vlt-mini-foot { display: flex; justify-content: space-between; font: 400 0.6875rem/1.2 var(--fd-vlt-sans); color: var(--fd-vlt-mute-dark); }
1650.fd-vlt-mini-meter { display: block; height: 2px; background: rgba(255,255,255,0.18); position: relative; }
1651.fd-vlt-mini-meter::after { content: ""; position: absolute; inset: 0; background: #fff; transform-origin: left; transform: scaleX(var(--m)); }
1652.fd-vlt-table { gap: 0; }
1653.fd-vlt-table small { margin-bottom: 6px; }
1654.fd-vlt-row { display: grid; grid-template-columns: 48px 1fr 0.8fr auto; gap: 8px; padding: 8px 0; border-top: 1px solid var(--fd-vlt-line); font: 400 0.75rem/1.2 var(--fd-vlt-sans); }
1655.fd-vlt-row span:first-child, .fd-vlt-row span:nth-child(3) { color: var(--fd-vlt-mute); }
1656.fd-vlt-row span:last-child { font-variant-numeric: tabular-nums; font-weight: 500; text-align: right; }
1657.fd-vlt-appr strong { font-size: 1.125rem; }
1658.fd-vlt-appr > span { font: 400 0.6875rem/1.2 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1659.fd-vlt-appr-btns { display: flex; gap: 6px; margin-top: auto; }
1660.fd-vlt-appr-btns span { padding: 6px 8px; border: 1px solid var(--fd-vlt-ink); font: 500 0.625rem/1 var(--fd-vlt-sans); }
1661.fd-vlt-appr-btns span:last-child { background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); }
1662
1663/* capabilities */
1664.fd-vlt-caps { position: relative; height: 300vh; background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); --p: 0; }
1665.fd-vlt-caps-stick { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; justify-content: center; gap: 40px; overflow: hidden; }
1666.fd-vlt-caps-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; }
1667.fd-vlt-caps-count { font: 500 0.875rem/1 var(--fd-vlt-mono); color: var(--fd-vlt-mute-dark); font-variant-numeric: tabular-nums; }
1668.fd-vlt-caps-count span { color: var(--fd-vlt-paper); }
1669.fd-vlt-caps-track {
1670 --x: 0px; display: flex; gap: 20px; width: 100%; overflow: visible;
1671 padding: 0 max(32px, calc((100% - 1280px) / 2 + 32px));
1672 transform: translate3d(var(--x), 0, 0); will-change: transform; outline-offset: -2px;
1673}
1674.fd-vlt-cap {
1675 flex: 0 0 min(400px, 80vw); display: flex; flex-direction: column; min-height: min(500px, 58vh); padding: 22px;
1676 border: 1px solid var(--fd-vlt-line-dark); background: var(--fd-vlt-ink-2);
1677 transition: border-color var(--fd-dur-2) var(--fd-ease-out), background-color var(--fd-dur-2) var(--fd-ease-out);
1678}
1679.fd-vlt-cap:hover { border-color: rgba(255,255,255,0.4); background: #222226; }
1680.fd-vlt-cap-top { display: flex; justify-content: space-between; color: var(--fd-vlt-mute-dark); }
1681.fd-vlt-cap-art { flex: 1; display: grid; place-items: center; min-height: 120px; padding: 18px 0; color: var(--fd-vlt-paper); }
1682.fd-vlt-cap-art svg { width: 78%; max-width: 240px; height: auto; }
1683.fd-vlt-cap-art svg rect[fill="#fff"], .fd-vlt-cap-art svg circle[fill="#fff"] { fill: var(--fd-vlt-ink-2); }
1684.fd-vlt-cap-art svg [stroke="#fff"] { stroke: var(--fd-vlt-ink); }
1685.fd-vlt-cap h3 { font: 600 1.625rem/1.1 var(--fd-vlt-sans); letter-spacing: -0.03em; }
1686.fd-vlt-cap p { margin-top: 10px; font: 400 0.9375rem/1.5 var(--fd-vlt-sans); color: var(--fd-vlt-mute-dark); }
1687.fd-vlt-cap dl { margin-top: 20px; border-top: 1px solid var(--fd-vlt-line-dark); }
1688.fd-vlt-cap dl div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--fd-vlt-line-dark); font: 400 0.8125rem/1.2 var(--fd-vlt-sans); }
1689.fd-vlt-cap dt { color: var(--fd-vlt-mute-dark); }
1690.fd-vlt-cap dd { font-variant-numeric: tabular-nums; }
1691.fd-vlt-cap-end { flex: 0 0 1px; }
1692.fd-vlt-caps-progress { position: relative; height: 1px; background: var(--fd-vlt-line-dark); }
1693.fd-vlt-caps-progress i { position: absolute; inset: 0; background: var(--fd-vlt-paper); transform-origin: left; transform: scaleX(var(--p)); }
1694
1695/* stats */
1696.fd-vlt-stats { padding: 140px 0 120px; }
1697.fd-vlt-stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 64px; border-top: 1px solid var(--fd-vlt-ink); }
1698.fd-vlt-stat { display: flex; flex-direction: column; gap: 14px; padding: 18px 24px 8px 0; border-right: 1px solid var(--fd-vlt-line); }
1699.fd-vlt-stat + .fd-vlt-stat { padding-left: 24px; }
1700.fd-vlt-stat:last-child { border-right: 0; }
1701.fd-vlt-stat .fd-vlt-mono { color: var(--fd-vlt-mute); }
1702.fd-vlt-count { font: 600 clamp(2.5rem, 4.6vw, 4.25rem)/1 var(--fd-vlt-sans); letter-spacing: -0.05em; font-variant-numeric: tabular-nums; white-space: nowrap; }
1703.fd-vlt-stat p { max-width: 22em; font: 400 0.9375rem/1.45 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1704.fd-vlt-footnote { margin-top: 40px; font: 400 0.75rem/1.4 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1705
1706/* security */
1707.fd-vlt-sec { padding: 120px 0 0; background: var(--fd-vlt-canvas); border-top: 1px solid var(--fd-vlt-line); overflow: hidden; }
1708.fd-vlt-sec-grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 64px; }
1709.fd-vlt-sec-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; border-top: 1px solid var(--fd-vlt-ink); }
1710.fd-vlt-sec-col { padding: 18px 20px 0 0; }
1711.fd-vlt-sec-col + .fd-vlt-sec-col { padding-left: 20px; border-left: 1px solid var(--fd-vlt-line); }
1712.fd-vlt-sec-col .fd-vlt-mono { color: var(--fd-vlt-mute); }
1713.fd-vlt-sec-col h3 { margin-top: 28px; font: 600 1.25rem/1.2 var(--fd-vlt-sans); letter-spacing: -0.02em; }
1714.fd-vlt-sec-col p { margin-top: 10px; font: 400 0.9375rem/1.5 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1715.fd-vlt-marquee { margin-top: 96px; border-top: 1px solid var(--fd-vlt-line); }
1716.fd-vlt-marquee-row { overflow: hidden; border-bottom: 1px solid var(--fd-vlt-line); -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); }
1717.fd-vlt-marquee-track { display: flex; width: max-content; animation: fd-vlt-marquee 48s linear infinite; }
1718.fd-vlt-marquee-row[data-dir="rev"] .fd-vlt-marquee-track { animation-direction: reverse; animation-duration: 56s; }
1719.fd-vlt-marquee:hover .fd-vlt-marquee-track { animation-play-state: paused; }
1720.fd-vlt-marquee-track li { display: inline-flex; align-items: center; gap: 10px; padding: 20px 32px; border-right: 1px solid var(--fd-vlt-line); font: 500 0.8125rem/1 var(--fd-vlt-mono); letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; }
1721@keyframes fd-vlt-marquee { to { transform: translateX(-50%); } }
1722
1723/* testimonial */
1724.fd-vlt-quote { padding: 140px 0; }
1725.fd-vlt-quote-grid { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 24px 48px; }
1726.fd-vlt-quote figure { grid-column: 2; }
1727.fd-vlt-quote blockquote { font: 500 clamp(1.625rem, 3.1vw, 2.75rem)/1.15 var(--fd-vlt-sans); letter-spacing: -0.03em; text-indent: -0.42em; }
1728.fd-vlt-quote figcaption { display: flex; align-items: center; gap: 14px; margin-top: 36px; }
1729.fd-vlt-avatar { display: block; width: 44px; height: 44px; object-fit: cover; object-position: center top; background: var(--fd-vlt-ink); }
1730.fd-vlt-quote figcaption b { display: block; font: 600 0.9375rem/1.3 var(--fd-vlt-sans); }
1731.fd-vlt-quote figcaption small { display: block; font: 400 0.8125rem/1.3 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1732.fd-vlt-quote-stats { grid-column: 2; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 56px; border-top: 1px solid var(--fd-vlt-ink); }
1733.fd-vlt-quote-stats div { padding: 16px 16px 0 0; }
1734.fd-vlt-quote-stats div + div { padding-left: 16px; border-left: 1px solid var(--fd-vlt-line); }
1735.fd-vlt-quote-stats dt { font: 600 1.75rem/1.1 var(--fd-vlt-sans); letter-spacing: -0.035em; }
1736.fd-vlt-quote-stats dd { margin-top: 4px; font: 400 0.8125rem/1.4 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1737
1738/* pricing */
1739.fd-vlt-pricing { padding: 120px 0 140px; border-top: 1px solid var(--fd-vlt-line); }
1740.fd-vlt-pricing-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; flex-wrap: wrap; }
1741.fd-vlt-seg { position: relative; display: inline-grid; grid-template-columns: 1fr 1fr; padding: 4px; border: 1px solid var(--fd-vlt-ink); background: var(--fd-vlt-paper); }
1742.fd-vlt-seg button { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 38px; padding: 0 18px; font: 500 0.875rem/1 var(--fd-vlt-sans); color: var(--fd-vlt-ink); transition: color var(--fd-dur-2) var(--fd-ease-out); }
1743.fd-vlt-seg button[aria-checked="true"] { color: var(--fd-vlt-paper); }
1744.fd-vlt-seg-thumb { position: absolute; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 4px); background: var(--fd-vlt-ink); transition: transform var(--fd-dur-3) var(--fd-spring); }
1745.fd-vlt-seg[data-annual] .fd-vlt-seg-thumb { transform: translateX(100%); }
1746.fd-vlt-save { font: 600 0.6875rem/1 var(--fd-vlt-mono); opacity: 0.75; }
1747.fd-vlt-plans { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 56px; border: 1px solid var(--fd-vlt-ink); }
1748.fd-vlt-plan { display: flex; flex-direction: column; padding: 28px; background: var(--fd-vlt-paper); }
1749.fd-vlt-plan + .fd-vlt-plan { border-left: 1px solid var(--fd-vlt-ink); }
1750.fd-vlt-plan[data-featured] { background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); }
1751.fd-vlt-plan-top { display: flex; justify-content: space-between; align-items: center; }
1752.fd-vlt-plan h3 { font: 600 1.25rem/1.2 var(--fd-vlt-sans); letter-spacing: -0.02em; }
1753.fd-vlt-plan-who { margin-top: 6px; font: 400 0.875rem/1.4 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1754.fd-vlt-plan[data-featured] .fd-vlt-plan-who, .fd-vlt-plan[data-featured] .fd-vlt-plan-bill, .fd-vlt-plan[data-featured] .fd-vlt-price-per, .fd-vlt-plan[data-featured] .fd-vlt-price-cur { color: var(--fd-vlt-mute-dark); }
1755.fd-vlt-price { display: flex; align-items: flex-start; gap: 4px; margin-top: 36px; font: 600 3.5rem/1.1 var(--fd-vlt-sans); letter-spacing: -0.05em; font-variant-numeric: tabular-nums; }
1756.fd-vlt-price-cur { font-size: 0.42em; margin-top: 0.3em; color: var(--fd-vlt-mute); letter-spacing: 0; }
1757.fd-vlt-price-per { align-self: flex-end; margin-bottom: 0.4em; font: 400 0.9375rem/1 var(--fd-vlt-sans); letter-spacing: 0; color: var(--fd-vlt-mute); }
1758.fd-vlt-plan-bill { margin-top: 6px; font: 400 0.8125rem/1.3 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1759.fd-vlt-plan .fd-vlt-btn { justify-content: space-between; margin-top: 28px; }
1760.fd-vlt-plan ul { margin-top: 28px; border-top: 1px solid var(--fd-vlt-line); }
1761.fd-vlt-plan[data-featured] ul { border-top-color: var(--fd-vlt-line-dark); }
1762.fd-vlt-plan li { display: flex; gap: 10px; align-items: flex-start; padding: 11px 0; border-bottom: 1px solid var(--fd-vlt-line); font: 400 0.875rem/1.4 var(--fd-vlt-sans); }
1763.fd-vlt-plan[data-featured] li { border-bottom-color: var(--fd-vlt-line-dark); }
1764.fd-vlt-check { flex: none; margin-top: 2px; }
1765
1766/* faq */
1767.fd-vlt-faq { padding: 120px 0 140px; background: var(--fd-vlt-canvas); border-top: 1px solid var(--fd-vlt-line); }
1768.fd-vlt-faq-grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 64px; align-items: start; }
1769.fd-vlt-faq-list { border-top: 1px solid var(--fd-vlt-ink); }
1770.fd-vlt-faq-item { border-bottom: 1px solid var(--fd-vlt-line-2); }
1771.fd-vlt-faq-item button { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 24px; padding: 24px 0; font: 500 1.1875rem/1.3 var(--fd-vlt-sans); letter-spacing: -0.02em; color: var(--fd-vlt-ink); }
1772.fd-vlt-faq-item button i { position: relative; flex: none; width: 14px; height: 14px; }
1773.fd-vlt-faq-item button i::before, .fd-vlt-faq-item button i::after { content: ""; position: absolute; left: 0; right: 0; top: 6.5px; height: 1.5px; background: currentColor; transition: transform var(--fd-dur-3) var(--fd-spring); }
1774.fd-vlt-faq-item button i::after { transform: rotate(90deg); }
1775.fd-vlt-faq-item[data-open] button i::after { transform: rotate(0deg); }
1776.fd-vlt-faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--fd-dur-3) var(--fd-ease-out); }
1777.fd-vlt-faq-item[data-open] .fd-vlt-faq-a { grid-template-rows: 1fr; }
1778.fd-vlt-faq-a > div { overflow: hidden; }
1779.fd-vlt-faq-a p { max-width: 40em; padding-bottom: 24px; font: 400 1rem/1.6 var(--fd-vlt-sans); color: var(--fd-vlt-mute); }
1780
1781/* cta */
1782.fd-vlt-cta { padding: 160px 0 170px; background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); }
1783.fd-vlt-cta-in { display: flex; flex-direction: column; align-items: flex-start; }
1784.fd-vlt-cta-h { margin-top: 24px; font: 600 clamp(3.5rem, 11vw, 10rem)/0.9 var(--fd-vlt-sans); letter-spacing: -0.06em; }
1785.fd-vlt-cta-p { margin-top: 28px; max-width: 30em; font: 400 1.1875rem/1.5 var(--fd-vlt-sans); color: var(--fd-vlt-mute-dark); }
1786
1787/* footer */
1788.fd-vlt-foot { position: relative; padding: 72px 0 0; background: var(--fd-vlt-ink); color: var(--fd-vlt-paper); border-top: 1px solid var(--fd-vlt-line-dark); overflow: hidden; }
1789.fd-vlt-foot .fd-vlt-brand { color: var(--fd-vlt-paper); align-self: start; }
1790.fd-vlt-foot-top { display: grid; grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); gap: 32px; }
1791.fd-vlt-foot-col h4 { font: 500 0.6875rem/1 var(--fd-vlt-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--fd-vlt-mute-dark); }
1792.fd-vlt-foot-col ul { display: grid; gap: 10px; margin-top: 18px; }
1793.fd-vlt-foot-col a { font: 400 0.875rem/1.3 var(--fd-vlt-sans); color: #d4d4d8; transition: color var(--fd-dur-1) linear; }
1794.fd-vlt-foot-col a:hover { color: #fff; }
1795.fd-vlt-legal { margin-top: 64px; max-width: 72em; font: 400 0.75rem/1.6 var(--fd-vlt-sans); color: var(--fd-vlt-mute-dark); }
1796.fd-vlt-foot-bot { display: flex; flex-wrap: wrap; gap: 12px 32px; justify-content: space-between; margin-top: 32px; padding: 20px 0; border-top: 1px solid var(--fd-vlt-line-dark); font: 400 0.8125rem/1.3 var(--fd-vlt-sans); color: var(--fd-vlt-mute-dark); }
1797.fd-vlt-giant { margin-top: 24px; padding: 0 16px; font: 700 clamp(6rem, 27vw, 24rem)/0.74 var(--fd-vlt-sans); letter-spacing: -0.07em; color: transparent; -webkit-text-stroke: 1px rgba(255,255,255,0.22); text-align: center; white-space: nowrap; user-select: none; transform: translateY(6%); }
1798
1799/* reveal */
1800.fd-vlt[data-js] [data-reveal] {
1801 opacity: 0; transform: translateY(22px);
1802 transition: opacity var(--fd-dur-4) var(--fd-ease-out), transform 900ms var(--fd-ease-out);
1803 transition-delay: calc(var(--i, 0) * 70ms);
1804}
1805.fd-vlt[data-js] [data-reveal][data-in] { opacity: 1; transform: none; }
1806
1807/* responsive */
1808@media (max-width: 1080px) {
1809 .fd-vlt-nav-links { gap: 20px; }
1810 .fd-vlt-plat-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 40px; }
1811 .fd-vlt-dash-body { grid-template-columns: 110px repeat(6, minmax(0, 1fr)); }
1812 .fd-vlt-foot-top { grid-template-columns: repeat(4, minmax(0, 1fr)); }
1813 .fd-vlt-foot-top > .fd-vlt-brand { grid-column: 1 / -1; }
1814}
1815@media (max-width: 900px) {
1816 .fd-vlt-wrap, .fd-vlt-nav-in { padding: 0 20px; }
1817 .fd-vlt-nav-links, .fd-vlt-nav-signin { display: none; }
1818 .fd-vlt-burger { display: block; }
1819 .fd-vlt-hero { min-height: 0; padding-top: calc(var(--fd-vlt-nav-h) + 40px); }
1820 .fd-vlt-hero-in { grid-template-columns: 1fr; gap: 56px; }
1821 .fd-vlt-hero-card { justify-self: stretch; max-width: 520px; }
1822 .fd-vlt-ticker { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 64px; }
1823 .fd-vlt-ticker > div:nth-child(2) { border-right: 0; }
1824 .fd-vlt-ticker > div:nth-child(3) { padding-left: 0; border-top: 1px solid var(--fd-vlt-line); }
1825 .fd-vlt-ticker > div:nth-child(4) { border-top: 1px solid var(--fd-vlt-line); }
1826 .fd-vlt-spec, .fd-vlt-reg { display: none; }
1827 .fd-vlt-plat { height: auto; padding: 96px 0; }
1828 .fd-vlt-plat-stick { position: relative; height: auto; overflow: visible; }
1829 .fd-vlt-plat-grid { grid-template-columns: 1fr; gap: 40px; }
1830 .fd-vlt-steps li { opacity: 1; }
1831 .fd-vlt-plat-bar { display: none; }
1832 .fd-vlt-dash-body {
1833 height: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; grid-auto-rows: minmax(130px, auto);
1834 grid-template-areas: "bal bal" "flow flow" "card appr" "txns txns";
1835 }
1836 .fd-vlt-slot-side { display: none; }
1837 .fd-vlt-slot-flow { min-height: 170px; }
1838 .fd-vlt-sec-grid, .fd-vlt-faq-grid { grid-template-columns: 1fr; gap: 40px; }
1839 .fd-vlt-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1840 .fd-vlt-stat:nth-child(2) { border-right: 0; }
1841 .fd-vlt-stat:nth-child(3) { padding-left: 0; }
1842 .fd-vlt-stat:nth-child(n + 3) { border-top: 1px solid var(--fd-vlt-line); padding-top: 18px; margin-top: 18px; }
1843 .fd-vlt-quote-grid { grid-template-columns: 1fr; }
1844 .fd-vlt-quote figure, .fd-vlt-quote-stats { grid-column: 1; }
1845 .fd-vlt-plans { grid-template-columns: 1fr; }
1846 .fd-vlt-plan + .fd-vlt-plan { border-left: 0; border-top: 1px solid var(--fd-vlt-ink); }
1847}
1848@media (max-width: 640px) {
1849 .fd-vlt-stats, .fd-vlt-quote, .fd-vlt-pricing, .fd-vlt-faq { padding: 88px 0; }
1850 .fd-vlt-sec { padding-top: 88px; }
1851 .fd-vlt-cta { padding: 112px 0; }
1852 .fd-vlt-btn { height: 46px; }
1853 .fd-vlt-nav-cta .fd-vlt-btn-sm { display: none; }
1854 .fd-vlt-sec-cols { grid-template-columns: 1fr; }
1855 .fd-vlt-sec-col + .fd-vlt-sec-col { padding-left: 0; border-left: 0; border-top: 1px solid var(--fd-vlt-line); margin-top: 24px; }
1856 .fd-vlt-sec-col h3 { margin-top: 12px; }
1857 .fd-vlt-stats-grid { grid-template-columns: 1fr; }
1858 .fd-vlt-stat, .fd-vlt-stat + .fd-vlt-stat { padding-left: 0; border-right: 0; }
1859 .fd-vlt-stat + .fd-vlt-stat { border-top: 1px solid var(--fd-vlt-line); padding-top: 18px; margin-top: 18px; }
1860 .fd-vlt-quote-stats { grid-template-columns: 1fr; }
1861 .fd-vlt-quote-stats div + div { padding-left: 0; border-left: 0; border-top: 1px solid var(--fd-vlt-line); margin-top: 16px; }
1862 .fd-vlt-quote blockquote { text-indent: 0; }
1863 .fd-vlt-foot-top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1864 .fd-vlt-card { padding: 20px 18px 6px; }
1865 .fd-vlt-card-meta { flex-direction: column; gap: 4px; }
1866 .fd-vlt-row { grid-template-columns: 40px 1fr auto; }
1867 .fd-vlt-row span:nth-child(3) { display: none; }
1868 .fd-vlt-caps-head { flex-direction: column; align-items: flex-start; }
1869 .fd-vlt-caps-stick { gap: 28px; }
1870 .fd-vlt-cap { min-height: min(460px, 62vh); }
1871 .fd-vlt-marquee { margin-top: 64px; }
1872}
1873@media (prefers-reduced-motion: reduce) {
1874 .fd-vlt *, .fd-vlt *::before, .fd-vlt *::after { animation: none !important; }
1875 .fd-vlt-odo-strip, .fd-vlt-seg-thumb, .fd-vlt-faq-a, .fd-vlt-card { transition-duration: 120ms !important; }
1876 .fd-vlt[data-js] [data-reveal] { transform: none; transition: opacity 120ms linear; transition-delay: 0ms; }
1877 .fd-vlt-card { transform: none; }
1878 .fd-vlt-plat { height: auto; padding: 96px 0; }
1879 .fd-vlt-plat-stick { position: relative; height: auto; }
1880 .fd-vlt-steps li { opacity: 1; }
1881 .fd-vlt-plat-bar { display: none; }
1882 .fd-vlt-caps { height: auto; padding: 96px 0; }
1883 .fd-vlt-caps-stick { position: relative; height: auto; }
1884 .fd-vlt-caps-track { transform: none; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 12px; }
1885 .fd-vlt-cap { scroll-snap-align: start; }
1886 .fd-vlt-caps-progress { display: none; }
1887 .fd-vlt-marquee-track { flex-wrap: wrap; width: auto; }
1888 .fd-vlt-marquee-row[data-dir="rev"] { display: none; }
1889}
1890@media (prefers-contrast: more) {
1891 .fd-vlt { --fd-vlt-mute: #3a3a40; --fd-vlt-line: rgba(11,11,12,0.35); --fd-vlt-mute-dark: #d4d4d8; }
1892 .fd-vlt-nav[data-condensed] { background: #fff; -webkit-backdrop-filter: none; backdrop-filter: none; }
1893}
1894@media (prefers-reduced-transparency: reduce) {
1895 .fd-vlt-nav[data-condensed], .fd-vlt-nav[data-open] { background: #fff; -webkit-backdrop-filter: none; backdrop-filter: none; }
1896}
1897`;