Setup Guide
One-time setup for using SOLAR // STUDIO 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 SOLAR // STUDIO design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ──────────────────────────────────────────── */
--color-solar-bg: #1C1208;
--color-solar-bg-alt: #201408;
--color-solar-bg-deep: #261A0A;
--color-solar-bg-raise: #2E2010;
--color-solar-bg-footer: #161008;
--color-solar-yellow: #F5C518;
--color-solar-yellow-dark: #D4A800;
--color-solar-coral: #FF6B4A;
--color-solar-coral-dark: #E5502E;
--color-solar-sky: #5BB8F5;
--color-solar-sky-dark: #2A96D8;
--color-solar-text: #F5EFE0;
--color-solar-muted: #A8947E;
--color-solar-faint: rgba(245, 239, 224, 0.35);
/* ── Fonts ───────────────────────────────────────────── */
--font-display: var(--font-plus-jakarta-sans);
--font-body: var(--font-dm-sans);
/* ── Animations ──────────────────────────────────────── */
--animate-pulse-dot: pulse-dot 2.4s ease-in-out infinite;
--animate-spin-cw: spin-cw 28s linear infinite;
--animate-spin-ccw: spin-ccw 20s linear infinite;
--animate-sun-pulse: sun-pulse 3.2s ease-in-out infinite;
--animate-glow-pulse: glow-pulse 3.2s ease-in-out infinite;
--animate-float: gentle-float 4s ease-in-out infinite;
--animate-blink: blink-cursor 0.8s step-end infinite;
--animate-pulse-soft: pulse-soft 2.5s 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-display);
font-weight: 700;
border-radius: 100px;
cursor: pointer;
text-decoration: none;
line-height: 1;
letter-spacing: -0.01em;
transition: background 0.2s, transform 0.15s, box-shadow 0.2s, border-color 0.2s;
white-space: nowrap;
border: 2px solid transparent;
}
.btn-base:hover { transform: translateY(-2px); text-decoration: none; }
.btn-base:active { transform: translateY(0) !important; }
.btn-sm { font-size: 0.8rem; padding: 8px 18px; }
.btn-md { font-size: 0.9rem; padding: 11px 24px; }
.btn-lg { font-size: 1rem; padding: 14px 32px; }
.btn-primary {
background: var(--color-solar-coral);
color: #fff;
border-color: var(--color-solar-coral);
}
.btn-primary:hover {
background: var(--color-solar-coral-dark);
box-shadow: 0 8px 24px rgba(255, 107, 74, 0.32);
color: #fff;
}
.btn-secondary {
background: transparent;
color: var(--color-solar-coral);
border-color: rgba(255, 107, 74, 0.5);
}
.btn-secondary:hover {
border-color: var(--color-solar-coral);
background: rgba(255, 107, 74, 0.08);
color: var(--color-solar-coral);
}
.btn-ghost {
background: transparent;
color: var(--color-solar-muted);
border-color: rgba(168, 148, 126, 0.3);
}
.btn-ghost:hover {
background: rgba(168, 148, 126, 0.08);
color: var(--color-solar-text);
}/* ─── Badges ─────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-family: var(--font-display);
font-weight: 700;
font-size: 0.65rem;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 4px 12px;
border-radius: 99px;
border: 1px solid transparent;
}
.badge--yellow { background: rgba(245, 197, 24, 0.12); color: var(--color-solar-yellow); border-color: rgba(245, 197, 24, 0.30); }
.badge--coral { background: rgba(255, 107, 74, 0.12); color: var(--color-solar-coral); border-color: rgba(255, 107, 74, 0.28); }
.badge--sky { background: rgba(91, 184, 245, 0.12); color: var(--color-solar-sky); border-color: rgba(91, 184, 245, 0.28); }/* ─── Features Section ───────────────────────────────── */
.solar-card {
background: var(--color-solar-bg-deep);
border: 1.5px solid rgba(245, 197, 24, 0.12);
border-radius: 20px;
padding: 32px 28px;
transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s, background 0.22s;
cursor: default;
}
.solar-card:hover {
transform: translateY(-5px);
box-shadow: 0 16px 48px rgba(245, 197, 24, 0.10);
border-color: rgba(245, 197, 24, 0.24);
background: var(--color-solar-bg-raise);
}
.card-title {
font-family: var(--font-display);
font-size: 1.05rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 8px;
color: var(--color-solar-text);
}
.card-description {
font-size: 0.875rem;
color: var(--color-solar-muted);
line-height: 1.72;
}/* ─── Text Variants ──────────────────────────────────── */
.text-body { font-size: 0.95rem; line-height: 1.75; color: var(--color-solar-muted); }
.text-caption { font-size: 0.8rem; color: var(--color-solar-muted); }
.text-label { font-family: var(--font-display); font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-solar-muted); }
.text-code { font-family: monospace; font-size: 0.85rem; color: var(--color-solar-yellow); }Button
Warm-toned light-mode button with primary, secondary, and ghost variants in three sizes. Renders as a Next.js Link when an href is provided.
Badge
Warm-palette badge for category tags and status labels in the SOLAR light theme.
Card
Feature card with a blob-shaped icon background in yellow, coral, or sky, a category tag, title, and description.
Text
Polymorphic text primitive with body, caption, label, and code variants styled for the SOLAR warm light palette.