Setup Guide
One-time setup for using VOW // NEXT components. Add these to your project, then copy any component from the theme.
The cn() utility combines clsx and tailwind-merge for conditional class names. Install both packages.
npm install clsx tailwind-mergeCreate lib/utils.ts with the cn() helper. Every component imports this for class name merging.
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]): string {
return twMerge(clsx(inputs))
}Add the VOW // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ─────────────────────────────────────────── */
--color-vow-ivory: #FDF6EE;
--color-vow-ivory-deep: #F5ECDF;
--color-vow-parchment: #EDE3D4;
--color-vow-burgundy: #7A2E3B;
--color-vow-burgundy-light: #9C4A58;
--color-vow-burgundy-faint: rgba(122, 46, 59, 0.08);
--color-vow-gold: #B29352;
--color-vow-gold-light: #C9AD6F;
--color-vow-gold-faint: rgba(178, 147, 82, 0.15);
--color-vow-sage: #8B9E7E;
--color-vow-sage-light: #A8B89D;
--color-vow-sage-faint: rgba(139, 158, 126, 0.12);
--color-vow-ink: #2E1F1F;
--color-vow-ink-soft: #5C4646;
--color-vow-ink-muted: #8A7272;
--color-vow-white: #FFFFFF;
/* ── Fonts ───────────────────────────────────────────── */
--font-display: var(--font-playfair);
--font-body: var(--font-karla);
/* ── Animations ──────────────────────────────────────── */
--animate-fade-up: fade-up 0.6s ease both;
--animate-gold-pulse: gold-pulse 3s ease-in-out infinite;
}Each component may need its own CSS classes in your globals.css. Copy the styles for the components you use.
/* ─── Buttons ────────────────────────────────────────── */
.btn-base {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
font-family: var(--font-body);
font-weight: 600;
border: none;
cursor: pointer;
text-decoration: none;
line-height: 1;
letter-spacing: 0.3em;
text-transform: uppercase;
transition: background 0.3s, color 0.3s, border-color 0.3s;
white-space: nowrap;
}
.btn-sm { font-size: 10px; padding: 12px 24px; }
.btn-md { font-size: 11px; padding: 16px 36px; }
.btn-lg { font-size: 11px; padding: 18px 48px; }
.btn-primary {
background: var(--color-vow-burgundy);
color: var(--color-vow-white);
}
.btn-primary:hover {
background: var(--color-vow-burgundy-light);
color: var(--color-vow-white);
}
.btn-secondary {
background: transparent;
color: var(--color-vow-burgundy);
border: 1px solid var(--color-vow-burgundy);
}
.btn-secondary:hover {
background: var(--color-vow-burgundy);
color: var(--color-vow-white);
}
.btn-ghost {
background: transparent;
color: var(--color-vow-ink-soft);
border: 1px solid var(--color-vow-parchment);
}
.btn-ghost:hover {
border-color: var(--color-vow-gold);
color: var(--color-vow-ink);
}/* ─── Badges ─────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-family: var(--font-body);
font-weight: 600;
font-size: 10px;
letter-spacing: 0.2em;
text-transform: uppercase;
padding: 6px 14px;
border: 1px solid transparent;
}
.badge--burgundy { color: var(--color-vow-burgundy); border-color: var(--color-vow-burgundy-light); background: var(--color-vow-burgundy-faint); }
.badge--gold { color: var(--color-vow-gold); border-color: var(--color-vow-gold-light); background: var(--color-vow-gold-faint); }
.badge--sage { color: var(--color-vow-sage); border-color: var(--color-vow-sage-light); background: var(--color-vow-sage-faint); }
.badge--ink { color: var(--color-vow-ink-soft); border-color: var(--color-vow-parchment); background: rgba(46, 31, 31, 0.04); }
.badge--ivory { color: var(--color-vow-ink-muted); border-color: var(--color-vow-parchment); background: var(--color-vow-ivory-deep); }/* ─── Text Variants ──────────────────────────────────── */
.text-body { font-size: 15px; line-height: 1.8; font-weight: 400; color: var(--color-vow-ink-soft); }
.text-caption { font-size: 13px; font-weight: 500; color: var(--color-vow-ink-muted); }
.text-label { font-size: 11px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; }
.text-code { font-family: monospace; font-size: 14px; color: var(--color-vow-burgundy); }/* ─── Services Section ───────────────────────────────── */
.vow-card {
padding: 48px 40px;
border: 1px solid var(--color-vow-parchment);
position: relative;
transition: border-color 0.4s;
}
.vow-card:hover { border-color: var(--color-vow-gold-light); }
.vow-card:nth-child(2) { margin-top: 60px; }
.vow-card:nth-child(3) { margin-top: -30px; }
.card-number {
font-family: var(--font-display);
font-size: 64px;
font-weight: 400;
color: var(--color-vow-burgundy-faint);
line-height: 1;
margin-bottom: 24px;
letter-spacing: -0.03em;
}
.vow-card:hover .card-number { color: var(--color-vow-gold-faint); }
.card-title {
font-family: var(--font-display);
font-size: 26px;
font-weight: 400;
color: var(--color-vow-ink);
margin-bottom: 16px;
line-height: 1.2;
}
.card-description {
font-size: 14px;
line-height: 1.8;
color: var(--color-vow-ink-muted);
max-width: 320px;
}
.card-tag {
display: inline-block;
margin-top: 24px;
font-family: var(--font-body);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--color-vow-sage);
padding: 6px 14px;
border: 1px solid var(--color-vow-sage-light);
}
@media (max-width: 768px) {
.services-section { padding: 80px 24px; }
.services-header {
flex-direction: column;
align-items: flex-start;
margin-bottom: 48px;
}
.services-intro { text-align: left; max-width: 100%; }
.services-grid { grid-template-columns: 1fr; }
.vow-card:nth-child(2),
.vow-card:nth-child(3) { margin-top: 0; }
}Button
Elegant button with primary, secondary, and ghost variants in three sizes. Burgundy accent, serif labels, refined spacing. Renders as a Next.js Link when an href is provided.
Badge
Refined badge with burgundy, gold, sage, ink, and ivory variants. Delicate uppercase tracking for floral and event contexts.
Text
Polymorphic text component with body, caption, label, and code variants. Serif display for headings, clean sans for body.
Card
Service card with numbered index, title, description, and tag. Clean lines and refined spacing for floral atelier services.