Setup Guide
One-time setup for using CONTOUR // 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 CONTOUR // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ─────────────────────────────────────────── */
--color-contour-midnight: #080B14;
--color-contour-midnight-up: #0D1120;
--color-contour-midnight-surface: #111628;
--color-contour-midnight-elevated: #161C32;
--color-contour-neon: #00E68A;
--color-contour-neon-dim: rgba(0, 230, 138, 0.6);
--color-contour-neon-faint: rgba(0, 230, 138, 0.13);
--color-contour-neon-glow: rgba(0, 230, 138, 0.27);
--color-contour-cream: #E8DCC8;
--color-contour-cream-muted: rgba(232, 220, 200, 0.6);
--color-contour-cream-faint: rgba(232, 220, 200, 0.2);
--color-contour-grid-line: rgba(232, 220, 200, 0.04);
--color-contour-warning: #FFB020;
--color-contour-error: #FF4D4D;
--color-contour-info: #3B82F6;
/* ── Fonts ───────────────────────────────────────────── */
--font-display: var(--font-space-grotesk);
--font-mono: var(--font-ibm-plex-mono);
/* ── Animations ──────────────────────────────────────── */
--animate-pulse-neon: pulse-neon 3s ease-in-out infinite;
--animate-grid-drift: grid-drift 20s linear 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-mono);
font-weight: 500;
letter-spacing: 0.12em;
text-transform: uppercase;
border: none;
cursor: pointer;
text-decoration: none;
line-height: 1;
white-space: nowrap;
transition: box-shadow 0.3s, transform 0.2s, border-color 0.3s, color 0.3s;
}
.btn-base:hover { text-decoration: none; }
.btn-sm { font-size: 11px; padding: 8px 16px; }
.btn-md { font-size: 12px; padding: 11px 22px; }
.btn-lg { font-size: 12px; padding: 14px 28px; }
.btn-primary {
background: var(--color-contour-neon);
color: var(--color-contour-midnight);
}
.btn-primary:hover {
box-shadow: 0 0 30px var(--color-contour-neon-glow);
transform: translateY(-1px);
color: var(--color-contour-midnight);
}
.btn-secondary {
background: transparent;
color: var(--color-contour-cream);
border: 1px solid var(--color-contour-cream-faint);
}
.btn-secondary:hover {
border-color: var(--color-contour-neon-dim);
color: var(--color-contour-neon);
}
.btn-ghost {
background: transparent;
color: var(--color-contour-cream-muted);
border: 1px solid var(--color-contour-cream-faint);
}
.btn-ghost:hover {
border-color: var(--color-contour-neon-dim);
color: var(--color-contour-neon);
}
/* ─── Responsive ─────────────────────────────────────── */
@media (max-width: 768px) {
.hero-section {
grid-template-columns: 1fr;
min-height: auto;
}
.hero-left {
padding: 100px 24px 60px;
border-right: none;
border-bottom: 1px solid var(--color-contour-grid-line);
}
.hero-left::after { left: 24px; }
.hero-right {
min-height: 400px;
padding: 40px 24px;
}
.hero-data-overlay { width: 100%; max-width: none; }
.hero-buttons { flex-direction: column; }
.btn-base.w-full-mobile { width: 100%; text-align: center; justify-content: center; }
.benchmark { padding: 16px 24px; }
.stats-strip { grid-template-columns: 1fr 1fr; }
.stat-cell { padding: 28px 24px; }
.stat-value { font-size: 28px; }
.features-section { padding: 60px 24px; }
.features-header { grid-template-columns: 1fr; gap: 20px; }
.features-grid { grid-template-columns: 1fr; }
.contour-card-wide { grid-column: span 1; }
.workflow-section { padding: 0 24px 60px; }
.workflow-steps { grid-template-columns: 1fr; gap: 40px; }
.workflow-steps::before { display: none; }
.terrain-inner { grid-template-columns: 1fr; gap: 40px; padding: 0 24px; }
.terrain-section { padding: 60px 0; }
.testimonials-section { padding: 60px 24px; }
.testimonials-grid { grid-template-columns: 1fr; }
.cta-section { padding: 80px 24px; }
.cta-actions { flex-direction: column; align-items: center; }
.footer-top { grid-template-columns: 1fr; gap: 40px; }
.footer-links { grid-template-columns: 1fr 1fr; }
}/* ─── Badges ─────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-family: var(--font-mono);
font-weight: 500;
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
padding: 3px 8px;
}
.badge--neon { background: rgba(0,230,138,0.1); color: var(--color-contour-neon); border: 1px solid rgba(0,230,138,0.25); }
.badge--cream { background: rgba(232,220,200,0.1); color: var(--color-contour-cream); border: 1px solid rgba(232,220,200,0.2); }
.badge--warning { background: rgba(255,176,32,0.1); color: var(--color-contour-warning); border: 1px solid rgba(255,176,32,0.25); }
.badge--error { background: rgba(255,77,77,0.1); color: var(--color-contour-error); border: 1px solid rgba(255,77,77,0.25); }
.badge--info { background: rgba(59,130,246,0.1); color: var(--color-contour-info); border: 1px solid rgba(59,130,246,0.25); }/* ─── Text Variants ──────────────────────────────────── */
.text-body { font-size: 15px; line-height: 1.8; color: var(--color-contour-cream-muted); }
.text-caption { font-family: var(--font-mono); font-size: 11px; color: var(--color-contour-cream-muted); letter-spacing: 0.05em; }
.text-label { font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; }
.text-code { font-family: var(--font-mono); font-size: 13px; color: var(--color-contour-neon); font-weight: 500; }/* ─── Features Section ───────────────────────────────── */
.contour-card {
background: var(--color-contour-midnight-up);
padding: 40px 32px;
border: 1px solid var(--color-contour-grid-line);
position: relative;
transition: border-color 0.3s;
}
.contour-card:hover {
border-color: var(--color-contour-neon-faint);
}
.contour-card-wide { grid-column: span 2; }
.feature-icon {
width: 36px;
height: 36px;
border: 1px solid var(--color-contour-neon-dim);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 24px;
font-family: var(--font-mono);
font-size: 14px;
color: var(--color-contour-neon);
}
.feature-tag {
position: absolute;
top: 16px;
right: 16px;
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--color-contour-neon-dim);
}
.card-title {
font-family: var(--font-display);
font-size: 18px;
font-weight: 500;
color: var(--color-contour-cream);
margin-bottom: 12px;
}
.card-description {
font-size: 14px;
line-height: 1.7;
color: var(--color-contour-cream-muted);
}
/* ─── Responsive ─────────────────────────────────────── */
@media (max-width: 768px) {
.hero-section {
grid-template-columns: 1fr;
min-height: auto;
}
.hero-left {
padding: 100px 24px 60px;
border-right: none;
border-bottom: 1px solid var(--color-contour-grid-line);
}
.hero-left::after { left: 24px; }
.hero-right {
min-height: 400px;
padding: 40px 24px;
}
.hero-data-overlay { width: 100%; max-width: none; }
.hero-buttons { flex-direction: column; }
.btn-base.w-full-mobile { width: 100%; text-align: center; justify-content: center; }
.benchmark { padding: 16px 24px; }
.stats-strip { grid-template-columns: 1fr 1fr; }
.stat-cell { padding: 28px 24px; }
.stat-value { font-size: 28px; }
.features-section { padding: 60px 24px; }
.features-header { grid-template-columns: 1fr; gap: 20px; }
.features-grid { grid-template-columns: 1fr; }
.contour-card-wide { grid-column: span 1; }
.workflow-section { padding: 0 24px 60px; }
.workflow-steps { grid-template-columns: 1fr; gap: 40px; }
.workflow-steps::before { display: none; }
.terrain-inner { grid-template-columns: 1fr; gap: 40px; padding: 0 24px; }
.terrain-section { padding: 60px 0; }
.testimonials-section { padding: 60px 24px; }
.testimonials-grid { grid-template-columns: 1fr; }
.cta-section { padding: 80px 24px; }
.cta-actions { flex-direction: column; align-items: center; }
.footer-top { grid-template-columns: 1fr; gap: 40px; }
.footer-links { grid-template-columns: 1fr 1fr; }
}Button
Dark topographic button with primary, secondary, and ghost variants in three sizes. Neon green accent on midnight navy. Renders as a Next.js Link when an href is provided.
Badge
Topographic badge with neon, cream, warning, error, and info variants. Monospace labels on dark surfaces.
Text
Polymorphic text component with body, caption, label, and code variants. IBM Plex Mono for labels and code, Space Grotesk for body.
Card
Data card with icon, tag badge, title, and description. Supports wide variant for featured layouts. Midnight navy surface with neon green accents.