Add Mylder brand design system with warm amber accent
- Implement comprehensive design system with OKLCH colors - Add warm stone neutrals replacing cold zinc grays - Add amber brand color for CTAs and accents - Update typography to Plus Jakarta Sans + JetBrains Mono - Add brand variants to Button and Badge components - Add utility classes: glass, shadow-brand, text-gradient-brand - Update all pages to use semantic design tokens - Add design system documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,11 +39,11 @@ export default function LoginPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950 px-4">
|
||||
<div className="min-h-screen flex items-center justify-center bg-background px-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<Link href="/" className="inline-flex items-center justify-center gap-2 mb-4">
|
||||
<Bot className="h-8 w-8 text-primary" />
|
||||
<Bot className="h-8 w-8 text-brand" />
|
||||
<span className="text-xl font-bold">Mylder</span>
|
||||
</Link>
|
||||
<CardTitle>Welcome back</CardTitle>
|
||||
@@ -76,11 +76,11 @@ export default function LoginPage() {
|
||||
/>
|
||||
</div>
|
||||
{error && (
|
||||
<p className="text-sm text-red-500">{error}</p>
|
||||
<p className="text-sm text-destructive">{error}</p>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-4">
|
||||
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||
<Button type="submit" variant="brand" className="w-full" disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
@@ -90,9 +90,9 @@ export default function LoginPage() {
|
||||
'Sign In'
|
||||
)}
|
||||
</Button>
|
||||
<p className="text-sm text-center text-zinc-500">
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Don't have an account?{' '}
|
||||
<Link href="/signup" className="text-primary hover:underline">
|
||||
<Link href="/signup" className="text-brand hover:underline">
|
||||
Sign up
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
@@ -57,11 +57,11 @@ export default function SignupPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950 px-4">
|
||||
<div className="min-h-screen flex items-center justify-center bg-background px-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<Link href="/" className="inline-flex items-center justify-center gap-2 mb-4">
|
||||
<Bot className="h-8 w-8 text-primary" />
|
||||
<Bot className="h-8 w-8 text-brand" />
|
||||
<span className="text-xl font-bold">Mylder</span>
|
||||
</Link>
|
||||
<CardTitle>Create your account</CardTitle>
|
||||
@@ -118,11 +118,11 @@ export default function SignupPage() {
|
||||
/>
|
||||
</div>
|
||||
{error && (
|
||||
<p className="text-sm text-red-500">{error}</p>
|
||||
<p className="text-sm text-destructive">{error}</p>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-4">
|
||||
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||
<Button type="submit" variant="brand" className="w-full" disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
@@ -132,9 +132,9 @@ export default function SignupPage() {
|
||||
'Create Account'
|
||||
)}
|
||||
</Button>
|
||||
<p className="text-sm text-center text-zinc-500">
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
Already have an account?{' '}
|
||||
<Link href="/login" className="text-primary hover:underline">
|
||||
<Link href="/login" className="text-brand hover:underline">
|
||||
Log in
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
@@ -20,11 +20,11 @@ export default async function DashboardPage() {
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-zinc-900 dark:text-white">Projects</h1>
|
||||
<p className="text-zinc-500">Manage your AI-powered development projects</p>
|
||||
<h1 className="text-2xl font-bold text-foreground">Projects</h1>
|
||||
<p className="text-muted-foreground">Manage your AI-powered development projects</p>
|
||||
</div>
|
||||
<Link href="/projects/new">
|
||||
<Button className="gap-2">
|
||||
<Button variant="brand" className="gap-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
New Project
|
||||
</Button>
|
||||
@@ -35,11 +35,11 @@ export default async function DashboardPage() {
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{projects.map((project) => (
|
||||
<Link key={project.id} href={`/projects/${project.id}`}>
|
||||
<Card className="h-full hover:border-primary/50 transition-colors cursor-pointer">
|
||||
<Card className="h-full hover:border-brand/50 hover:shadow-md transition-all cursor-pointer">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<CardTitle className="text-lg">{project.name}</CardTitle>
|
||||
<Badge variant={project.status === 'active' ? 'default' : 'secondary'}>
|
||||
<Badge variant={project.status === 'active' ? 'brand' : 'secondary'}>
|
||||
{project.status}
|
||||
</Badge>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@ export default async function DashboardPage() {
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center gap-4 text-sm text-zinc-500">
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
{project.tech_stack && project.tech_stack.length > 0 && (
|
||||
<div className="flex gap-1">
|
||||
{project.tech_stack.slice(0, 3).map((tech: string) => (
|
||||
@@ -59,7 +59,7 @@ export default async function DashboardPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-xs text-zinc-400 mt-4">
|
||||
<div className="flex items-center gap-1 text-xs text-muted-foreground mt-4">
|
||||
<Clock className="h-3 w-3" />
|
||||
Updated {new Date(project.updated_at).toLocaleDateString()}
|
||||
</div>
|
||||
@@ -71,17 +71,17 @@ export default async function DashboardPage() {
|
||||
) : (
|
||||
<Card className="border-dashed">
|
||||
<CardContent className="flex flex-col items-center justify-center py-16">
|
||||
<div className="w-16 h-16 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center mb-4">
|
||||
<FolderOpen className="h-8 w-8 text-zinc-400" />
|
||||
<div className="w-16 h-16 rounded-full bg-muted flex items-center justify-center mb-4">
|
||||
<FolderOpen className="h-8 w-8 text-muted-foreground" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-zinc-900 dark:text-white mb-2">
|
||||
<h3 className="text-lg font-semibold text-foreground mb-2">
|
||||
No projects yet
|
||||
</h3>
|
||||
<p className="text-zinc-500 text-center mb-6 max-w-sm">
|
||||
<p className="text-muted-foreground text-center mb-6 max-w-sm">
|
||||
Create your first project to start building with AI assistance.
|
||||
</p>
|
||||
<Link href="/projects/new">
|
||||
<Button className="gap-2">
|
||||
<Button variant="brand" className="gap-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
Create Your First Project
|
||||
</Button>
|
||||
|
||||
@@ -34,21 +34,21 @@ export default async function ProjectPage({ params }: { params: Promise<{ id: st
|
||||
return (
|
||||
<div className="h-[calc(100vh-4rem)] flex flex-col">
|
||||
{/* Project Header */}
|
||||
<div className="border-b bg-white dark:bg-zinc-950 px-4 py-3">
|
||||
<div className="border-b bg-card px-4 py-3">
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link href="/dashboard" className="text-zinc-500 hover:text-zinc-900 dark:hover:text-white">
|
||||
<Link href="/dashboard" className="text-muted-foreground hover:text-foreground transition-colors">
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</Link>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<h1 className="text-lg font-semibold">{project.name}</h1>
|
||||
<Badge variant={project.status === 'active' ? 'default' : 'secondary'}>
|
||||
<Badge variant={project.status === 'active' ? 'brand' : 'secondary'}>
|
||||
{project.status}
|
||||
</Badge>
|
||||
</div>
|
||||
{project.description && (
|
||||
<p className="text-sm text-zinc-500">{project.description}</p>
|
||||
<p className="text-sm text-muted-foreground">{project.description}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -89,7 +89,7 @@ export default function NewProjectPage() {
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<Link href="/dashboard" className="inline-flex items-center gap-2 text-sm text-zinc-500 hover:text-zinc-900 dark:hover:text-white mb-6">
|
||||
<Link href="/dashboard" className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors mb-6">
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Projects
|
||||
</Link>
|
||||
@@ -125,9 +125,9 @@ export default function NewProjectPage() {
|
||||
/>
|
||||
</div>
|
||||
{error && (
|
||||
<p className="text-sm text-red-500">{error}</p>
|
||||
<p className="text-sm text-destructive">{error}</p>
|
||||
)}
|
||||
<Button type="submit" className="w-full" disabled={isLoading || !name}>
|
||||
<Button type="submit" variant="brand" className="w-full" disabled={isLoading || !name}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
|
||||
@@ -3,120 +3,381 @@
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
/* ============================================
|
||||
MYLDER DESIGN SYSTEM
|
||||
Warm neutrals + Amber accent
|
||||
============================================ */
|
||||
|
||||
@theme inline {
|
||||
/* Color mappings */
|
||||
--color-background: var(--background);
|
||||
--color-background-subtle: var(--background-subtle);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
|
||||
/* Brand colors */
|
||||
--color-brand: var(--brand);
|
||||
--color-brand-foreground: var(--brand-foreground);
|
||||
--color-brand-muted: var(--brand-muted);
|
||||
|
||||
/* Semantic colors */
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-success: var(--success);
|
||||
--color-success-foreground: var(--success-foreground);
|
||||
--color-warning: var(--warning);
|
||||
--color-warning-foreground: var(--warning-foreground);
|
||||
--color-info: var(--info);
|
||||
--color-info-foreground: var(--info-foreground);
|
||||
|
||||
/* UI colors */
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
|
||||
/* Chart colors */
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
|
||||
/* Sidebar colors */
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
|
||||
/* Typography */
|
||||
--font-sans: var(--font-sans);
|
||||
--font-mono: var(--font-mono);
|
||||
|
||||
/* Border radius */
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--radius-2xl: calc(var(--radius) + 8px);
|
||||
--radius-3xl: calc(var(--radius) + 16px);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
LIGHT MODE (Default)
|
||||
Warm stone neutrals + amber accent
|
||||
============================================ */
|
||||
:root {
|
||||
/* Base radius */
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Plus Jakarta Sans', var(--font-geist-sans), system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', var(--font-geist-mono), monospace;
|
||||
|
||||
/* Brand - Amber */
|
||||
--brand: oklch(0.75 0.16 75);
|
||||
--brand-foreground: oklch(0.20 0.02 75);
|
||||
--brand-muted: oklch(0.92 0.06 75);
|
||||
|
||||
/* Backgrounds - Warm white */
|
||||
--background: oklch(0.99 0.002 75);
|
||||
--background-subtle: oklch(0.975 0.004 75);
|
||||
--foreground: oklch(0.15 0.01 75);
|
||||
|
||||
/* Cards & Surfaces */
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--card-foreground: oklch(0.15 0.01 75);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
--popover-foreground: oklch(0.15 0.01 75);
|
||||
|
||||
/* Primary - Dark (for contrast) */
|
||||
--primary: oklch(0.20 0.01 75);
|
||||
--primary-foreground: oklch(0.98 0.002 75);
|
||||
|
||||
/* Secondary - Light gray */
|
||||
--secondary: oklch(0.955 0.006 75);
|
||||
--secondary-foreground: oklch(0.25 0.01 75);
|
||||
|
||||
/* Muted - Subtle */
|
||||
--muted: oklch(0.955 0.006 75);
|
||||
--muted-foreground: oklch(0.50 0.01 75);
|
||||
|
||||
/* Accent - Warm amber tint */
|
||||
--accent: oklch(0.96 0.04 75);
|
||||
--accent-foreground: oklch(0.25 0.02 75);
|
||||
|
||||
/* Semantic states */
|
||||
--destructive: oklch(0.55 0.22 25);
|
||||
--destructive-foreground: oklch(0.98 0 0);
|
||||
--success: oklch(0.65 0.18 145);
|
||||
--success-foreground: oklch(0.98 0 0);
|
||||
--warning: oklch(0.80 0.15 85);
|
||||
--warning-foreground: oklch(0.25 0.02 85);
|
||||
--info: oklch(0.65 0.15 240);
|
||||
--info-foreground: oklch(0.98 0 0);
|
||||
|
||||
/* Borders & Inputs */
|
||||
--border: oklch(0.90 0.006 75);
|
||||
--input: oklch(0.90 0.006 75);
|
||||
--ring: oklch(0.75 0.16 75);
|
||||
|
||||
/* Charts - Vibrant palette */
|
||||
--chart-1: oklch(0.75 0.16 75);
|
||||
--chart-2: oklch(0.60 0.15 200);
|
||||
--chart-3: oklch(0.65 0.18 280);
|
||||
--chart-4: oklch(0.70 0.16 145);
|
||||
--chart-5: oklch(0.65 0.20 25);
|
||||
|
||||
/* Sidebar */
|
||||
--sidebar: oklch(0.985 0.003 75);
|
||||
--sidebar-foreground: oklch(0.15 0.01 75);
|
||||
--sidebar-primary: oklch(0.75 0.16 75);
|
||||
--sidebar-primary-foreground: oklch(0.20 0.02 75);
|
||||
--sidebar-accent: oklch(0.96 0.04 75);
|
||||
--sidebar-accent-foreground: oklch(0.25 0.02 75);
|
||||
--sidebar-border: oklch(0.90 0.006 75);
|
||||
--sidebar-ring: oklch(0.75 0.16 75);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
DARK MODE
|
||||
Warm dark + amber accent
|
||||
============================================ */
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
/* Brand - Slightly brighter for dark bg */
|
||||
--brand: oklch(0.78 0.15 75);
|
||||
--brand-foreground: oklch(0.15 0.02 75);
|
||||
--brand-muted: oklch(0.30 0.06 75);
|
||||
|
||||
/* Backgrounds - Warm dark */
|
||||
--background: oklch(0.14 0.008 75);
|
||||
--background-subtle: oklch(0.18 0.01 75);
|
||||
--foreground: oklch(0.96 0.004 75);
|
||||
|
||||
/* Cards & Surfaces */
|
||||
--card: oklch(0.20 0.01 75);
|
||||
--card-foreground: oklch(0.96 0.004 75);
|
||||
--popover: oklch(0.20 0.01 75);
|
||||
--popover-foreground: oklch(0.96 0.004 75);
|
||||
|
||||
/* Primary - Light (for contrast) */
|
||||
--primary: oklch(0.94 0.004 75);
|
||||
--primary-foreground: oklch(0.18 0.01 75);
|
||||
|
||||
/* Secondary */
|
||||
--secondary: oklch(0.26 0.012 75);
|
||||
--secondary-foreground: oklch(0.94 0.004 75);
|
||||
|
||||
/* Muted */
|
||||
--muted: oklch(0.26 0.012 75);
|
||||
--muted-foreground: oklch(0.65 0.01 75);
|
||||
|
||||
/* Accent */
|
||||
--accent: oklch(0.30 0.04 75);
|
||||
--accent-foreground: oklch(0.94 0.004 75);
|
||||
|
||||
/* Semantic states - Adjusted for dark */
|
||||
--destructive: oklch(0.65 0.20 22);
|
||||
--destructive-foreground: oklch(0.98 0 0);
|
||||
--success: oklch(0.70 0.16 145);
|
||||
--success-foreground: oklch(0.15 0 0);
|
||||
--warning: oklch(0.82 0.14 85);
|
||||
--warning-foreground: oklch(0.20 0.02 85);
|
||||
--info: oklch(0.70 0.14 240);
|
||||
--info-foreground: oklch(0.15 0 0);
|
||||
|
||||
/* Borders & Inputs */
|
||||
--border: oklch(1 0 0 / 12%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
--ring: oklch(0.78 0.15 75);
|
||||
|
||||
/* Charts - Adjusted for dark */
|
||||
--chart-1: oklch(0.78 0.15 75);
|
||||
--chart-2: oklch(0.68 0.14 200);
|
||||
--chart-3: oklch(0.72 0.16 280);
|
||||
--chart-4: oklch(0.75 0.15 145);
|
||||
--chart-5: oklch(0.72 0.18 25);
|
||||
|
||||
/* Sidebar */
|
||||
--sidebar: oklch(0.18 0.01 75);
|
||||
--sidebar-foreground: oklch(0.96 0.004 75);
|
||||
--sidebar-primary: oklch(0.78 0.15 75);
|
||||
--sidebar-primary-foreground: oklch(0.15 0.02 75);
|
||||
--sidebar-accent: oklch(0.26 0.03 75);
|
||||
--sidebar-accent-foreground: oklch(0.94 0.004 75);
|
||||
--sidebar-border: oklch(1 0 0 / 12%);
|
||||
--sidebar-ring: oklch(0.78 0.15 75);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
BASE STYLES
|
||||
============================================ */
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
@apply bg-background text-foreground antialiased;
|
||||
}
|
||||
|
||||
/* Smooth scrolling */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Focus visible styles */
|
||||
:focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-ring;
|
||||
}
|
||||
|
||||
/* Selection color */
|
||||
::selection {
|
||||
background: oklch(0.75 0.16 75 / 0.3);
|
||||
}
|
||||
|
||||
.dark ::selection {
|
||||
background: oklch(0.78 0.15 75 / 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
UTILITY CLASSES
|
||||
============================================ */
|
||||
@layer utilities {
|
||||
/* Brand text gradient */
|
||||
.text-gradient-brand {
|
||||
background: linear-gradient(90deg, oklch(0.70 0.18 75), oklch(0.65 0.16 85));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Brand background gradient */
|
||||
.bg-gradient-brand {
|
||||
background: linear-gradient(135deg, oklch(0.75 0.16 75), oklch(0.70 0.18 65));
|
||||
}
|
||||
|
||||
/* Subtle brand tint */
|
||||
.bg-brand-subtle {
|
||||
background: linear-gradient(135deg,
|
||||
oklch(0.75 0.16 75 / 0.05),
|
||||
oklch(0.75 0.16 75 / 0.1));
|
||||
}
|
||||
|
||||
/* Brand glow shadow */
|
||||
.shadow-brand {
|
||||
box-shadow:
|
||||
0 0 0 1px oklch(0.75 0.16 75 / 0.1),
|
||||
0 4px 16px oklch(0.75 0.16 75 / 0.15);
|
||||
}
|
||||
|
||||
.shadow-brand-lg {
|
||||
box-shadow:
|
||||
0 0 0 1px oklch(0.75 0.16 75 / 0.15),
|
||||
0 8px 32px oklch(0.75 0.16 75 / 0.2);
|
||||
}
|
||||
|
||||
.dark .shadow-brand {
|
||||
box-shadow:
|
||||
0 0 0 1px oklch(0.78 0.15 75 / 0.2),
|
||||
0 4px 16px oklch(0.78 0.15 75 / 0.2);
|
||||
}
|
||||
|
||||
.dark .shadow-brand-lg {
|
||||
box-shadow:
|
||||
0 0 0 1px oklch(0.78 0.15 75 / 0.25),
|
||||
0 8px 32px oklch(0.78 0.15 75 / 0.25);
|
||||
}
|
||||
|
||||
/* Glass effect */
|
||||
.glass {
|
||||
background: oklch(1 0 0 / 0.8);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.dark .glass {
|
||||
background: oklch(0.14 0.008 75 / 0.8);
|
||||
}
|
||||
|
||||
/* Shimmer loading animation */
|
||||
.shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
oklch(0.95 0 0) 0%,
|
||||
oklch(0.90 0 0) 50%,
|
||||
oklch(0.95 0 0) 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.dark .shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
oklch(0.25 0 0) 0%,
|
||||
oklch(0.30 0 0) 50%,
|
||||
oklch(0.25 0 0) 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
ANIMATIONS
|
||||
============================================ */
|
||||
@keyframes shimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse-brand {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 0 0 oklch(0.75 0.16 75 / 0.4);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 8px oklch(0.75 0.16 75 / 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import { Plus_Jakarta_Sans, JetBrains_Mono } from "next/font/google";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = Geist({
|
||||
const plusJakarta = Plus_Jakarta_Sans({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
weight: ["300", "400", "500", "600", "700", "800"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
const jetbrainsMono = JetBrains_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
weight: ["400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -26,7 +28,7 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
className={`${plusJakarta.variable} ${jetbrainsMono.variable} antialiased`}
|
||||
>
|
||||
{children}
|
||||
<Toaster />
|
||||
|
||||
@@ -4,13 +4,13 @@ import { ArrowRight, Layers, MessageSquare, Zap, Clock, Shield, Users } from 'lu
|
||||
|
||||
export default function LandingPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-b from-zinc-50 to-white dark:from-zinc-950 dark:to-zinc-900">
|
||||
<div className="min-h-screen bg-gradient-to-b from-background to-background-subtle">
|
||||
{/* Navigation */}
|
||||
<nav className="fixed top-0 w-full z-50 border-b bg-white/80 backdrop-blur-sm dark:bg-zinc-950/80 dark:border-zinc-800">
|
||||
<nav className="fixed top-0 w-full z-50 border-b glass">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Layers className="h-8 w-8 text-primary" />
|
||||
<Layers className="h-8 w-8 text-brand" />
|
||||
<span className="text-xl font-bold">Mylder</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -18,7 +18,7 @@ export default function LandingPage() {
|
||||
<Button variant="ghost">Log in</Button>
|
||||
</Link>
|
||||
<Link href="/signup">
|
||||
<Button>Start a Project</Button>
|
||||
<Button variant="brand">Start a Project</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,21 +28,21 @@ export default function LandingPage() {
|
||||
{/* Hero Section */}
|
||||
<section className="pt-32 pb-20 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-primary/10 text-primary text-sm font-medium mb-8">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-brand/10 text-brand text-sm font-medium mb-8">
|
||||
<Zap className="h-4 w-4" />
|
||||
Professional Software Development
|
||||
</div>
|
||||
<h1 className="text-4xl sm:text-6xl font-bold tracking-tight text-zinc-900 dark:text-white mb-6">
|
||||
<h1 className="text-4xl sm:text-6xl font-bold tracking-tight text-foreground mb-6">
|
||||
Your vision,
|
||||
<span className="text-primary"> professionally built</span>
|
||||
<span className="text-gradient-brand"> professionally built</span>
|
||||
</h1>
|
||||
<p className="text-xl text-zinc-600 dark:text-zinc-400 mb-8 max-w-2xl mx-auto">
|
||||
<p className="text-xl text-muted-foreground mb-8 max-w-2xl mx-auto">
|
||||
A lean, professional process to bring your software ideas to life.
|
||||
Chat with us, get real-time updates, and launch with confidence.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Link href="/signup">
|
||||
<Button size="lg" className="gap-2">
|
||||
<Button variant="brand" size="lg" className="gap-2">
|
||||
Describe Your Project <ArrowRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
@@ -56,13 +56,13 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* How It Works */}
|
||||
<section id="how-it-works" className="py-20 px-4 sm:px-6 lg:px-8 bg-zinc-50 dark:bg-zinc-900/50">
|
||||
<section id="how-it-works" className="py-20 px-4 sm:px-6 lg:px-8 bg-muted/50">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold text-zinc-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-foreground mb-4">
|
||||
A streamlined process from idea to launch
|
||||
</h2>
|
||||
<p className="text-lg text-zinc-600 dark:text-zinc-400">
|
||||
<p className="text-lg text-muted-foreground">
|
||||
No complexity. No surprises. Just professional software development.
|
||||
</p>
|
||||
</div>
|
||||
@@ -90,10 +90,10 @@ export default function LandingPage() {
|
||||
<section id="features" className="py-20 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold text-zinc-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-foreground mb-4">
|
||||
Why clients choose Mylder
|
||||
</h2>
|
||||
<p className="text-lg text-zinc-600 dark:text-zinc-400">
|
||||
<p className="text-lg text-muted-foreground">
|
||||
A modern approach to software development that puts you in control.
|
||||
</p>
|
||||
</div>
|
||||
@@ -133,47 +133,47 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* Pricing Section */}
|
||||
<section id="pricing" className="py-20 px-4 sm:px-6 lg:px-8 bg-zinc-50 dark:bg-zinc-900/50">
|
||||
<section id="pricing" className="py-20 px-4 sm:px-6 lg:px-8 bg-muted/50">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold text-zinc-900 dark:text-white mb-4">
|
||||
<h2 className="text-3xl font-bold text-foreground mb-4">
|
||||
Transparent, project-based pricing
|
||||
</h2>
|
||||
<p className="text-lg text-zinc-600 dark:text-zinc-400">
|
||||
<p className="text-lg text-muted-foreground">
|
||||
Every project is unique. Get a custom quote based on your specific needs.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-zinc-900 rounded-2xl border dark:border-zinc-800 p-8 md:p-12">
|
||||
<div className="bg-card rounded-2xl border p-8 md:p-12 shadow-sm">
|
||||
<div className="text-center">
|
||||
<h3 className="text-2xl font-bold text-zinc-900 dark:text-white mb-4">
|
||||
<h3 className="text-2xl font-bold text-foreground mb-4">
|
||||
Start with a free consultation
|
||||
</h3>
|
||||
<p className="text-zinc-600 dark:text-zinc-400 mb-8 max-w-xl mx-auto">
|
||||
<p className="text-muted-foreground mb-8 max-w-xl mx-auto">
|
||||
Describe your project idea and we'll get back to you with a clear scope,
|
||||
timeline, and quote. No obligations, no pressure.
|
||||
</p>
|
||||
<div className="grid sm:grid-cols-3 gap-6 mb-10 text-left">
|
||||
<div className="flex items-start gap-3">
|
||||
<svg className="h-5 w-5 text-primary mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg className="h-5 w-5 text-brand mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span className="text-sm text-zinc-600 dark:text-zinc-400">Fixed-price projects with clear deliverables</span>
|
||||
<span className="text-sm text-muted-foreground">Fixed-price projects with clear deliverables</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<svg className="h-5 w-5 text-primary mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg className="h-5 w-5 text-brand mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span className="text-sm text-zinc-600 dark:text-zinc-400">Milestone-based payments for larger projects</span>
|
||||
<span className="text-sm text-muted-foreground">Milestone-based payments for larger projects</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<svg className="h-5 w-5 text-primary mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg className="h-5 w-5 text-brand mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span className="text-sm text-zinc-600 dark:text-zinc-400">Retainer options for ongoing development</span>
|
||||
<span className="text-sm text-muted-foreground">Retainer options for ongoing development</span>
|
||||
</div>
|
||||
</div>
|
||||
<Link href="/signup">
|
||||
<Button size="lg" className="gap-2">
|
||||
<Button variant="brand" size="lg" className="gap-2">
|
||||
Describe Your Project <ArrowRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
@@ -183,7 +183,7 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-primary text-primary-foreground">
|
||||
<section className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-brand text-brand-foreground">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
Ready to bring your idea to life?
|
||||
@@ -200,13 +200,13 @@ export default function LandingPage() {
|
||||
</section>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="py-12 px-4 sm:px-6 lg:px-8 border-t dark:border-zinc-800">
|
||||
<footer className="py-12 px-4 sm:px-6 lg:px-8 border-t">
|
||||
<div className="max-w-6xl mx-auto flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Layers className="h-6 w-6 text-primary" />
|
||||
<Layers className="h-6 w-6 text-brand" />
|
||||
<span className="font-semibold">Mylder</span>
|
||||
</div>
|
||||
<p className="text-sm text-zinc-500">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
© {new Date().getFullYear()} Mylder. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
@@ -218,23 +218,23 @@ export default function LandingPage() {
|
||||
function StepCard({ step, title, description }: { step: string; title: string; description: string }) {
|
||||
return (
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-xl font-bold mx-auto mb-4">
|
||||
<div className="w-12 h-12 rounded-full bg-brand text-brand-foreground flex items-center justify-center text-xl font-bold mx-auto mb-4">
|
||||
{step}
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-zinc-900 dark:text-white mb-2">{title}</h3>
|
||||
<p className="text-zinc-600 dark:text-zinc-400">{description}</p>
|
||||
<h3 className="text-lg font-semibold text-foreground mb-2">{title}</h3>
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FeatureCard({ icon, title, description }: { icon: React.ReactNode; title: string; description: string }) {
|
||||
return (
|
||||
<div className="p-6 rounded-xl border bg-white dark:bg-zinc-900 dark:border-zinc-800">
|
||||
<div className="w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center text-primary mb-4">
|
||||
<div className="p-6 rounded-xl border bg-card shadow-sm hover:shadow-md transition-shadow">
|
||||
<div className="w-12 h-12 rounded-lg bg-brand/10 flex items-center justify-center text-brand mb-4">
|
||||
{icon}
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-zinc-900 dark:text-white mb-2">{title}</h3>
|
||||
<p className="text-zinc-600 dark:text-zinc-400">{description}</p>
|
||||
<h3 className="text-lg font-semibold text-foreground mb-2">{title}</h3>
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ export function DashboardNav({ user }: { user: SupabaseUser }) {
|
||||
.toUpperCase() || user.email?.[0].toUpperCase() || '?'
|
||||
|
||||
return (
|
||||
<nav className="fixed top-0 w-full z-50 border-b bg-white/80 backdrop-blur-sm dark:bg-zinc-950/80 dark:border-zinc-800">
|
||||
<nav className="fixed top-0 w-full z-50 border-b glass">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between h-16 items-center">
|
||||
<div className="flex items-center gap-8">
|
||||
<Link href="/dashboard" className="flex items-center gap-2">
|
||||
<Bot className="h-8 w-8 text-primary" />
|
||||
<Bot className="h-8 w-8 text-brand" />
|
||||
<span className="text-xl font-bold">Mylder</span>
|
||||
</Link>
|
||||
<div className="hidden md:flex items-center gap-4">
|
||||
@@ -61,7 +61,7 @@ export function DashboardNav({ user }: { user: SupabaseUser }) {
|
||||
{user.user_metadata?.full_name && (
|
||||
<p className="font-medium">{user.user_metadata.full_name}</p>
|
||||
)}
|
||||
<p className="text-sm text-zinc-500 truncate">{user.email}</p>
|
||||
<p className="text-sm text-muted-foreground truncate">{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
@@ -11,10 +11,26 @@ const badgeVariants = cva(
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
||||
brand:
|
||||
"border-transparent bg-brand text-brand-foreground [a&]:hover:bg-brand/90",
|
||||
"brand-outline":
|
||||
"border-brand/30 bg-brand/10 text-brand [a&]:hover:bg-brand/20",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
success:
|
||||
"border-transparent bg-success text-success-foreground [a&]:hover:bg-success/90",
|
||||
"success-outline":
|
||||
"border-success/30 bg-success/10 text-success [a&]:hover:bg-success/20",
|
||||
warning:
|
||||
"border-transparent bg-warning text-warning-foreground [a&]:hover:bg-warning/90",
|
||||
"warning-outline":
|
||||
"border-warning/30 bg-warning/10 text-warning [a&]:hover:bg-warning/20",
|
||||
info:
|
||||
"border-transparent bg-info text-info-foreground [a&]:hover:bg-info/90",
|
||||
"info-outline":
|
||||
"border-info/30 bg-info/10 text-info [a&]:hover:bg-info/20",
|
||||
outline:
|
||||
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
||||
},
|
||||
|
||||
@@ -10,15 +10,24 @@ const buttonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
brand:
|
||||
"bg-brand text-brand-foreground hover:bg-brand/90 shadow-brand hover:shadow-brand-lg transition-shadow",
|
||||
destructive:
|
||||
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
success:
|
||||
"bg-success text-success-foreground hover:bg-success/90",
|
||||
outline:
|
||||
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||
"outline-brand":
|
||||
"border-brand/30 bg-brand/5 text-brand hover:bg-brand/10 hover:border-brand/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
"ghost-brand":
|
||||
"text-brand hover:bg-brand/10 hover:text-brand",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
"link-brand": "text-brand underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
|
||||
546
src/styles/design-system.md
Normal file
546
src/styles/design-system.md
Normal file
@@ -0,0 +1,546 @@
|
||||
# Mylder Brand Design System
|
||||
|
||||
## Brand Identity
|
||||
|
||||
**Tagline**: Intelligent Automation, Human Touch
|
||||
|
||||
**Personality**: Professional, Approachable, Innovative, Trustworthy
|
||||
|
||||
**Aesthetic**: Refined Tech-Forward Minimalism with Warm Energy
|
||||
|
||||
---
|
||||
|
||||
## Color System (OKLCH)
|
||||
|
||||
### Philosophy
|
||||
Using OKLCH color space for perceptually uniform colors. Warm stone neutrals replace cold grays to feel more human/approachable for an AI platform. Amber accent represents energy and intelligence.
|
||||
|
||||
### Primary Palette
|
||||
|
||||
#### Brand Colors
|
||||
```css
|
||||
/* Amber - Primary Brand Accent */
|
||||
--brand: oklch(0.75 0.16 75); /* Vibrant amber */
|
||||
--brand-hover: oklch(0.70 0.18 75); /* Darker on hover */
|
||||
--brand-muted: oklch(0.85 0.08 75); /* Soft amber for backgrounds */
|
||||
--brand-foreground: oklch(0.20 0.02 75); /* Dark text on brand */
|
||||
|
||||
/* Stone - Warm Neutrals (replaces zinc/gray) */
|
||||
--stone-50: oklch(0.985 0.002 75); /* Near white, warm */
|
||||
--stone-100: oklch(0.965 0.004 75); /* Subtle warm */
|
||||
--stone-200: oklch(0.925 0.006 75); /* Light warm */
|
||||
--stone-300: oklch(0.87 0.008 75); /* Medium-light */
|
||||
--stone-400: oklch(0.70 0.01 75); /* Medium */
|
||||
--stone-500: oklch(0.55 0.012 75); /* Medium-dark */
|
||||
--stone-600: oklch(0.45 0.014 75); /* Dark */
|
||||
--stone-700: oklch(0.35 0.012 75); /* Darker */
|
||||
--stone-800: oklch(0.25 0.01 75); /* Very dark */
|
||||
--stone-900: oklch(0.18 0.008 75); /* Near black, warm */
|
||||
--stone-950: oklch(0.12 0.006 75); /* Deepest */
|
||||
```
|
||||
|
||||
### Semantic Colors
|
||||
|
||||
#### Light Mode
|
||||
```css
|
||||
:root {
|
||||
/* Backgrounds */
|
||||
--background: oklch(0.99 0.002 75); /* Warm white */
|
||||
--background-subtle: oklch(0.975 0.004 75); /* Subtle warmth */
|
||||
--foreground: oklch(0.15 0.01 75); /* Warm black */
|
||||
|
||||
/* Cards & Surfaces */
|
||||
--card: oklch(1 0 0); /* Pure white cards */
|
||||
--card-foreground: oklch(0.15 0.01 75);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.15 0.01 75);
|
||||
|
||||
/* Primary (Dark buttons/CTAs) */
|
||||
--primary: oklch(0.20 0.01 75);
|
||||
--primary-foreground: oklch(0.98 0.002 75);
|
||||
|
||||
/* Secondary (Light buttons) */
|
||||
--secondary: oklch(0.955 0.006 75);
|
||||
--secondary-foreground: oklch(0.25 0.01 75);
|
||||
|
||||
/* Muted (Disabled, hints) */
|
||||
--muted: oklch(0.955 0.006 75);
|
||||
--muted-foreground: oklch(0.50 0.01 75);
|
||||
|
||||
/* Accent (Amber brand) */
|
||||
--accent: oklch(0.92 0.06 75);
|
||||
--accent-foreground: oklch(0.25 0.02 75);
|
||||
|
||||
/* Brand (Primary amber) */
|
||||
--brand: oklch(0.75 0.16 75);
|
||||
--brand-foreground: oklch(0.20 0.02 75);
|
||||
|
||||
/* Destructive */
|
||||
--destructive: oklch(0.55 0.22 25);
|
||||
--destructive-foreground: oklch(0.98 0 0);
|
||||
|
||||
/* Success */
|
||||
--success: oklch(0.65 0.18 145);
|
||||
--success-foreground: oklch(0.98 0 0);
|
||||
|
||||
/* Warning */
|
||||
--warning: oklch(0.80 0.15 85);
|
||||
--warning-foreground: oklch(0.25 0.02 85);
|
||||
|
||||
/* Info */
|
||||
--info: oklch(0.65 0.15 240);
|
||||
--info-foreground: oklch(0.98 0 0);
|
||||
|
||||
/* Borders & Inputs */
|
||||
--border: oklch(0.90 0.006 75);
|
||||
--input: oklch(0.90 0.006 75);
|
||||
--ring: oklch(0.75 0.16 75); /* Amber focus ring */
|
||||
}
|
||||
```
|
||||
|
||||
#### Dark Mode
|
||||
```css
|
||||
.dark {
|
||||
/* Backgrounds */
|
||||
--background: oklch(0.14 0.008 75); /* Warm dark */
|
||||
--background-subtle: oklch(0.18 0.01 75);
|
||||
--foreground: oklch(0.96 0.004 75); /* Warm white */
|
||||
|
||||
/* Cards & Surfaces */
|
||||
--card: oklch(0.20 0.01 75);
|
||||
--card-foreground: oklch(0.96 0.004 75);
|
||||
--popover: oklch(0.20 0.01 75);
|
||||
--popover-foreground: oklch(0.96 0.004 75);
|
||||
|
||||
/* Primary (Light buttons on dark) */
|
||||
--primary: oklch(0.94 0.004 75);
|
||||
--primary-foreground: oklch(0.18 0.01 75);
|
||||
|
||||
/* Secondary */
|
||||
--secondary: oklch(0.26 0.012 75);
|
||||
--secondary-foreground: oklch(0.94 0.004 75);
|
||||
|
||||
/* Muted */
|
||||
--muted: oklch(0.26 0.012 75);
|
||||
--muted-foreground: oklch(0.65 0.01 75);
|
||||
|
||||
/* Accent (Amber, slightly brighter for dark) */
|
||||
--accent: oklch(0.30 0.04 75);
|
||||
--accent-foreground: oklch(0.94 0.004 75);
|
||||
|
||||
/* Brand (Amber, adjusted for dark) */
|
||||
--brand: oklch(0.78 0.15 75);
|
||||
--brand-foreground: oklch(0.15 0.02 75);
|
||||
|
||||
/* Destructive */
|
||||
--destructive: oklch(0.65 0.20 22);
|
||||
--destructive-foreground: oklch(0.98 0 0);
|
||||
|
||||
/* Success */
|
||||
--success: oklch(0.70 0.16 145);
|
||||
--success-foreground: oklch(0.15 0 0);
|
||||
|
||||
/* Warning */
|
||||
--warning: oklch(0.82 0.14 85);
|
||||
--warning-foreground: oklch(0.20 0.02 85);
|
||||
|
||||
/* Info */
|
||||
--info: oklch(0.70 0.14 240);
|
||||
--info-foreground: oklch(0.15 0 0);
|
||||
|
||||
/* Borders & Inputs */
|
||||
--border: oklch(1 0 0 / 12%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.78 0.15 75);
|
||||
}
|
||||
```
|
||||
|
||||
### Chart Colors (Data Visualization)
|
||||
```css
|
||||
/* Light mode - vibrant, distinguishable */
|
||||
--chart-1: oklch(0.75 0.16 75); /* Amber (brand) */
|
||||
--chart-2: oklch(0.60 0.15 200); /* Teal */
|
||||
--chart-3: oklch(0.65 0.18 280); /* Purple */
|
||||
--chart-4: oklch(0.70 0.16 145); /* Green */
|
||||
--chart-5: oklch(0.65 0.20 25); /* Coral */
|
||||
|
||||
/* Dark mode - adjusted for contrast */
|
||||
--chart-1: oklch(0.78 0.15 75);
|
||||
--chart-2: oklch(0.68 0.14 200);
|
||||
--chart-3: oklch(0.72 0.16 280);
|
||||
--chart-4: oklch(0.75 0.15 145);
|
||||
--chart-5: oklch(0.72 0.18 25);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
### Font Stack
|
||||
```css
|
||||
/* Primary - Display & Headings */
|
||||
--font-display: 'Plus Jakarta Sans', system-ui, sans-serif;
|
||||
|
||||
/* Body - Reading & UI */
|
||||
--font-body: 'Plus Jakarta Sans', system-ui, sans-serif;
|
||||
|
||||
/* Mono - Code & Technical */
|
||||
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
```
|
||||
|
||||
### Type Scale (Fluid)
|
||||
```css
|
||||
/* Using clamp() for fluid typography */
|
||||
--text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.8rem); /* 12-13px */
|
||||
--text-sm: clamp(0.8125rem, 0.77rem + 0.21vw, 0.875rem); /* 13-14px */
|
||||
--text-base: clamp(0.9375rem, 0.9rem + 0.19vw, 1rem); /* 15-16px */
|
||||
--text-lg: clamp(1.0625rem, 1rem + 0.31vw, 1.125rem); /* 17-18px */
|
||||
--text-xl: clamp(1.1875rem, 1.1rem + 0.44vw, 1.25rem); /* 19-20px */
|
||||
--text-2xl: clamp(1.375rem, 1.25rem + 0.63vw, 1.5rem); /* 22-24px */
|
||||
--text-3xl: clamp(1.625rem, 1.45rem + 0.88vw, 1.875rem); /* 26-30px */
|
||||
--text-4xl: clamp(2rem, 1.75rem + 1.25vw, 2.25rem); /* 32-36px */
|
||||
--text-5xl: clamp(2.5rem, 2.1rem + 2vw, 3rem); /* 40-48px */
|
||||
--text-6xl: clamp(3rem, 2.5rem + 2.5vw, 3.75rem); /* 48-60px */
|
||||
```
|
||||
|
||||
### Line Heights
|
||||
```css
|
||||
--leading-none: 1;
|
||||
--leading-tight: 1.25;
|
||||
--leading-snug: 1.375;
|
||||
--leading-normal: 1.5;
|
||||
--leading-relaxed: 1.625;
|
||||
--leading-loose: 2;
|
||||
```
|
||||
|
||||
### Font Weights
|
||||
```css
|
||||
--font-light: 300;
|
||||
--font-normal: 400;
|
||||
--font-medium: 500;
|
||||
--font-semibold: 600;
|
||||
--font-bold: 700;
|
||||
--font-extrabold: 800;
|
||||
```
|
||||
|
||||
### Letter Spacing
|
||||
```css
|
||||
--tracking-tighter: -0.05em;
|
||||
--tracking-tight: -0.025em;
|
||||
--tracking-normal: 0;
|
||||
--tracking-wide: 0.025em;
|
||||
--tracking-wider: 0.05em;
|
||||
--tracking-widest: 0.1em;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spacing & Layout
|
||||
|
||||
### Spacing Scale
|
||||
```css
|
||||
/* Base unit: 4px */
|
||||
--space-0: 0;
|
||||
--space-px: 1px;
|
||||
--space-0.5: 0.125rem; /* 2px */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-1.5: 0.375rem; /* 6px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-2.5: 0.625rem; /* 10px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-3.5: 0.875rem; /* 14px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-7: 1.75rem; /* 28px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-9: 2.25rem; /* 36px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--space-14: 3.5rem; /* 56px */
|
||||
--space-16: 4rem; /* 64px */
|
||||
--space-20: 5rem; /* 80px */
|
||||
--space-24: 6rem; /* 96px */
|
||||
--space-28: 7rem; /* 112px */
|
||||
--space-32: 8rem; /* 128px */
|
||||
```
|
||||
|
||||
### Container Widths
|
||||
```css
|
||||
--container-xs: 20rem; /* 320px */
|
||||
--container-sm: 24rem; /* 384px */
|
||||
--container-md: 28rem; /* 448px */
|
||||
--container-lg: 32rem; /* 512px */
|
||||
--container-xl: 36rem; /* 576px */
|
||||
--container-2xl: 42rem; /* 672px */
|
||||
--container-3xl: 48rem; /* 768px */
|
||||
--container-4xl: 56rem; /* 896px */
|
||||
--container-5xl: 64rem; /* 1024px */
|
||||
--container-6xl: 72rem; /* 1152px */
|
||||
--container-7xl: 80rem; /* 1280px */
|
||||
--container-full: 100%;
|
||||
```
|
||||
|
||||
### Breakpoints
|
||||
```css
|
||||
--screen-sm: 640px;
|
||||
--screen-md: 768px;
|
||||
--screen-lg: 1024px;
|
||||
--screen-xl: 1280px;
|
||||
--screen-2xl: 1536px;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Border Radius
|
||||
|
||||
```css
|
||||
--radius-none: 0;
|
||||
--radius-sm: 0.25rem; /* 4px - subtle */
|
||||
--radius-md: 0.5rem; /* 8px - default */
|
||||
--radius-lg: 0.75rem; /* 12px - cards */
|
||||
--radius-xl: 1rem; /* 16px - modals */
|
||||
--radius-2xl: 1.5rem; /* 24px - large surfaces */
|
||||
--radius-3xl: 2rem; /* 32px - hero elements */
|
||||
--radius-full: 9999px; /* Pills, avatars */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shadows
|
||||
|
||||
### Light Mode
|
||||
```css
|
||||
--shadow-xs: 0 1px 2px oklch(0 0 0 / 0.04);
|
||||
--shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
|
||||
--shadow-md: 0 4px 6px -1px oklch(0 0 0 / 0.06), 0 2px 4px -1px oklch(0 0 0 / 0.04);
|
||||
--shadow-lg: 0 10px 15px -3px oklch(0 0 0 / 0.06), 0 4px 6px -2px oklch(0 0 0 / 0.03);
|
||||
--shadow-xl: 0 20px 25px -5px oklch(0 0 0 / 0.08), 0 10px 10px -5px oklch(0 0 0 / 0.03);
|
||||
--shadow-2xl: 0 25px 50px -12px oklch(0 0 0 / 0.15);
|
||||
|
||||
/* Brand glow (for CTAs) */
|
||||
--shadow-brand: 0 0 0 1px oklch(0.75 0.16 75 / 0.1),
|
||||
0 4px 16px oklch(0.75 0.16 75 / 0.15);
|
||||
--shadow-brand-lg: 0 0 0 1px oklch(0.75 0.16 75 / 0.15),
|
||||
0 8px 32px oklch(0.75 0.16 75 / 0.2);
|
||||
```
|
||||
|
||||
### Dark Mode
|
||||
```css
|
||||
--shadow-xs: 0 1px 2px oklch(0 0 0 / 0.2);
|
||||
--shadow-sm: 0 1px 3px oklch(0 0 0 / 0.3), 0 1px 2px oklch(0 0 0 / 0.2);
|
||||
--shadow-md: 0 4px 6px -1px oklch(0 0 0 / 0.3), 0 2px 4px -1px oklch(0 0 0 / 0.2);
|
||||
--shadow-lg: 0 10px 15px -3px oklch(0 0 0 / 0.3), 0 4px 6px -2px oklch(0 0 0 / 0.2);
|
||||
--shadow-xl: 0 20px 25px -5px oklch(0 0 0 / 0.35), 0 10px 10px -5px oklch(0 0 0 / 0.2);
|
||||
--shadow-2xl: 0 25px 50px -12px oklch(0 0 0 / 0.5);
|
||||
|
||||
/* Brand glow (brighter for dark) */
|
||||
--shadow-brand: 0 0 0 1px oklch(0.78 0.15 75 / 0.2),
|
||||
0 4px 16px oklch(0.78 0.15 75 / 0.2);
|
||||
--shadow-brand-lg: 0 0 0 1px oklch(0.78 0.15 75 / 0.25),
|
||||
0 8px 32px oklch(0.78 0.15 75 / 0.25);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Motion & Animation
|
||||
|
||||
### Durations
|
||||
```css
|
||||
--duration-instant: 0ms;
|
||||
--duration-fast: 100ms;
|
||||
--duration-normal: 200ms;
|
||||
--duration-slow: 300ms;
|
||||
--duration-slower: 500ms;
|
||||
--duration-slowest: 700ms;
|
||||
```
|
||||
|
||||
### Easings
|
||||
```css
|
||||
--ease-linear: linear;
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
```
|
||||
|
||||
### Common Animations
|
||||
```css
|
||||
/* Fade */
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
/* Slide up */
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale */
|
||||
@keyframes scale-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pulse (for loading states) */
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
/* Shimmer (skeleton loading) */
|
||||
@keyframes shimmer {
|
||||
0% { background-position: -200% 0; }
|
||||
100% { background-position: 200% 0; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Patterns
|
||||
|
||||
### Button Variants
|
||||
```tsx
|
||||
// Primary (brand amber)
|
||||
<Button variant="brand">Get Started</Button>
|
||||
|
||||
// Default (dark)
|
||||
<Button variant="default">Submit</Button>
|
||||
|
||||
// Secondary (light)
|
||||
<Button variant="secondary">Cancel</Button>
|
||||
|
||||
// Ghost (transparent)
|
||||
<Button variant="ghost">Menu</Button>
|
||||
|
||||
// Outline (bordered)
|
||||
<Button variant="outline">Learn More</Button>
|
||||
|
||||
// Destructive (red)
|
||||
<Button variant="destructive">Delete</Button>
|
||||
```
|
||||
|
||||
### Card Styles
|
||||
```tsx
|
||||
// Default card
|
||||
<Card className="bg-card shadow-sm hover:shadow-md transition-shadow">
|
||||
|
||||
// Elevated card (more prominent)
|
||||
<Card className="bg-card shadow-lg">
|
||||
|
||||
// Interactive card
|
||||
<Card className="bg-card shadow-sm hover:shadow-lg hover:border-brand/20 transition-all cursor-pointer">
|
||||
|
||||
// Brand accent card
|
||||
<Card className="bg-gradient-to-br from-brand/5 to-brand/10 border-brand/20">
|
||||
```
|
||||
|
||||
### Input Styles
|
||||
```tsx
|
||||
// Default input
|
||||
<Input className="border-input focus:border-brand focus:ring-brand/20" />
|
||||
|
||||
// With icon
|
||||
<div className="relative">
|
||||
<Icon className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input className="pl-10" />
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gradients
|
||||
|
||||
### Brand Gradients
|
||||
```css
|
||||
/* Subtle background */
|
||||
--gradient-brand-subtle: linear-gradient(135deg,
|
||||
oklch(0.75 0.16 75 / 0.05) 0%,
|
||||
oklch(0.75 0.16 75 / 0.1) 100%);
|
||||
|
||||
/* Hero gradient */
|
||||
--gradient-brand-hero: linear-gradient(135deg,
|
||||
oklch(0.75 0.16 75) 0%,
|
||||
oklch(0.70 0.18 65) 100%);
|
||||
|
||||
/* Text gradient */
|
||||
--gradient-brand-text: linear-gradient(90deg,
|
||||
oklch(0.70 0.18 75) 0%,
|
||||
oklch(0.65 0.16 85) 100%);
|
||||
```
|
||||
|
||||
### Background Gradients
|
||||
```css
|
||||
/* Warm fade (light mode) */
|
||||
--gradient-warm: linear-gradient(180deg,
|
||||
oklch(0.99 0.002 75) 0%,
|
||||
oklch(0.975 0.006 75) 100%);
|
||||
|
||||
/* Dark gradient */
|
||||
--gradient-dark: linear-gradient(180deg,
|
||||
oklch(0.14 0.008 75) 0%,
|
||||
oklch(0.10 0.006 75) 100%);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Iconography
|
||||
|
||||
### Icon Library
|
||||
- Primary: **Lucide React** (consistent with shadcn/ui)
|
||||
- Size scale: 16px, 20px, 24px, 32px
|
||||
- Stroke width: 1.5px (default), 2px (bold)
|
||||
|
||||
### Icon Colors
|
||||
```css
|
||||
/* Default */
|
||||
.icon { color: var(--foreground); }
|
||||
|
||||
/* Muted */
|
||||
.icon-muted { color: var(--muted-foreground); }
|
||||
|
||||
/* Brand */
|
||||
.icon-brand { color: var(--brand); }
|
||||
|
||||
/* On interactive elements */
|
||||
.btn:hover .icon { color: var(--brand); }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage Guidelines
|
||||
|
||||
### Do
|
||||
- Use warm stone colors for neutrals
|
||||
- Use amber brand color for primary CTAs and accents
|
||||
- Maintain consistent spacing (multiples of 4px)
|
||||
- Use subtle shadows and transitions
|
||||
- Ensure 4.5:1 contrast ratio for text
|
||||
|
||||
### Don't
|
||||
- Mix cold grays with warm neutrals
|
||||
- Overuse the brand amber color
|
||||
- Use pure black (#000) or white (#fff)
|
||||
- Add excessive shadows or effects
|
||||
- Forget dark mode support
|
||||
|
||||
---
|
||||
|
||||
## Implementation
|
||||
|
||||
See `globals.css` for the complete CSS implementation with all variables defined.
|
||||
Reference in New Issue
Block a user