.card
Default container. Rounded-2xl, border-border-light, shadow-soft, hovers to shadow-card. Wraps grid items, list items, anything that needs a visible edge.
Logo
The wordmark is the primary brand surface. Use the icon-only variant when space is tight; the horizontal lockup everywhere else.
Palette · layer 1
Hex CSS vars under --color-{name}-{stop}. Theme-independent — these are the same color in light and dark mode. Use scale stops directly (e.g. text-primary-900) when you need a specific shade; reach for the semantic surface tokens (next section) when you want something that flips with the theme.
Default text. Inverse surfaces. The authority register.
Default text. Inverse surfaces. The authority register.
Motion spark. CTAs. Focus rings. The brand color.
Motion spark. CTAs. Focus rings. The brand color.
Pricing emphasis, secondary CTAs. Used sparingly.
Pricing emphasis, secondary CTAs. Used sparingly.
Borders, dividers, fills with no brand weight.
Borders, dividers, fills with no brand weight.
Palette · layer 2
Hex CSS vars under --color-{bg|text|border}-*. Flip on [data-theme="dark"]. Component code never branches on theme — it always uses the named token, and the var resolves to the right hex per theme. Toggle the theme above and the swatches below all retune.
bg-primary
--color-bg-primary
Page surface. White / #0e1014.
bg-secondary
--color-bg-secondary
Card surface, sticky header tint.
bg-tertiary
--color-bg-tertiary
Hover states, nested panels.
bg-inverse
--color-bg-inverse
Inverted pill / badge surface.
Text
Borders
Elevation
The Tailwind tokens shadow-{soft,card,lift,glow} resolve through CSS vars in globals.css, so dark mode automatically re-tunes them with deeper rgba so cards still lift off the surface. Toggle the theme to confirm — the shadow under each card visibly changes.
shadow-soft
--shadow-soft
baseline card lift
shadow-card
--shadow-card
card on hover
shadow-lift
--shadow-lift
modal / overlay
shadow-glow
--shadow-glow
focus / featured CTA
Backgrounds
bg-hero-grid is the only branded gradient in the system. It layers two radial glows (emerald top-left, amber bottom-right) over the bg-primary → bg-secondary base. Dark mode bumps the emerald to 12% and the amber to 8% so the page doesn't read as a flat slab of black.
bg-hero-grid
--gradient-hero-grid · light / dark variants in globals.css
Typography
The system ships three named scales: h-display (the hero h1), h-section (page h2), and eyebrow (the small uppercase accent above headings). Body text isn't a named utility — compose it with text-* + leading-relaxed and the text-secondary token.
How it works
Drop your illustration pack, type a prompt, get a broadcast-ready MP4 and editable Lottie in 90 seconds. Iteration thereafter is sub-second.
Same engine across all three tiers. The difference is who runs it.
Used by brand, growth and product teams that would rather ship than wait on an agency.
v0.1.0 · local-first · cloud-optional
Chrome
The three named container classes. Reach for them before composing new ones.
Default container. Rounded-2xl, border-border-light, shadow-soft, hovers to shadow-card. Wraps grid items, list items, anything that needs a visible edge.
Tiny pill — status, count, label. Override the border / bg utility classes inline when you need a semantic tint.
Vertical rhythm. Two tiers — the standard section is the default, the tight one for short stat rows or proof bars.
Actions
The whole site uses these three classes. btn-primary is the ink-on-light authoritative CTA; btn-accent is the emerald spark for the brand action; btn-ghost is the bordered tertiary.
.btn-primary
Authority. The primary CTA on most surfaces — deep ink reads as the most serious choice.
.btn-accent
The brand spark. Use for the one action you want the eye to land on first (top tier on /pricing, the generate button).
.btn-ghost
Tertiary. Pairs with btn-primary or btn-accent — don't use two of these next to each other.
Motion
Motion always communicates state. It never decorates. The system enforces this with named easing/duration tokens — never inline cubic-bezier or arbitrary ms values.
60%
--ease-out-quart
Workhorse. Fast start, gentle landing. Use for hover, focus, reveal, enter — anything responding to user input.
30%
--ease-snap
Snap. Near-instant with a hairline tail. Toggles, checkboxes, tab switches — anything that should feel decisive.
10%
--ease-in-quart
Exit. Slow start, fast finish. Drawer close, toast dismiss — conveys departure.
Spring (--ease-spring) is reserved for one moment per session (the generate-success punctuation). Linear (--ease-linear) is for indeterminate progress only — skeleton shimmer, spinner.
Motion · tokens
Every token below is exposed to Tailwind too (duration-base, ease-out-quart, etc.) so you rarely need to reach for arbitrary values.
| Token | Value | Use |
|---|---|---|
| --dur-instant | 90ms | press, color shift |
| --dur-fast | 180ms | hover, focus ring, chip toggle |
| --dur-base | 240ms | drawer slide, panel reveal (default) |
| --dur-slow | 320ms | preview reveal, large surface entry |
| --dur-stagger | 30ms | × index for sibling sequences |
| Token | Value | Use |
|---|---|---|
| --ease-out-quart | 0.2 0.8 0.2 1 | 60% — workhorse |
| --ease-snap | 0.12 0 0.08 1 | 30% — toggles |
| --ease-in-quart | 0.55 0 0.85 0.3 | 10% — exits |
| --ease-spring | 0.34 1.56 0.64 1 | once per session |
| --ease-linear | linear | indeterminate progress only |
Two more delay tokens worth knowing: --delay-loader-show (200ms) is how long to wait before showing a spinner so fast responses don't flash one, and --delay-loader-min (400ms) is how long to keep a visible loader so it doesn't jitter.
Motion · utilities
Each utility binds a transition to a named token pair so you stay inside the design system. Hover the demos to see them fire — toggle to dark to confirm they hold up.
.motion-hover
Background, border, color, shadow on hover. The default.
.motion-press
Instant scale on active. Pairs with motion-hover for buttons.
.motion-reveal
Transform + opacity. For elements that enter the viewport.
.motion-snap
Tabs, segmented controls. Snappy.
.motion-drawer
Side drawer slide. Transform only, base duration.
.motion-exit
Exit transition — slow start, fast finish.
Motion · keyframes
A tight catalog. Skeleton shimmer + mic-listening pulse + toast in/out are the only ones the production app ships.
.animate-skeleton-shimmer
The only background animation we ship. Linear-easing — it's indeterminate progress.
.animate-pulse-accent
Mic-listening ring. Subtle accent expansion — never a color flash.
.animate-toast-in / -out
Toast enter (base, out-quart) and dismiss (fast, in-quart).
loader pattern
--delay-loader-show 200ms before spinner, --delay-loader-min 400ms once visible. Demo spins on click.
.stagger-child
Set style={{ '--i': index }} on each child to space sibling animations by --dur-stagger.
transition-transform
duration-fast ease-out-quartTailwind escape hatch
When you really need a one-off, use the duration-* / ease-* tokens — never raw ms / cubic-bezier.
When in doubt
bg-bg-*, text-text-*, border-border-* token.bg-primary-900).focus-visible:ring-accent-500; :focus-visible is already handled at the base layer..motion-hover..motion-snap..motion-reveal..motion-drawer..motion-exit.