Calm Clinic Hero

Warm and unhurried: a breathing gradient orb, an appointment stack that fans out, and quiet trust stats.

  • Heroes
  • Healthcare
  • React only · 0 deps
  • 1 file
Full screen

Install. One command, or copy the file.

$npx shadcn@latest add https://freedesignmd.com/r/hero-health-calm.json
  • Byte-identical to the preview
  • No Tailwind or config needed
  • SSR-safe · keyboard accessible
  • Respects reduced motion & transparency
components/heroes/hero-health-calm.tsx
1/**
2 * HeroHealthCalm — a warm, unhurried hero for a digital clinic. A breathing
3 * gradient orb (6s inhale / exhale) sits behind a stack of appointment cards
4 * that fans out on load and gently re-stacks as the section scrolls away.
5 * The pointer lifts the hovered card; trust stats sit below the headline.
6 *
7 * Props: title, lede, primaryCta, secondaryCta, appointments
8 * ({ who, role, when, kind, tone }[]), stats ({ value, label }[]).
9 * CSS vars: --fd-clm-paper, --fd-clm-ink, --fd-clm-accent, --fd-clm-orb-a/b/c.
10 *
11 * Browser support: all evergreen browsers.
12 * Motion: long, low-amplitude CSS loops (breathing), CSS fan-out entrance,
13 * pointer parallax on a soft spring, scroll re-stack via rAF +
14 * getBoundingClientRect (transform only, paused off-screen).
15 * prefers-reduced-motion: cards rest fanned, orb is still.
16 * Accessibility: the card stack is a list with readable text; the orb is
17 * decorative.
18 */
19import { useEffect, useRef } from "react";
20import type { ReactNode } from "react";
21
22export type Appointment = { who: string; role: string; when: string; kind: string; tone: "sage" | "peach" | "sky" };
23export type CalmStat = { value: string; label: string };
24
25export interface HeroHealthCalmProps {
26 eyebrow?: ReactNode;
27 title?: ReactNode;
28 lede?: ReactNode;
29 primaryCta?: { label: string; href: string };
30 secondaryCta?: { label: string; href: string };
31 appointments?: Appointment[];
32 stats?: CalmStat[];
33}
34
35const DEFAULT_APPTS: Appointment[] = [
36 { who: "Dr. Leila Haddad", role: "General practice", when: "Today · 4:30 pm", kind: "Video visit · 20 min", tone: "sage" },
37 { who: "Sam Whitlock, RD", role: "Nutrition", when: "Thu 14 Nov · 9:00 am", kind: "Follow-up · 30 min", tone: "peach" },
38 { who: "Dr. Mateo Ruiz", role: "Dermatology", when: "Mon 18 Nov · 11:15 am", kind: "Photo review · async", tone: "sky" },
39];
40
41const DEFAULT_STATS: CalmStat[] = [
42 { value: "11 min", label: "median wait for a same-day visit" },
43 { value: "4.9", label: "average rating from 62,000 patients" },
44 { value: "HSA/FSA", label: "eligible · most insurers accepted" },
45];
46
47export function HeroHealthCalm({
48 eyebrow = "Primary care, membership included",
49 title = (
50 <>
51 A doctor who knows you,
52 <br />
53 <em>whenever you need one.</em>
54 </>
55 ),
56 lede = "Same-day video visits, a care team that answers within the hour, and prescriptions sent to your pharmacy before you’ve put the kettle on.",
57 primaryCta = { label: "Book your first visit", href: "#book" },
58 secondaryCta = { label: "Check your coverage", href: "#coverage" },
59 appointments = DEFAULT_APPTS,
60 stats = DEFAULT_STATS,
61}: HeroHealthCalmProps) {
62 const root = useRef<HTMLElement>(null);
63 const stack = useRef<HTMLOListElement>(null);
64 const orb = useRef<HTMLDivElement>(null);
65
66 useEffect(() => {
67 const el = root.current;
68 if (!el || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
69 const sp = { x: 0, y: 0, tx: 0, ty: 0 };
70 const onMove = (e: PointerEvent) => {
71 if (e.pointerType === "touch") return;
72 const r = el.getBoundingClientRect();
73 sp.tx = ((e.clientX - r.left) / r.width) * 2 - 1;
74 sp.ty = ((e.clientY - r.top) / r.height) * 2 - 1;
75 };
76 el.addEventListener("pointermove", onMove);
77 let raf = 0;
78 let visible = true;
79 const frame = () => {
80 raf = 0;
81 sp.x += (sp.tx - sp.x) * 0.045;
82 sp.y += (sp.ty - sp.y) * 0.045;
83 const r = el.getBoundingClientRect();
84 const p = Math.min(1, Math.max(0, -r.top / Math.max(1, r.height * 0.7)));
85 if (stack.current) {
86 stack.current.style.setProperty("--fan", (1 - p).toFixed(4));
87 stack.current.style.transform = `translate3d(${(sp.x * 10).toFixed(2)}px, ${(sp.y * 8 + p * -40).toFixed(2)}px, 0) rotateX(${(-sp.y * 4).toFixed(2)}deg) rotateY(${(sp.x * 6).toFixed(2)}deg)`;
88 }
89 if (orb.current) orb.current.style.transform = `translate3d(${(sp.x * -24).toFixed(2)}px, ${(sp.y * -18 + p * 80).toFixed(2)}px, 0) scale(${(1 + p * 0.25).toFixed(4)})`;
90 if (visible && !document.hidden) raf = requestAnimationFrame(frame);
91 };
92 const start = () => {
93 if (!raf && visible && !document.hidden) raf = requestAnimationFrame(frame);
94 };
95 const io = new IntersectionObserver(([e]) => {
96 visible = e.isIntersecting;
97 if (visible) start();
98 });
99 io.observe(el);
100 document.addEventListener("visibilitychange", start);
101 start();
102 return () => {
103 cancelAnimationFrame(raf);
104 io.disconnect();
105 document.removeEventListener("visibilitychange", start);
106 el.removeEventListener("pointermove", onMove);
107 };
108 }, []);
109
110 return (
111 <section ref={root} className="fd-clm" aria-label="Tend Health">
112 <style>{css}</style>
113 <div className="fd-clm-grid">
114 <div className="fd-clm-copy">
115 <p className="fd-clm-eyebrow">
116 <span className="fd-clm-pulse" aria-hidden="true" />
117 {eyebrow}
118 </p>
119 <h1 className="fd-clm-h1">{title}</h1>
120 <p className="fd-clm-lede">{lede}</p>
121 <div className="fd-clm-ctas">
122 <a className="fd-clm-btn" href={primaryCta.href}>
123 {primaryCta.label}
124 </a>
125 <a className="fd-clm-link" href={secondaryCta.href}>
126 {secondaryCta.label}
127 <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
128 <path d="M3 8h9M8.5 4.5 12 8l-3.5 3.5" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
129 </svg>
130 </a>
131 </div>
132 <dl className="fd-clm-stats">
133 {stats.map((s) => (
134 <div key={s.label}>
135 <dt>{s.label}</dt>
136 <dd>{s.value}</dd>
137 </div>
138 ))}
139 </dl>
140 </div>
141
142 <div className="fd-clm-visual">
143 <div ref={orb} className="fd-clm-orbwrap" aria-hidden="true">
144 <div className="fd-clm-orb" />
145 <div className="fd-clm-ring" />
146 <div className="fd-clm-ring fd-clm-ring-2" />
147 </div>
148 <ol ref={stack} className="fd-clm-stack" aria-label="Upcoming appointments">
149 {appointments.map((a, i) => (
150 <li key={a.who} className={`fd-clm-card fd-clm-${a.tone}`} style={{ ["--i" as string]: i, ["--fy" as string]: `${[0, 206, 334][i] ?? i * 128}px` }}>
151 <div className="fd-clm-card-top">
152 <span className="fd-clm-av" aria-hidden="true">
153 {a.who.replace(/^Dr\. /, "").split(" ").map((w) => w[0]).slice(0, 2).join("")}
154 </span>
155 <div className="fd-clm-who">
156 <b>{a.who}</b>
157 <span>{a.role}</span>
158 </div>
159 {i === 0 && <span className="fd-clm-live">Ready</span>}
160 </div>
161 <div className="fd-clm-card-bot">
162 <span className="fd-clm-when">
163 <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
164 <circle cx="8" cy="8" r="6.2" fill="none" stroke="currentColor" strokeWidth="1.3" />
165 <path d="M8 4.8V8l2.2 1.4" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" />
166 </svg>
167 {a.when}
168 </span>
169 <span className="fd-clm-kind">{a.kind}</span>
170 </div>
171 {i === 0 && (
172 <div className="fd-clm-join">
173 <span>Join waiting room</span>
174 <span className="fd-clm-dots" aria-hidden="true">
175 <i /><i /><i />
176 </span>
177 </div>
178 )}
179 </li>
180 ))}
181 </ol>
182 </div>
183 </div>
184 </section>
185 );
186}
187
188const css = `
189.fd-clm, .fd-clm *, .fd-clm *::before, .fd-clm *::after { box-sizing: border-box; }
190.fd-clm {
191 --fd-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
192 --fd-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
193 --fd-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
194 --fd-dur-1: 120ms; --fd-dur-2: 240ms; --fd-dur-3: 420ms; --fd-dur-4: 700ms;
195 --fd-clm-paper: #FBF7F1;
196 --fd-clm-ink: #1F2A24;
197 --fd-clm-muted: #66706A;
198 --fd-clm-accent: #2F5D4A;
199 --fd-clm-orb-a: #F6C8A8;
200 --fd-clm-orb-b: #CFE3D2;
201 --fd-clm-orb-c: #F3E2B8;
202 --fd-clm-serif: ui-serif, "New York", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
203 --fd-clm-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", Roboto, sans-serif;
204 position: relative; display: block; overflow: hidden; margin: 0; padding: 0; min-height: 860px;
205 background: var(--fd-clm-paper); color: var(--fd-clm-ink); font: 400 1rem/1.5 var(--fd-clm-sans);
206 isolation: isolate;
207}
208.fd-clm-grid {
209 position: relative; max-width: 1240px; min-height: 860px; margin: 0 auto; padding: 132px 48px 72px;
210 display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 48px; align-items: center;
211}
212.fd-clm-eyebrow {
213 display: inline-flex; align-items: center; gap: 10px; margin: 0 0 26px; padding: 0;
214 font: 500 0.875rem/1 var(--fd-clm-sans); letter-spacing: -0.005em; color: var(--fd-clm-accent);
215 animation: fd-clm-rise 1100ms var(--fd-ease-out) 100ms both;
216}
217.fd-clm-pulse { position: relative; display: block; width: 8px; height: 8px; border-radius: 9999px; background: #5FA37F; }
218.fd-clm-pulse::after { content: ""; position: absolute; inset: -5px; border-radius: 9999px; border: 1px solid #5FA37F; animation: fd-clm-ping 3s var(--fd-ease-out) infinite; }
219.fd-clm-h1 {
220 margin: 0; padding: 0; color: var(--fd-clm-ink);
221 font: 400 clamp(2.5rem, 4.6vw, 4.125rem)/1.02 var(--fd-clm-serif); letter-spacing: -0.03em; text-wrap: balance;
222 animation: fd-clm-soft 1600ms var(--fd-ease-out) 200ms both;
223}
224.fd-clm-h1 em { font-style: italic; color: var(--fd-clm-accent); }
225.fd-clm-lede {
226 margin: 26px 0 0; padding: 0; max-width: 30rem; color: var(--fd-clm-muted);
227 font: 400 clamp(1.0625rem, 1.2vw, 1.1875rem)/1.6 var(--fd-clm-sans); letter-spacing: -0.008em; text-wrap: pretty;
228 animation: fd-clm-rise 1100ms var(--fd-ease-out) 450ms both;
229}
230.fd-clm-ctas { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; margin: 36px 0 0; animation: fd-clm-rise 1100ms var(--fd-ease-out) 600ms both; }
231.fd-clm-btn {
232 display: inline-flex; align-items: center; margin: 0; height: 54px; padding: 0 28px; border-radius: 9999px; border: 0;
233 background: var(--fd-clm-accent); color: #FBF7F1; text-decoration: none; font: 500 1rem/1 var(--fd-clm-sans); letter-spacing: -0.01em;
234 box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 14px 30px -14px rgba(47,93,74,0.7);
235 transition: transform var(--fd-dur-2) var(--fd-spring), background var(--fd-dur-2) var(--fd-ease-out);
236}
237.fd-clm-btn:hover { background: #274E3E; }
238.fd-clm-btn:active { transform: scale(0.96); transition-duration: var(--fd-dur-1); }
239.fd-clm-link { display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 0; color: var(--fd-clm-ink); text-decoration: none; font: 500 1rem/1 var(--fd-clm-sans); letter-spacing: -0.01em; }
240.fd-clm-link svg { display: block; transition: transform var(--fd-dur-3) var(--fd-ease-out); }
241.fd-clm-link:hover svg { transform: translateX(4px); }
242.fd-clm-btn:focus-visible, .fd-clm-link:focus-visible { outline: 2px solid rgba(47,93,74,0.7); outline-offset: 3px; }
243.fd-clm-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; margin: 56px 0 0; padding: 24px 0 0; border-top: 1px solid rgba(31,42,36,0.1); animation: fd-clm-rise 1100ms var(--fd-ease-out) 750ms both; }
244.fd-clm-stats div { display: flex; flex-direction: column-reverse; justify-content: flex-end; margin: 0; }
245.fd-clm-stats dd { margin: 0 0 6px; padding: 0; font: 400 1.75rem/1 var(--fd-clm-serif); letter-spacing: -0.02em; color: var(--fd-clm-ink); }
246.fd-clm-stats dt { margin: 0; padding: 0; font: 400 0.8125rem/1.4 var(--fd-clm-sans); color: var(--fd-clm-muted); }
247
248.fd-clm-visual { position: relative; height: 560px; display: grid; place-items: center; perspective: 1400px; }
249.fd-clm-orbwrap { position: absolute; inset: 0; display: grid; place-items: center; will-change: transform; }
250.fd-clm-orb {
251 width: 470px; height: 470px; border-radius: 50%;
252 background:
253 radial-gradient(40% 40% at 30% 30%, var(--fd-clm-orb-c), transparent 70%),
254 radial-gradient(50% 50% at 70% 35%, var(--fd-clm-orb-a), transparent 72%),
255 radial-gradient(60% 60% at 45% 75%, var(--fd-clm-orb-b), transparent 75%),
256 radial-gradient(closest-side, #F7DCC6, #FBF7F1);
257 filter: blur(26px) saturate(1.1);
258 animation: fd-clm-in 2000ms var(--fd-ease-out) both, fd-clm-breathe 12s var(--fd-ease-in-out) 2s infinite;
259}
260.fd-clm-ring { position: absolute; width: 520px; height: 520px; border-radius: 50%; border: 1px solid rgba(47,93,74,0.12); animation: fd-clm-breathe 12s var(--fd-ease-in-out) 2.4s infinite, fd-clm-fade 2000ms var(--fd-ease-out) 400ms both; }
261.fd-clm-ring-2 { width: 640px; height: 640px; border-color: rgba(47,93,74,0.07); animation-delay: 2.8s, 600ms; }
262
263.fd-clm-stack { --fan: 1; position: relative; width: 380px; height: 460px; margin: 0; padding: 0; list-style: none; transform-style: preserve-3d; will-change: transform; }
264.fd-clm-card {
265 --y: calc(var(--i) * 16px * (1 - var(--fan)) + var(--fy) * var(--fan));
266 --r: calc((var(--i) - 1) * var(--fan) * 2.5deg);
267 --s: calc(1 - var(--i) * 0.05 * (1 - var(--fan)));
268 position: absolute; left: 0; right: 0; top: 0; margin: 0; padding: 18px 18px 16px;
269 border-radius: 24px; background: rgba(255,255,255,0.86); border: 1px solid rgba(255,255,255,0.9);
270 box-shadow: 0 1px 0 #fff inset, 0 24px 48px -24px rgba(70, 52, 30, 0.28), 0 0 0 1px rgba(31,42,36,0.05);
271 -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
272 z-index: calc(10 - var(--i));
273 transform: translate3d(calc((var(--i) - 1) * var(--fan) * 22px), var(--y), calc(var(--i) * -30px)) rotate(var(--r)) scale(var(--s));
274 animation: fd-clm-deal 1400ms var(--fd-ease-out) both; animation-delay: calc(600ms + var(--i) * 180ms);
275 transition: box-shadow var(--fd-dur-3) var(--fd-ease-out);
276}
277.fd-clm-card:hover { box-shadow: 0 1px 0 #fff inset, 0 34px 60px -24px rgba(70, 52, 30, 0.38), 0 0 0 1px rgba(31,42,36,0.08); }
278.fd-clm-card-top { display: flex; align-items: center; gap: 12px; }
279.fd-clm-av { display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: 9999px; font: 500 0.9375rem/1 var(--fd-clm-serif); color: var(--fd-clm-ink); }
280.fd-clm-sage .fd-clm-av { background: linear-gradient(135deg, #DCEBDD, #B9D5C0); }
281.fd-clm-peach .fd-clm-av { background: linear-gradient(135deg, #FBE1CF, #F2C3A4); }
282.fd-clm-sky .fd-clm-av { background: linear-gradient(135deg, #DDE9F4, #BCD2E8); }
283.fd-clm-who { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
284.fd-clm-who b { font: 600 0.9375rem/1.2 var(--fd-clm-sans); letter-spacing: -0.01em; color: var(--fd-clm-ink); }
285.fd-clm-who span { font: 400 0.8125rem/1.2 var(--fd-clm-sans); color: var(--fd-clm-muted); }
286.fd-clm-live { margin-left: auto; padding: 5px 10px; border-radius: 9999px; background: #E3F1E7; color: #2F6B4D; font: 600 0.6875rem/1 var(--fd-clm-sans); letter-spacing: 0.02em; }
287.fd-clm-card-bot { display: flex; justify-content: space-between; gap: 12px; margin: 16px 0 0; padding: 14px 0 0; border-top: 1px dashed rgba(31,42,36,0.12); }
288.fd-clm-when { display: inline-flex; align-items: center; gap: 6px; font: 500 0.8125rem/1 var(--fd-clm-sans); color: var(--fd-clm-ink); }
289.fd-clm-when svg { display: block; color: var(--fd-clm-muted); }
290.fd-clm-kind { font: 400 0.8125rem/1 var(--fd-clm-sans); color: var(--fd-clm-muted); }
291.fd-clm-join { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 0; padding: 12px 16px; border-radius: 14px; background: var(--fd-clm-accent); color: #FBF7F1; font: 500 0.875rem/1 var(--fd-clm-sans); }
292.fd-clm-dots { display: inline-flex; gap: 4px; }
293.fd-clm-dots i { display: block; width: 5px; height: 5px; border-radius: 9999px; background: currentColor; opacity: 0.4; animation: fd-clm-dot 1.8s var(--fd-ease-in-out) infinite; }
294.fd-clm-dots i:nth-child(2) { animation-delay: 0.2s; } .fd-clm-dots i:nth-child(3) { animation-delay: 0.4s; }
295
296@keyframes fd-clm-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
297@keyframes fd-clm-soft { from { opacity: 0; filter: blur(10px); } to { opacity: 1; filter: none; } }
298@keyframes fd-clm-fade { from { opacity: 0; } to { opacity: 1; } }
299@keyframes fd-clm-in { from { opacity: 0; transform: scale(0.7); } to { opacity: 1; transform: none; } }
300@keyframes fd-clm-breathe { 0%, 100% { transform: scale(0.94); } 50% { transform: scale(1.06); } }
301@keyframes fd-clm-ping { 0% { transform: scale(0.6); opacity: 0.8; } 80%, 100% { transform: scale(1.6); opacity: 0; } }
302@keyframes fd-clm-dot { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
303@keyframes fd-clm-deal { from { opacity: 0; transform: translate3d(0, 60px, -80px) rotate(0deg) scale(0.92); } to { opacity: 1; } }
304
305@media (max-width: 900px) {
306 .fd-clm { min-height: 844px; }
307 .fd-clm-grid { grid-template-columns: 1fr; gap: 12px; padding: 104px 20px 48px; min-height: 844px; }
308 .fd-clm-visual { height: 500px; order: 2; }
309 .fd-clm-orb { width: 340px; height: 340px; }
310 .fd-clm-ring { width: 380px; height: 380px; } .fd-clm-ring-2 { width: 460px; height: 460px; }
311 .fd-clm-stack { width: min(340px, 100%); }
312 .fd-clm-stack { height: 400px; }
313 .fd-clm-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-top: 36px; }
314 .fd-clm-stats dd { font-size: 1.25rem; }
315 .fd-clm-stats dt { font-size: 0.75rem; }
316}
317@media (prefers-reduced-motion: reduce) { .fd-clm *, .fd-clm *::before, .fd-clm *::after { animation: none !important; } }
318@media (prefers-reduced-transparency: reduce) { .fd-clm-card { background: #fff; -webkit-backdrop-filter: none; backdrop-filter: none; } }
319`;
320
321/* ───────────────────────── Demo ───────────────────────── */
322
323export function Demo() {
324 return (
325 <div className="fd-clm-demo">
326 <style>{demoCss}</style>
327 <header className="fd-clm-demo-nav">
328 <a className="fd-clm-demo-logo" href="#top">
329 <svg viewBox="0 0 22 22" width="22" height="22" aria-hidden="true">
330 <path d="M11 3c3 3.2 6 6 6 9.4A6 6 0 0 1 11 18.6a6 6 0 0 1-6-6.2C5 9 8 6.2 11 3Z" fill="#2F5D4A" />
331 <path d="M11 9v6M8 12h6" stroke="#FBF7F1" strokeWidth="1.6" strokeLinecap="round" />
332 </svg>
333 tend
334 </a>
335 <nav aria-label="Primary">
336 <a href="#care">Care</a>
337 <a href="#membership">Membership</a>
338 <a href="#employers">For employers</a>
339 <a href="#clinicians">Our clinicians</a>
340 </nav>
341 <div className="fd-clm-demo-r">
342 <a href="#login">Log in</a>
343 <a className="fd-clm-demo-cta" href="#join">Join for $19/mo</a>
344 </div>
345 </header>
346 <HeroHealthCalm />
347 </div>
348 );
349}
350
351const demoCss = `
352.fd-clm-demo { position: relative; margin: 0; padding: 0; min-height: 100vh; background: #FBF7F1; }
353.fd-clm-demo *, .fd-clm-demo *::before, .fd-clm-demo *::after { box-sizing: border-box; }
354.fd-clm-demo-nav {
355 position: absolute; z-index: 10; top: 0; left: 0; right: 0; max-width: 1240px; height: 80px; margin: 0 auto; padding: 0 48px;
356 display: flex; align-items: center; justify-content: space-between; gap: 20px;
357 animation: fd-clm-demo-in 1200ms cubic-bezier(0.22, 1, 0.36, 1) both;
358}
359.fd-clm-demo-nav .fd-clm-demo-logo { display: inline-flex; align-items: center; gap: 8px; margin: 0; color: #1F2A24; text-decoration: none; font: 500 1.5rem/1 ui-serif, "New York", "Iowan Old Style", Georgia, serif; letter-spacing: -0.03em; }
360.fd-clm-demo-logo svg { display: block; }
361.fd-clm-demo-nav nav { display: flex; gap: 32px; }
362.fd-clm-demo-nav a { color: #48524C; text-decoration: none; font: 500 0.9375rem/1 ui-sans-serif, -apple-system, "Inter", sans-serif; letter-spacing: -0.01em; }
363.fd-clm-demo-r { display: flex; align-items: center; gap: 22px; }
364.fd-clm-demo-r .fd-clm-demo-cta { display: inline-flex; align-items: center; height: 40px; padding: 0 18px; border-radius: 9999px; background: #fff; color: #1F2A24; box-shadow: 0 0 0 1px rgba(31,42,36,0.1), 0 4px 12px -6px rgba(70,52,30,0.25); }
365.fd-clm-demo-nav a:focus-visible { outline: 2px solid rgba(47,93,74,.7); outline-offset: 2px; border-radius: 8px; }
366@keyframes fd-clm-demo-in { from { opacity: 0; } to { opacity: 1; } }
367@media (max-width: 900px) { .fd-clm-demo-nav { padding: 0 20px; height: 68px; } .fd-clm-demo-nav nav, .fd-clm-demo-r a:not(.fd-clm-demo-cta) { display: none; } }
368@media (prefers-reduced-motion: reduce) { .fd-clm-demo-nav { animation: none; } }
369`;

More Heroes. Same file contract.

Ledger Card Hero

A photoreal CSS-3D metal card that tilts to the cursor, then flips and docks on scroll while spend stats count up.

Agent Terminal Hero

A terminal types a prompt and streams an agent's plan while the generated dashboard assembles itself beside it.

Maison Editorial Hero

A giant serif masthead and procedural duotone fabric frames revealed by clip-path wipes, drifting apart on scroll.