Modularity-Lib Style Guide
Comprehensive design system extracted from the modularity-lib — the reference for "that vibe" when building new UI in this codebase.
Modularity-Lib Style Guide
TL;DR for agents: When the user says "make it look like the modularity lib", "that vibe", or "similar design", they mean: deep dark purple/navy background, purple-to-blue gradient accents, translucent glassmorphism cards, subtle radial ambient glows, clean white typography, and smooth micro-interactions.
The Design in One Sentence
A dark-mode-first, glassmorphism-heavy UI built on a deep navy/purple base, with purple-to-blue gradient accents, translucent frosted-glass surfaces, and smooth hover micro-interactions — elegant, spacious, and modern.
Two Modes: Know Which One You're Building
The modularity-lib ships two complementary visual modes depending on context:
| Mode | Where Used | Base Surface | Feel |
|---|---|---|---|
| Dark Dashboard | modularity-dashboard, module-card, module-workbench |
Deep navy #0f0f23 |
Rich, bold, spacious |
| Light Builder | ai-builder |
Soft white/lavender | Clean, airy, focused |
Both use the same accent color system — only the surface changes. Default to Dark Dashboard unless explicitly asked for a light variant.
Color System
Primary Accent Gradients
These are the signature colors. Use them for CTAs, icons, active states, and highlights.
// PRIMARY — Purple to Blue (most common)
linear-gradient(135deg, #7c3aed, #3b82f6)
// AI / VIBE — Indigo to Violet (for AI features, brand moments)
linear-gradient(135deg, #6366f1, #a855f7)
// VIVID VIBE — Full spectrum (badges, hero moments)
linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%)
// HEADER ACCENT LINE (ultra-thin top border highlight)
linear-gradient(90deg, #6366f1 0%, #764ba2 50%, #f093fb 100%)
Semantic Colors
// Success
$color-success: #10b981;
$color-success-light: #34d399;
$color-success-dim: rgba(16, 185, 129, 0.15);
// Warning
$color-warning: #f59e0b;
$color-warning-light: #fbbf24;
$color-warning-dim: rgba(251, 191, 36, 0.15);
// Danger / Error
$color-danger: #ef4444;
$color-danger-light: #f87171;
$color-danger-dim: rgba(248, 113, 113, 0.15);
// Info / Accent blue
$color-info: #3b82f6;
$color-info-light: #60a5fa;
// Favorite / Gold
$color-gold: #fbbf24;
Dark Mode Surface Palette
// Page backgrounds
$bg-page: linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #0d1421 100%);
$bg-ambient: radial-gradient(ellipse at 20% 30%, rgba(124, 58, 237, 0.1), transparent 50%),
radial-gradient(ellipse at 80% 70%, rgba(59, 130, 246, 0.08), transparent 50%);
// Surface tiers (glass cards, panels)
$surface-0: rgba(255, 255, 255, 0.03); // hero/hero-like panels
$surface-1: rgba(255, 255, 255, 0.04); // default cards
$surface-2: rgba(255, 255, 255, 0.06); // hovered cards
$surface-3: rgba(255, 255, 255, 0.08); // active/focused elements
// SCSS variable equivalents (module-workbench)
$surface: #1a1a2e;
$surface-light: #252542;
$surface-lighter: #2d2d4a;
$border: #3d3d5c;
Text Hierarchy
$text-primary: #ffffff;
$text-secondary: rgba(255, 255, 255, 0.6);
$text-tertiary: rgba(255, 255, 255, 0.5);
$text-quaternary: rgba(255, 255, 255, 0.35);
$text-muted: #94a3b8; // workbench variant
$text-body: #e2e8f0; // workbench variant
Border / Divider
$border-subtle: rgba(255, 255, 255, 0.06);
$border-default: rgba(255, 255, 255, 0.08);
$border-medium: rgba(255, 255, 255, 0.10);
$border-strong: rgba(255, 255, 255, 0.15);
$border-accent: rgba(124, 58, 237, 0.3); // purple accent border
$border-accent-h: rgba(124, 58, 237, 0.4); // hovered accent
Background Pattern
Every full-page view uses this layered background — a dark gradient base with soft ambient radial glows.
:host {
display: block;
min-height: 100vh;
background: linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #0d1421 100%);
// Ambient glow layer (fixed, not scrolling)
&::before {
content: '';
position: fixed;
inset: 0;
background:
radial-gradient(ellipse at 20% 30%, rgba(124, 58, 237, 0.10) 0%, transparent 50%),
radial-gradient(ellipse at 80% 70%, rgba(59, 130, 246, 0.08) 0%, transparent 50%);
pointer-events: none;
z-index: 0;
}
}
Rule: All direct children of the page host must have
position: relative; z-index: 1to render above this background layer.
Glassmorphism Card System
The cornerstone of the design. Cards are translucent frosted panels.
Default Card
.glass-card {
background: rgba(255, 255, 255, 0.04);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 16px;
transition: all 0.2s ease;
&:hover {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(124, 58, 237, 0.3);
transform: translateY(-2px);
}
}
Hero / Large Panel
.hero-panel {
background: rgba(255, 255, 255, 0.03);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
padding: 32px;
}
Card Back / Dark Variant
.card-back {
background: linear-gradient(145deg, rgba(30, 20, 50, 0.98), rgba(40, 25, 70, 0.95));
border-color: rgba(124, 58, 237, 0.3);
}
3D Flip Card Pattern
Module cards use a 3D flip to reveal settings. Perspective on the container, backface-visibility: hidden on each face, and rotateY for the flip.
.card-container {
perspective: 1200px;
&.flipped .card-front { transform: rotateY(-180deg); pointer-events: none; }
&.flipped .card-back { transform: rotateY(0deg); pointer-events: all; }
}
.card {
backface-visibility: hidden;
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.card-front { transform: rotateY(0deg); }
.card-back { transform: rotateY(180deg); }
Button System
Primary (CTA)
.btn-primary {
background: linear-gradient(135deg, #7c3aed, #3b82f6);
color: white;
border: none;
border-radius: 12px;
padding: 12px 24px;
font-size: 14px;
font-weight: 600;
box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4);
transition: all 0.2s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(124, 58, 237, 0.5);
}
}
Glow Animation (for hero CTAs)
&.btn-glow {
animation: glow 2s ease-in-out infinite;
}
@keyframes glow {
0%, 100% { box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4); }
50% { box-shadow: 0 4px 30px rgba(124, 58, 237, 0.6), 0 0 40px rgba(124, 58, 237, 0.3); }
}
Shine Effect (for generate/submit buttons)
.btn-generate {
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%);
position: relative;
overflow: hidden;
// Sweeping shine on hover
&::before {
content: '';
position: absolute;
top: 0; left: -100%;
width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.6s ease;
}
&:hover::before { left: 100%; }
&:hover {
transform: translateY(-3px);
box-shadow:
0 8px 32px rgba(99, 102, 241, 0.45),
0 4px 12px rgba(168, 85, 247, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
}
Secondary (Ghost Glass)
.btn-secondary {
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(255, 255, 255, 0.15);
&:hover {
background: rgba(255, 255, 255, 0.12);
transform: translateY(-2px);
}
}
Icon Button
.btn-icon {
padding: 10px;
background: rgba(255, 255, 255, 0.06);
color: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
&:hover {
background: rgba(255, 255, 255, 0.10);
color: white;
}
&.active {
background: rgba(124, 58, 237, 0.2);
border-color: rgba(124, 58, 237, 0.4);
color: #a78bfa;
}
}
Ghost Button
.btn-ghost {
background: transparent;
color: rgba(255, 255, 255, 0.6);
padding: 8px;
&:hover {
color: white;
background: rgba(255, 255, 255, 0.08);
}
}
Platform / Success Button
.btn-platform {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
border: none;
&:hover {
background: linear-gradient(135deg, #34d399, #10b981);
box-shadow: 0 4px 16px rgba(16, 185, 129, 0.4);
}
}
Size Variants
.btn { padding: 12px 24px; font-size: 14px; }
.btn-sm { padding: 6px 12px; font-size: 13px; }
.btn-lg { padding: 18px 28px; font-size: 16px; font-weight: 700; }
Icon Container Patterns
Icons are always wrapped in a gradient-tinted rounded container.
// Large (hero / dashboard icon)
.icon-xl {
width: 72px; height: 72px;
background: linear-gradient(135deg, #7c3aed, #3b82f6);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(124, 58, 237, 0.4);
color: white;
font-size: 28px;
}
// Medium (card icon)
.icon-md {
width: 48px; height: 48px;
background: linear-gradient(135deg, rgba(124, 58, 237, 0.2), rgba(59, 130, 246, 0.2));
border-radius: 12px;
color: #a78bfa;
font-size: 18-20px;
}
// Small (mini card icon, back-side)
.icon-sm {
width: 32px; height: 32px;
background: linear-gradient(135deg, rgba(124, 58, 237, 0.3), rgba(59, 130, 246, 0.3));
border-radius: 8px;
color: #a78bfa;
font-size: 14px;
}
// Suggestion / AI icon (indigo-to-violet)
.icon-ai {
width: 44px; height: 44px;
background: linear-gradient(135deg, #6366f1, #a855f7);
border-radius: 12px;
color: white;
box-shadow: 0 2px 8px rgba(99, 102, 241, 0.25);
}
Color intent of icon tints:
- Purple tint
rgba(124, 58, 237, ...)→ general module/feature- Blue tint
rgba(59, 130, 246, ...)→ built-in / system- Green tint
rgba(52, 211, 153, ...)→ success / deployed- Amber tint
rgba(251, 191, 36, ...)→ in-progress / building- Gray tint
rgba(156, 163, 175, ...)→ draft / inactive
Status Badge System
All status badges use the same anatomy: translucent background + matching text.
// Status pattern
.status-badge {
padding: 4px 10px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
border-radius: 6px;
&.status-draft { background: rgba(156, 163, 175, 0.15); color: #9ca3af; }
&.status-building { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
&.status-testing { background: rgba(168, 85, 247, 0.15); color: #a855f7; }
&.status-ready { background: rgba(52, 211, 153, 0.15); color: #34d399; }
&.status-deployed { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }
}
// Source badges (custom / builtin / external)
.source-badge {
padding: 4px 8px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
border-radius: 4px;
&.source-custom { background: rgba(139, 92, 246, 0.15); color: #a78bfa; }
&.source-builtin { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
&.source-external { background: rgba(52, 211, 153, 0.15); color: #6ee7b7; }
}
Category Chip / Filter Chip
.category-chip {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background: rgba(255, 255, 255, 0.08);
color: white;
}
&.active {
background: linear-gradient(135deg, rgba(124, 58, 237, 0.2), rgba(59, 130, 246, 0.2));
border-color: rgba(124, 58, 237, 0.4);
color: white;
}
}
Stats / Metrics Cards
.stat-card {
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
background: rgba(255, 255, 255, 0.04);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 16px;
transition: all 0.2s ease;
cursor: pointer;
&:hover {
background: rgba(255, 255, 255, 0.06);
transform: translateY(-2px);
}
&.active {
background: rgba(124, 58, 237, 0.1);
border-color: rgba(124, 58, 237, 0.3);
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: white;
}
.stat-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.5);
}
}
Form Elements
Dark Theme Input
input, select, textarea {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 10px;
color: white;
font-size: 14px;
padding: 10px 40px 10px 14px; // with icon space
outline: none;
transition: all 0.2s ease;
&::placeholder { color: rgba(255, 255, 255, 0.4); }
&:focus {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(124, 58, 237, 0.4);
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.12);
}
}
Light Theme Input (ai-builder variant)
input, textarea {
border: 2px solid rgba(203, 213, 225, 0.6);
border-radius: 14px;
background: rgba(255, 255, 255, 0.8);
color: #1e1e2e;
font-size: 0.95rem;
padding: 16px 18px;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.04);
transition: all 0.25s ease;
&:focus {
border-color: #6366f1;
background: white;
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.12);
}
}
Progress Bar
.progress-bar {
height: 3px; // thin version (inside cards)
// height: 8px; // standard version
background: rgba(255, 255, 255, 0.08);
border-radius: 2px;
overflow: hidden;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #7c3aed, #3b82f6);
// Or: linear-gradient(90deg, #6366f1, #10b981, #22c55e) — full spectrum
border-radius: 2px;
transition: width 0.3s ease;
box-shadow: 0 0 12px rgba(124, 58, 237, 0.4);
// Animated shine
&::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%);
animation: progressShine 2s ease-in-out infinite;
}
}
}
@keyframes progressShine {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
Empty State
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px;
background: rgba(255, 255, 255, 0.02);
border: 2px dashed rgba(255, 255, 255, 0.1);
border-radius: 20px;
text-align: center;
.empty-icon {
width: 80px; height: 80px;
background: rgba(124, 58, 237, 0.1);
border-radius: 20px;
margin-bottom: 20px;
i { font-size: 32px; color: #7c3aed; }
}
h3 { margin: 0 0 8px; font-size: 18px; color: white; }
p { margin: 0 0 20px; color: rgba(255, 255, 255, 0.5); }
}
Loading State
Spinner
.loader {
width: 40px; height: 40px;
border: 3px solid rgba(124, 58, 237, 0.2);
border-top-color: #7c3aed;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
Full-Page Generation Overlay
.generation-card {
background: rgba(var(--ux-surface-rgb), 0.8);
backdrop-filter: blur(24px);
border-radius: 24px;
padding: 48px;
text-align: center;
max-width: 500px;
.pulse-ring {
position: absolute;
width: 100%; height: 100%;
border-radius: 50%;
border: 2px solid var(--ux-primary);
opacity: 0;
animation: pulse-ring 2s ease-out infinite;
&.delay-1 { animation-delay: 0.5s; }
&.delay-2 { animation-delay: 1.0s; }
}
}
@keyframes pulse-ring {
0% { transform: scale(0.8); opacity: 0.8; }
100% { transform: scale(1.5); opacity: 0; }
}
Dividers
// Standard hairline
.divider {
height: 1px;
background: rgba(255, 255, 255, 0.04);
}
// Gradient fade-out divider (decorative)
.divider-gradient {
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
}
Custom Scrollbar
&::-webkit-scrollbar { width: 4px; }
&::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.05); border-radius: 2px; }
&::-webkit-scrollbar-thumb {
background: rgba(124, 58, 237, 0.4);
border-radius: 2px;
&:hover { background: rgba(124, 58, 237, 0.6); }
}
Header / Workbench Header
The workbench header has a signature 3px gradient accent line at the top.
.workbench-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 32px;
background: linear-gradient(135deg, rgba(#252542, 0.95), rgba(#252542, 0.98));
border-bottom: 1px solid rgba(#3d3d5c, 0.5);
backdrop-filter: blur(12px);
// Signature gradient top line
&::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: linear-gradient(90deg, #6366f1 0%, #764ba2 50%, #f093fb 100%);
opacity: 0.8;
}
}
Step Navigation
Used in multi-step wizards (module workbench).
.step-item {
padding: 14px 20px;
background: rgba(#2d2d4a, 0.4);
border: 1px solid rgba(#3d3d5c, 0.3);
border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
backdrop-filter: blur(8px);
// Active step
&.active {
background: linear-gradient(135deg, rgba(#6366f1, 0.15), rgba(#764ba2, 0.1));
border-color: rgba(#6366f1, 0.5);
box-shadow: 0 4px 20px rgba(#6366f1, 0.2), inset 0 1px 0 rgba(255,255,255,0.1);
.step-title {
background: linear-gradient(135deg, #818cf8, #c084fc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
// Completed step
&.step-complete .step-indicator {
background: linear-gradient(135deg, #10b981, #059669);
box-shadow: 0 4px 12px rgba(#10b981, 0.3);
}
// Partial step
&.step-partial .step-indicator {
background: linear-gradient(135deg, #f59e0b, #d97706);
box-shadow: 0 4px 12px rgba(#f59e0b, 0.3);
}
}
.step-connector {
width: 32px; height: 3px;
background: linear-gradient(90deg, rgba(#3d3d5c, 0.3), rgba(#3d3d5c, 0.5), rgba(#3d3d5c, 0.3));
border-radius: 2px;
}
Grid Layouts
// Stat cards row (up to 5 columns)
.stats-bar {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 16px;
@media (max-width: 1200px) { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 768px) { grid-template-columns: repeat(2, 1fr); }
}
// Module cards (auto-fill, responsive)
.modules-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 20px;
}
// Template cards (4 → 2 → 1)
.templates-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
@media (max-width: 1200px) { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 768px) { grid-template-columns: 1fr; }
}
// Main content + sidebar
.builder-content {
display: grid;
grid-template-columns: 1fr 380px;
gap: 24px;
@media (max-width: 1200px) { grid-template-columns: 1fr; }
}
Spacing Scale
All padding and gap values come from this consistent scale:
| Token | Value | Common Use |
|---|---|---|
--space-xs |
4px |
Badge padding, tiny gaps |
--space-sm |
8px |
Icon gaps, chip inner |
--space-md |
12px |
Button gap, small card padding |
--space-lg |
16px |
Card gaps, grid gaps |
--space-xl |
20px |
Card padding, large gaps |
--space-2xl |
24px |
Page section padding |
--space-3xl |
32px |
Hero section padding |
Typography
// Page title / Hero
h1 { font-size: 28px; font-weight: 700; color: #ffffff; letter-spacing: -0.02em; }
// Section title
.section-title { font-size: 18px; font-weight: 600; color: white; }
// Card title
.card-title { font-size: 15px; font-weight: 600; color: white; line-height: 1.3; }
// Label / overline (uppercase caps)
.overline {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.1em;
color: rgba(255, 255, 255, 0.4);
}
// Body text
.body { font-size: 14-15px; color: rgba(255, 255, 255, 0.6); line-height: 1.5; }
// Caption / meta
.caption { font-size: 12-13px; color: rgba(255, 255, 255, 0.35-0.5); }
// Micro
.micro { font-size: 10-11px; text-transform: uppercase; letter-spacing: 0.05em; }
// Gradient text (hero moments)
.text-gradient {
background: linear-gradient(135deg, #818cf8, #c084fc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
// Monospace (code, versions)
.monospace {
font-family: 'JetBrains Mono', 'Fira Code', monospace;
background: rgba(255, 255, 255, 0.05);
padding: 2px 8px;
border-radius: 4px;
}
Border Radius Scale
$radius-xs: 4px; // badges, tiny chips
$radius-sm: 8px; // small buttons, inputs
$radius-md: 10px; // action items, filter buttons
$radius-lg: 12px; // standard buttons, icon containers
$radius-xl: 16px; // cards, panels
$radius-2xl: 20px; // hero panels, large cards
$radius-3xl: 24px; // full panels (ai-builder)
$radius-pill: 20px; // category chips, status pills
Transition / Easing
// Standard interactive transition
transition: all 0.2s ease;
// Refined — use for cards and hover-lift effects
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
// Smooth entrance / exit
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
// Card flip (3D)
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
// Button hover lift
transform: translateY(-2px); // standard hover
transform: translateY(-3px); // hero CTA hover
// Slide-in animation
@keyframes slideUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
// Entrance animation
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
Complete Component Cheat Sheet
When building any new component, use this lookup table:
| Element | Style Recipe |
|---|---|
| Page background | linear-gradient(135deg, #0f0f23, #1a1a3e, #0d1421) + ::before ambient radials |
| Card | rgba(255,255,255,0.04) bg, blur(12px), 1px solid rgba(255,255,255,0.06), 16px radius |
| Card hover | rgba(255,255,255,0.06) bg, rgba(124,58,237,0.3) border, translateY(-2px) |
| Hero section | Same as card but rgba(255,255,255,0.03), blur(20px), 20px radius, 32px padding |
| Primary button | linear-gradient(135deg, #7c3aed, #3b82f6), 0 4px 20px rgba(124,58,237,0.4) shadow |
| Primary button hover | translateY(-2px), 0 8px 30px rgba(124,58,237,0.5) |
| Ghost/secondary button | rgba(255,255,255,0.08) bg, rgba(255,255,255,0.15) border |
| Icon container (medium) | linear-gradient(135deg, rgba(124,58,237,0.2), rgba(59,130,246,0.2)), 12px radius, #a78bfa color |
| Section title | 18px, 600 weight, white, with #a78bfa tinted icon |
| Status: ready | rgba(52,211,153,0.15) bg, #34d399 text |
| Status: building | rgba(251,191,36,0.15) bg, #fbbf24 text |
| Status: deployed | rgba(59,130,246,0.15) bg, #3b82f6 text |
| Status: draft | rgba(156,163,175,0.15) bg, #9ca3af text |
| Category chip inactive | rgba(255,255,255,0.04) bg, 20px radius |
| Category chip active | linear-gradient(135deg, rgba(124,58,237,0.2), rgba(59,130,246,0.2)), purple border |
| Input (dark) | rgba(255,255,255,0.06) bg, rgba(255,255,255,0.1) border, focus → purple border + ring |
| Progress bar | linear-gradient(90deg, #7c3aed, #3b82f6), 3px thin / 8px standard height |
| Scrollbar | 4px width, rgba(124,58,237,0.4) thumb |
| Header accent line | 3px top border, linear-gradient(90deg, #6366f1, #764ba2, #f093fb) |
| Empty state border | 2px dashed rgba(255,255,255,0.1), 20px radius |
| Divider | 1px solid rgba(255,255,255,0.04) OR gradient fade variant |
| Transition | all 0.2s ease standard / 0.3s cubic-bezier(0.4,0,0.2,1) smooth |
| Hover lift | translateY(-2px) |
Anti-Patterns (Do NOT Do These)
| Wrong | Right |
|---|---|
Hardcoded white background: white on dark surfaces |
Use rgba(255,255,255,0.04) glass surfaces |
Solid opaque borders border: 1px solid #333 |
Use rgba(255,255,255,0.06–0.15) |
| Flat monochrome icons | Wrap in gradient icon container |
border-radius: 4px on cards |
Minimum 16px for cards, 20px for panels |
| Saturated solid colors for status badges | Use 15% opacity tinted backgrounds |
No backdrop-filter on glass panels |
Always add blur(12–20px) |
| Missing hover state | Every interactive element needs transition + hover |
| Gradient text without fallback color | Always pair with color fallback |
Quick-Start Template (Dark Dashboard Component)
:host {
display: block;
min-height: 100vh;
background: linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #0d1421 100%);
&::before {
content: '';
position: fixed;
inset: 0;
background:
radial-gradient(ellipse at 20% 30%, rgba(124, 58, 237, 0.10), transparent 50%),
radial-gradient(ellipse at 80% 70%, rgba(59, 130, 246, 0.08), transparent 50%);
pointer-events: none;
z-index: 0;
}
}
.my-section {
position: relative;
z-index: 1;
padding: 24px;
}
.my-card {
background: rgba(255, 255, 255, 0.04);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 16px;
padding: 20px;
transition: all 0.2s ease;
&:hover {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(124, 58, 237, 0.3);
transform: translateY(-2px);
}
}
.my-cta {
background: linear-gradient(135deg, #7c3aed, #3b82f6);
color: white;
border: none;
border-radius: 12px;
padding: 12px 24px;
font-weight: 600;
box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4);
cursor: pointer;
transition: all 0.2s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(124, 58, 237, 0.5);
}
}
Light Builder Mode — Companion Guide
When building builder-type interfaces (configurators, wizards, settings panels), use the Light Builder mode. This shares the same accent system as the Dark Dashboard but inverts the surface hierarchy for a clean, airy, focused feel.
When to Use Light vs Dark
| Mode | Use For | Examples |
|---|---|---|
| Dark Dashboard | Monitoring, visualization, data-heavy pages | Observatory, Workflow Builder, Agent Monitor |
| Light Builder | Configuration, forms, editing, onboarding | Vitto Maker, AI Builder, Settings panels |
Light Mode Color System
// Page backgrounds
$bg-page: linear-gradient(135deg, #f8f7ff 0%, #f0eeff 40%, #eef2ff 100%);
$bg-ambient: radial-gradient(ellipse at 15% 20%, rgba(99, 102, 241, 0.06), transparent 50%),
radial-gradient(ellipse at 85% 80%, rgba(139, 92, 246, 0.04), transparent 50%);
// Surface tiers (glass cards, panels)
$surface-card: rgba(255, 255, 255, 0.85); // default cards
$surface-card-hover: rgba(255, 255, 255, 0.95); // hovered cards
$surface-sidebar: rgba(255, 255, 255, 0.6); // sidebar panels
$surface-input: rgba(255, 255, 255, 0.7); // inputs, search bars
$surface-input-focus: white; // focused inputs
// Text hierarchy
$text-primary: #1e1e2e;
$text-secondary: #4b5563;
$text-tertiary: #9ca3af;
// Borders — use indigo-tinted alpha for cohesion
$border-light: rgba(99, 102, 241, 0.08);
$border-default: rgba(99, 102, 241, 0.12);
$border-hover: rgba(99, 102, 241, 0.25);
$border-focus: rgba(99, 102, 241, 0.25);
// Shadows — indigo-tinted for brand cohesion (NOT pure black)
$shadow-sm: 0 1px 3px rgba(99, 102, 241, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
$shadow-md: 0 4px 12px rgba(99, 102, 241, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04);
$shadow-lg: 0 4px 16px rgba(99, 102, 241, 0.10), 0 2px 4px rgba(0, 0, 0, 0.04);
Light Mode Background Pattern
:host {
display: block;
background: linear-gradient(135deg, #f8f7ff 0%, #f0eeff 40%, #eef2ff 100%);
position: relative;
&::before {
content: '';
position: fixed;
inset: 0;
background:
radial-gradient(ellipse at 15% 20%, rgba(99, 102, 241, 0.06), transparent 50%),
radial-gradient(ellipse at 85% 80%, rgba(139, 92, 246, 0.04), transparent 50%);
pointer-events: none;
z-index: 0;
}
}
Light Mode Card
.card {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(12px);
border: 1px solid rgba(99, 102, 241, 0.08);
border-radius: 16px;
padding: 20px;
box-shadow: 0 1px 4px rgba(99, 102, 241, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03);
transition: all 0.2s ease;
&:hover {
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.1), 0 2px 4px rgba(0, 0, 0, 0.04);
border-color: rgba(99, 102, 241, 0.15);
}
}
Light Mode Input
input, select, textarea {
background: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(99, 102, 241, 0.08);
border-radius: 10px;
color: #1e1e2e;
font-size: 13px;
padding: 10px 14px;
transition: all 0.15s ease;
&::placeholder { color: #9ca3af; }
&:focus {
background: white;
border-color: rgba(99, 102, 241, 0.25);
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.06);
}
}
Light Mode Badges / Pills
Use color-mix() for automatic accent tinting:
.badge {
font-size: 11px;
font-weight: 600;
padding: 3px 10px;
border-radius: 10px;
background: color-mix(in srgb, var(--accent, #818cf8) 8%, transparent);
color: var(--accent, #818cf8);
border: 1px solid color-mix(in srgb, var(--accent, #818cf8) 12%, transparent);
}
Light Mode Toggle Switch
.switch {
width: 38px; height: 22px;
border-radius: 11px;
border: 1px solid rgba(0, 0, 0, 0.08);
background: rgba(0, 0, 0, 0.06);
position: relative;
&--on {
background: color-mix(in srgb, var(--accent, #818cf8) 85%, white);
border-color: color-mix(in srgb, var(--accent, #818cf8) 30%, transparent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #818cf8) 10%, transparent);
}
.knob {
width: 16px; height: 16px;
border-radius: 50%;
background: white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
position: absolute; top: 2px; left: 2px;
transition: transform 0.2s ease;
.switch--on & { transform: translateX(16px); }
}
}
Light Mode Component Cheat Sheet
| Element | Light Mode Recipe |
|---|---|
| Page background | linear-gradient(135deg, #f8f7ff, #f0eeff, #eef2ff) + ::before ambient radials (opacity 0.04-0.06) |
| Card | rgba(255,255,255,0.85) bg, blur(12px), 1px solid rgba(99,102,241,0.08), indigo-tinted shadow |
| Card hover | 0.95 bg, rgba(99,102,241,0.15) border, larger shadow |
| Sidebar | rgba(255,255,255,0.6) bg, blur(20px) backdrop |
| Primary button | Same gradient as dark mode: linear-gradient(135deg, #7c3aed, #3b82f6) |
| Ghost button | rgba(255,255,255,0.8) bg, rgba(99,102,241,0.12) border |
| Input | rgba(255,255,255,0.7) bg, focus → white + indigo ring |
| Text primary | #1e1e2e (dark navy) |
| Text secondary | #4b5563 (gray-600) |
| Text tertiary | #9ca3af (gray-400) |
| Border | rgba(99,102,241,0.08) light, 0.12 default, 0.25 hover/focus |
| Shadows | Always indigo-tinted: rgba(99,102,241,0.06-0.10) + small black component |
| Icon containers | Same as dark: color-mix(in srgb, var(--accent) 10%, transparent) with 1px solid at 12% |
| Badge/pill | color-mix(in srgb, var(--accent) 8%, transparent) bg + 12% border |
| Scrollbar | 4px width, rgba(99,102,241,0.15-0.3) thumb |
Light Mode Anti-Patterns
| Wrong | Right |
|---|---|
Pure #ffffff backgrounds everywhere |
Use rgba(255,255,255,0.85) glass surfaces |
border: 1px solid #e5e7eb (generic gray) |
Use rgba(99,102,241,0.08) (indigo-tinted) for brand cohesion |
box-shadow with pure black |
Use indigo-tinted shadows for warmth |
| Dark text directly on light background (#000) | Use #1e1e2e (dark navy) for softer contrast |
| No backdrop-filter on light panels | Add blur(12-20px) for frosted glass effect |
| Missing ambient glow | Add subtle rgba(99,102,241,0.04-0.06) radial gradients |
Last updated: March 4, 2026 — Session 177 | Source: libs/libs-structural/modularity-lib/src/lib/components/**/*.scss, libs/libs-ai/vitto-maker/src/lib/components/**/*.scss