feat: simplify theme system to single Warm Sage brand palette
Consolidate from 11 themes to one cohesive Warm Sage palette across landing page, auth layout, dashboard components, kanban columns, demo banner, theme picker, and CSS variables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,10 +7,10 @@ export default function AuthLayout({ children }: { children: React.ReactNode })
|
||||
return (
|
||||
<div className="min-h-screen flex bg-[#FAFAF7]">
|
||||
{/* Left brand panel — hidden on mobile */}
|
||||
<div className="hidden lg:flex lg:w-[480px] xl:w-[540px] relative flex-col justify-between bg-[#1C1917] p-10 overflow-hidden">
|
||||
<div className="hidden lg:flex lg:w-[480px] xl:w-[540px] relative flex-col justify-between bg-[#2D3436] p-10 overflow-hidden">
|
||||
{/* Decorative blurs */}
|
||||
<div className="absolute top-0 right-0 w-80 h-80 rounded-full bg-[#E07A3A]/15 blur-[100px] pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-0 w-64 h-64 rounded-full bg-[#0D7C66]/10 blur-[80px] pointer-events-none" />
|
||||
<div className="absolute top-0 right-0 w-80 h-80 rounded-full bg-[#6B8F71]/15 blur-[100px] pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-0 w-64 h-64 rounded-full bg-[#C4856A]/10 blur-[80px] pointer-events-none" />
|
||||
|
||||
{/* Subtle grid */}
|
||||
<div
|
||||
@@ -40,15 +40,15 @@ export default function AuthLayout({ children }: { children: React.ReactNode })
|
||||
<div className="relative">
|
||||
<h2 className="font-heading text-3xl font-bold text-white leading-snug mb-4">
|
||||
Home maintenance,<br />
|
||||
<span className="text-[#E07A3A]">simplified.</span>
|
||||
<span className="text-[#8FB896]">simplified.</span>
|
||||
</h2>
|
||||
<p className="text-[#A8A29E] leading-relaxed max-w-sm">
|
||||
<p className="text-[#9A9E97] leading-relaxed max-w-sm">
|
||||
Track tasks, organize contractors, and store important
|
||||
documents — all in one place built for homeowners.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="relative text-xs text-[#78716C]">
|
||||
<p className="relative text-xs text-[#8A8F87]">
|
||||
© {new Date().getFullYear()} Casera
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -8,8 +8,8 @@ export default function DemoLandingPage() {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col items-center justify-center bg-[#FAFAF7] px-6 relative overflow-hidden">
|
||||
{/* Decorative background */}
|
||||
<div className="absolute top-20 right-[-10%] w-[500px] h-[500px] rounded-full bg-[#E07A3A]/[0.04] blur-3xl pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-[-5%] w-[300px] h-[300px] rounded-full bg-[#0D7C66]/[0.03] blur-3xl pointer-events-none" />
|
||||
<div className="absolute top-20 right-[-10%] w-[500px] h-[500px] rounded-full bg-[#6B8F71]/[0.04] blur-3xl pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-[-5%] w-[300px] h-[300px] rounded-full bg-[#C4856A]/[0.03] blur-3xl pointer-events-none" />
|
||||
|
||||
<div className="relative mx-auto max-w-lg text-center">
|
||||
{/* Logo */}
|
||||
@@ -21,16 +21,16 @@ export default function DemoLandingPage() {
|
||||
height={36}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span className="font-heading text-2xl font-bold tracking-tight text-[#1C1917]">
|
||||
<span className="font-heading text-2xl font-bold tracking-tight text-[#2D3436]">
|
||||
Casera
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Hero */}
|
||||
<h1 className="font-heading text-4xl font-bold tracking-tight text-[#1C1917]">
|
||||
<h1 className="font-heading text-4xl font-bold tracking-tight text-[#2D3436]">
|
||||
See Casera in action
|
||||
</h1>
|
||||
<p className="mt-4 text-lg text-[#78716C] leading-relaxed">
|
||||
<p className="mt-4 text-lg text-[#8A8F87] leading-relaxed">
|
||||
Explore the full app with sample data. No account needed —
|
||||
just click and start exploring.
|
||||
</p>
|
||||
@@ -39,7 +39,7 @@ export default function DemoLandingPage() {
|
||||
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<Link
|
||||
href="/demo/app"
|
||||
className="group inline-flex items-center gap-2.5 rounded-full bg-[#E07A3A] px-8 py-4 text-base font-semibold text-white shadow-lg shadow-[#E07A3A]/20 hover:bg-[#C4632A] transition-all"
|
||||
className="group inline-flex items-center gap-2.5 rounded-full bg-[#C4856A] px-8 py-4 text-base font-semibold text-white shadow-lg shadow-[#C4856A]/20 hover:bg-[#A86B52] transition-all"
|
||||
>
|
||||
<Play className="size-4" />
|
||||
Launch Demo
|
||||
@@ -48,9 +48,9 @@ export default function DemoLandingPage() {
|
||||
</div>
|
||||
|
||||
{/* Login link */}
|
||||
<p className="mt-8 text-sm text-[#A8A29E]">
|
||||
<p className="mt-8 text-sm text-[#9A9E97]">
|
||||
Already have an account?{" "}
|
||||
<Link href="/login" className="text-[#E07A3A] font-medium hover:underline">
|
||||
<Link href="/login" className="text-[#6B8F71] font-medium hover:underline">
|
||||
Sign In
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
+28
-13
@@ -49,25 +49,40 @@
|
||||
--radius-4xl: calc(var(--radius) + 16px);
|
||||
|
||||
/* App-specific theme-aware Tailwind utilities */
|
||||
--color-bg-primary: #FFFFFF;
|
||||
--color-bg-secondary: #F7F7F7;
|
||||
--color-text-primary: #1C1917;
|
||||
--color-text-secondary: #78716C;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
--color-bg-primary: var(--color-bg-primary);
|
||||
--color-bg-secondary: var(--color-bg-secondary);
|
||||
--color-text-primary: var(--color-text-primary);
|
||||
--color-text-secondary: var(--color-text-secondary);
|
||||
--color-text-on-primary: var(--color-text-on-primary);
|
||||
--color-app-primary: var(--color-primary);
|
||||
--color-app-secondary: var(--color-secondary);
|
||||
--color-app-accent: var(--color-accent);
|
||||
--color-app-error: var(--color-error);
|
||||
|
||||
/* Landing page brand colors (theme-independent) */
|
||||
--color-brand-orange: #E07A3A;
|
||||
--color-brand-orange-dark: #C4632A;
|
||||
--color-brand-orange-light: #FFF3EB;
|
||||
--color-brand-teal: #0D7C66;
|
||||
--color-brand-teal-light: #ECFDF5;
|
||||
--color-brand-slate: #1C1917;
|
||||
/* Brand colors — Warm Sage palette */
|
||||
--color-brand-sage: #6B8F71;
|
||||
--color-brand-sage-light: #EDF2ED;
|
||||
--color-brand-clay: #C4856A;
|
||||
--color-brand-clay-light: #FDF3EE;
|
||||
--color-brand-charcoal: #2D3436;
|
||||
--color-brand-cream: #FAFAF7;
|
||||
--color-brand-linen: #F2EFE9;
|
||||
--color-brand-stone: #E8E3DC;
|
||||
|
||||
/* Legacy brand aliases (for any remaining references) */
|
||||
--color-brand-orange: #C4856A;
|
||||
--color-brand-orange-dark: #A86B52;
|
||||
--color-brand-orange-light: #FDF3EE;
|
||||
--color-brand-teal: #6B8F71;
|
||||
--color-brand-teal-light: #EDF2ED;
|
||||
--color-brand-slate: #2D3436;
|
||||
--color-brand-warm: #FFFFFF;
|
||||
|
||||
/* Warm shadow tokens */
|
||||
--shadow-warm-sm: 0 1px 3px rgba(45, 52, 54, 0.06), 0 1px 2px rgba(45, 52, 54, 0.04);
|
||||
--shadow-warm-md: 0 4px 12px rgba(45, 52, 54, 0.07), 0 2px 4px rgba(45, 52, 54, 0.04);
|
||||
--shadow-warm-lg: 0 8px 24px rgba(45, 52, 54, 0.08), 0 4px 8px rgba(45, 52, 54, 0.04);
|
||||
|
||||
/* Animation tokens */
|
||||
--animate-fade-up: fade-up 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||
--animate-fade-in: fade-in 0.6s ease both;
|
||||
@@ -76,7 +91,7 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--radius: 0.75rem;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
+53
-53
@@ -18,14 +18,14 @@ const features = [
|
||||
title: "Smart Task Tracking",
|
||||
description:
|
||||
"Kanban boards, recurring schedules, and due date reminders keep every repair and project on track.",
|
||||
color: "bg-[#FFF3EB] text-[#E07A3A]",
|
||||
color: "bg-[#EDF2ED] text-[#6B8F71]",
|
||||
},
|
||||
{
|
||||
icon: HardHat,
|
||||
title: "Contractor Rolodex",
|
||||
description:
|
||||
"Store contact details, specialties, and notes for every service provider. Never lose a plumber's number again.",
|
||||
color: "bg-[#ECFDF5] text-[#0D7C66]",
|
||||
color: "bg-[#FDF3EE] text-[#C4856A]",
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
@@ -82,9 +82,9 @@ const highlights = [
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-white text-[#1C1917] font-sans selection:bg-[#E07A3A]/20">
|
||||
<div className="min-h-screen bg-[#FAFAF7] text-[#2D3436] font-sans selection:bg-[#6B8F71]/20">
|
||||
{/* ─── Navigation ─── */}
|
||||
<nav className="fixed top-0 w-full z-50 bg-white/80 backdrop-blur-xl border-b border-[#E7E5E4]/60">
|
||||
<nav className="fixed top-0 w-full z-50 bg-[#FAFAF7]/80 backdrop-blur-xl border-b border-[#E8E3DC]/60">
|
||||
<div className="max-w-7xl mx-auto px-6 flex items-center justify-between h-16">
|
||||
<Link href="/" className="flex items-center gap-2.5">
|
||||
<Image
|
||||
@@ -94,7 +94,7 @@ export default function HomePage() {
|
||||
height={32}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span className="font-heading text-xl font-bold tracking-tight text-[#1C1917]">
|
||||
<span className="font-heading text-xl font-bold tracking-tight text-[#2D3436]">
|
||||
Casera
|
||||
</span>
|
||||
</Link>
|
||||
@@ -102,19 +102,19 @@ export default function HomePage() {
|
||||
<div className="hidden md:flex items-center gap-8">
|
||||
<a
|
||||
href="#features"
|
||||
className="text-sm font-medium text-[#78716C] hover:text-[#1C1917] transition-colors"
|
||||
className="text-sm font-medium text-[#8A8F87] hover:text-[#2D3436] transition-colors"
|
||||
>
|
||||
Features
|
||||
</a>
|
||||
<a
|
||||
href="#how-it-works"
|
||||
className="text-sm font-medium text-[#78716C] hover:text-[#1C1917] transition-colors"
|
||||
className="text-sm font-medium text-[#8A8F87] hover:text-[#2D3436] transition-colors"
|
||||
>
|
||||
How It Works
|
||||
</a>
|
||||
<Link
|
||||
href="/demo"
|
||||
className="text-sm font-medium text-[#78716C] hover:text-[#1C1917] transition-colors"
|
||||
className="text-sm font-medium text-[#8A8F87] hover:text-[#2D3436] transition-colors"
|
||||
>
|
||||
Demo
|
||||
</Link>
|
||||
@@ -123,13 +123,13 @@ export default function HomePage() {
|
||||
<div className="flex items-center gap-3">
|
||||
<Link
|
||||
href="/login"
|
||||
className="text-sm font-medium text-[#78716C] hover:text-[#1C1917] transition-colors hidden sm:inline-flex"
|
||||
className="text-sm font-medium text-[#8A8F87] hover:text-[#2D3436] transition-colors hidden sm:inline-flex"
|
||||
>
|
||||
Sign In
|
||||
</Link>
|
||||
<Link
|
||||
href="/register"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-[#1C1917] px-5 py-2 text-sm font-semibold text-white hover:bg-[#292524] transition-colors"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-[#2D3436] px-5 py-2 text-sm font-semibold text-white hover:bg-[#3D4446] transition-colors"
|
||||
>
|
||||
Get Started
|
||||
<ArrowRight className="size-3.5" />
|
||||
@@ -142,14 +142,14 @@ export default function HomePage() {
|
||||
<section className="relative pt-32 pb-24 md:pt-40 md:pb-32 overflow-hidden">
|
||||
{/* Decorative background */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<div className="absolute top-20 right-[-10%] w-[600px] h-[600px] rounded-full bg-[#E07A3A]/[0.04] blur-3xl" />
|
||||
<div className="absolute bottom-0 left-[-5%] w-[400px] h-[400px] rounded-full bg-[#0D7C66]/[0.03] blur-3xl" />
|
||||
<div className="absolute top-20 right-[-10%] w-[600px] h-[600px] rounded-full bg-[#6B8F71]/[0.04] blur-3xl" />
|
||||
<div className="absolute bottom-0 left-[-5%] w-[400px] h-[400px] rounded-full bg-[#C4856A]/[0.03] blur-3xl" />
|
||||
{/* Subtle grid pattern */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.03]"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(#1C1917 1px, transparent 1px), linear-gradient(90deg, #1C1917 1px, transparent 1px)",
|
||||
"linear-gradient(#2D3436 1px, transparent 1px), linear-gradient(90deg, #2D3436 1px, transparent 1px)",
|
||||
backgroundSize: "64px 64px",
|
||||
}}
|
||||
/>
|
||||
@@ -158,17 +158,17 @@ export default function HomePage() {
|
||||
<div className="max-w-7xl mx-auto px-6 relative">
|
||||
<div className="max-w-3xl">
|
||||
{/* Badge */}
|
||||
<div className="animate-fade-up stagger-1 inline-flex items-center gap-2 rounded-full border border-[#E7E5E4] bg-white px-4 py-1.5 text-sm text-[#78716C] mb-8 shadow-sm">
|
||||
<span className="inline-block size-2 rounded-full bg-[#0D7C66] animate-pulse" />
|
||||
<div className="animate-fade-up stagger-1 inline-flex items-center gap-2 rounded-full border border-[#E8E3DC] bg-white px-4 py-1.5 text-sm text-[#8A8F87] mb-8 shadow-sm">
|
||||
<span className="inline-block size-2 rounded-full bg-[#6B8F71] animate-pulse" />
|
||||
Now available for homeowners
|
||||
</div>
|
||||
|
||||
<h1 className="animate-fade-up stagger-2 font-heading text-5xl sm:text-6xl md:text-7xl font-bold tracking-tight leading-[1.08]">
|
||||
Your home,{" "}
|
||||
<span className="text-[#E07A3A]">perfectly maintained.</span>
|
||||
<span className="text-[#6B8F71]">perfectly maintained.</span>
|
||||
</h1>
|
||||
|
||||
<p className="animate-fade-up stagger-3 mt-6 text-lg md:text-xl text-[#78716C] max-w-xl leading-relaxed">
|
||||
<p className="animate-fade-up stagger-3 mt-6 text-lg md:text-xl text-[#8A8F87] max-w-xl leading-relaxed">
|
||||
Track tasks, organize contractors, and store important
|
||||
documents. Everything you need to keep your home running
|
||||
smoothly — in one place.
|
||||
@@ -177,17 +177,17 @@ export default function HomePage() {
|
||||
<div className="animate-fade-up stagger-4 mt-10 flex flex-wrap gap-4">
|
||||
<Link
|
||||
href="/register"
|
||||
className="group inline-flex items-center gap-2 rounded-full bg-[#E07A3A] px-7 py-3.5 text-base font-semibold text-white shadow-lg shadow-[#E07A3A]/20 hover:bg-[#C4632A] transition-all hover:shadow-xl hover:shadow-[#E07A3A]/25"
|
||||
className="group inline-flex items-center gap-2 rounded-full bg-[#C4856A] px-7 py-3.5 text-base font-semibold text-white shadow-lg shadow-[#C4856A]/20 hover:bg-[#A86B52] transition-all hover:shadow-xl hover:shadow-[#C4856A]/25"
|
||||
>
|
||||
Get Started — Free
|
||||
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
||||
</Link>
|
||||
<Link
|
||||
href="/demo"
|
||||
className="group inline-flex items-center gap-2 rounded-full border-2 border-[#E7E5E4] bg-white px-7 py-3.5 text-base font-semibold text-[#1C1917] hover:border-[#D6D3D1] hover:bg-[#F5F5F4] transition-all"
|
||||
className="group inline-flex items-center gap-2 rounded-full border-2 border-[#E8E3DC] bg-white px-7 py-3.5 text-base font-semibold text-[#2D3436] hover:border-[#D6D1CA] hover:bg-[#F2EFE9] transition-all"
|
||||
>
|
||||
Try the Demo
|
||||
<ChevronRight className="size-4 text-[#A8A29E] transition-transform group-hover:translate-x-0.5" />
|
||||
<ChevronRight className="size-4 text-[#8A8F87] transition-transform group-hover:translate-x-0.5" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -196,21 +196,21 @@ export default function HomePage() {
|
||||
<div className="animate-fade-up stagger-5 hidden lg:block absolute top-12 right-6 w-[420px]">
|
||||
<div className="relative">
|
||||
{/* Main card */}
|
||||
<div className="rounded-2xl bg-white border border-[#E7E5E4] shadow-xl shadow-black/[0.04] p-5">
|
||||
<div className="rounded-2xl bg-white border border-[#E8E3DC] shadow-xl shadow-[#2D3436]/[0.04] p-5">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="size-8 rounded-lg bg-[#FFF3EB] flex items-center justify-center">
|
||||
<CheckSquare className="size-4 text-[#E07A3A]" />
|
||||
<div className="size-8 rounded-lg bg-[#EDF2ED] flex items-center justify-center">
|
||||
<CheckSquare className="size-4 text-[#6B8F71]" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-semibold">Upcoming Tasks</div>
|
||||
<div className="text-xs text-[#A8A29E]">3 due this week</div>
|
||||
<div className="text-xs text-[#8A8F87]">3 due this week</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2.5">
|
||||
{[
|
||||
{ task: "Replace HVAC filter", due: "Tomorrow", status: "bg-[#FEF3C7] text-[#92400E]" },
|
||||
{ task: "Schedule gutter cleaning", due: "Wed", status: "bg-[#ECFDF5] text-[#0D7C66]" },
|
||||
{ task: "Check smoke detectors", due: "Fri", status: "bg-[#FFF3EB] text-[#E07A3A]" },
|
||||
{ task: "Schedule gutter cleaning", due: "Wed", status: "bg-[#EDF2ED] text-[#6B8F71]" },
|
||||
{ task: "Check smoke detectors", due: "Fri", status: "bg-[#FDF3EE] text-[#C4856A]" },
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.task}
|
||||
@@ -229,13 +229,13 @@ export default function HomePage() {
|
||||
|
||||
{/* Floating stat card */}
|
||||
<div
|
||||
className="absolute -bottom-8 -left-8 rounded-xl bg-white border border-[#E7E5E4] shadow-lg shadow-black/[0.04] p-4 w-48"
|
||||
className="absolute -bottom-8 -left-8 rounded-xl bg-white border border-[#E8E3DC] shadow-lg shadow-[#2D3436]/[0.04] p-4 w-48"
|
||||
style={{ animation: "float 6s ease-in-out infinite" }}
|
||||
>
|
||||
<div className="text-xs text-[#A8A29E] mb-1">This Month</div>
|
||||
<div className="text-2xl font-bold font-heading text-[#0D7C66]">12 Done</div>
|
||||
<div className="mt-2 h-1.5 rounded-full bg-[#F7F7F7] overflow-hidden">
|
||||
<div className="h-full w-3/4 rounded-full bg-[#0D7C66]" />
|
||||
<div className="text-xs text-[#8A8F87] mb-1">This Month</div>
|
||||
<div className="text-2xl font-bold font-heading text-[#6B8F71]">12 Done</div>
|
||||
<div className="mt-2 h-1.5 rounded-full bg-[#F2EFE9] overflow-hidden">
|
||||
<div className="h-full w-3/4 rounded-full bg-[#6B8F71]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -244,7 +244,7 @@ export default function HomePage() {
|
||||
</section>
|
||||
|
||||
{/* ─── Social proof strip ─── */}
|
||||
<section className="border-y border-[#E7E5E4] bg-white/50">
|
||||
<section className="border-y border-[#E8E3DC] bg-white/50">
|
||||
<div className="max-w-7xl mx-auto px-6 py-8 flex flex-wrap items-center justify-center gap-x-12 gap-y-4 text-center">
|
||||
{[
|
||||
{ value: "Free", label: "to get started" },
|
||||
@@ -252,10 +252,10 @@ export default function HomePage() {
|
||||
{ value: "All-in-one", label: "home management" },
|
||||
].map((stat) => (
|
||||
<div key={stat.label} className="flex items-baseline gap-2">
|
||||
<span className="text-lg font-bold font-heading text-[#1C1917]">
|
||||
<span className="text-lg font-bold font-heading text-[#2D3436]">
|
||||
{stat.value}
|
||||
</span>
|
||||
<span className="text-sm text-[#A8A29E]">{stat.label}</span>
|
||||
<span className="text-sm text-[#8A8F87]">{stat.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -265,13 +265,13 @@ export default function HomePage() {
|
||||
<section id="features" className="py-24 md:py-32">
|
||||
<div className="max-w-7xl mx-auto px-6">
|
||||
<div className="max-w-2xl mb-16">
|
||||
<p className="text-sm font-semibold text-[#E07A3A] uppercase tracking-wider mb-3">
|
||||
<p className="text-sm font-semibold text-[#6B8F71] uppercase tracking-wider mb-3">
|
||||
Features
|
||||
</p>
|
||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
||||
Everything your home needs, nothing it doesn't.
|
||||
</h2>
|
||||
<p className="mt-4 text-lg text-[#78716C] leading-relaxed">
|
||||
<p className="mt-4 text-lg text-[#8A8F87] leading-relaxed">
|
||||
Casera brings all your home maintenance into one clear,
|
||||
organized space. No bloat, no learning curve.
|
||||
</p>
|
||||
@@ -281,7 +281,7 @@ export default function HomePage() {
|
||||
{features.map((feature, i) => (
|
||||
<div
|
||||
key={feature.title}
|
||||
className={`group relative rounded-2xl border border-[#E7E5E4] bg-white p-8 transition-all hover:shadow-lg hover:shadow-black/[0.04] hover:-translate-y-0.5 stagger-${i + 1}`}
|
||||
className={`group relative rounded-2xl border border-[#E8E3DC] bg-white p-8 transition-all hover:shadow-lg hover:shadow-[#2D3436]/[0.04] hover:-translate-y-0.5 stagger-${i + 1}`}
|
||||
>
|
||||
<div
|
||||
className={`inline-flex items-center justify-center size-12 rounded-xl ${feature.color} mb-5`}
|
||||
@@ -291,7 +291,7 @@ export default function HomePage() {
|
||||
<h3 className="font-heading text-xl font-bold mb-2">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-[#78716C] leading-relaxed">
|
||||
<p className="text-[#8A8F87] leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -303,11 +303,11 @@ export default function HomePage() {
|
||||
{/* ─── How It Works ─── */}
|
||||
<section
|
||||
id="how-it-works"
|
||||
className="py-24 md:py-32 bg-[#F7F7F7] relative noise-overlay"
|
||||
className="py-24 md:py-32 bg-[#F2EFE9] relative noise-overlay"
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-6 relative">
|
||||
<div className="text-center max-w-2xl mx-auto mb-16">
|
||||
<p className="text-sm font-semibold text-[#0D7C66] uppercase tracking-wider mb-3">
|
||||
<p className="text-sm font-semibold text-[#6B8F71] uppercase tracking-wider mb-3">
|
||||
How It Works
|
||||
</p>
|
||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
||||
@@ -318,13 +318,13 @@ export default function HomePage() {
|
||||
<div className="grid md:grid-cols-3 gap-8 md:gap-12">
|
||||
{steps.map((step) => (
|
||||
<div key={step.number} className="text-center md:text-left">
|
||||
<div className="inline-flex items-center justify-center size-14 rounded-2xl bg-[#1C1917] text-white font-heading font-bold text-lg mb-5">
|
||||
<div className="inline-flex items-center justify-center size-14 rounded-2xl bg-[#2D3436] text-white font-heading font-bold text-lg mb-5">
|
||||
{step.number}
|
||||
</div>
|
||||
<h3 className="font-heading text-xl font-bold mb-2">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-[#78716C] leading-relaxed">
|
||||
<p className="text-[#8A8F87] leading-relaxed">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -340,7 +340,7 @@ export default function HomePage() {
|
||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
||||
Built for real homeowners
|
||||
</h2>
|
||||
<p className="mt-4 text-lg text-[#78716C]">
|
||||
<p className="mt-4 text-lg text-[#8A8F87]">
|
||||
Thoughtful details that make home maintenance feel manageable.
|
||||
</p>
|
||||
</div>
|
||||
@@ -349,13 +349,13 @@ export default function HomePage() {
|
||||
{highlights.map((item) => (
|
||||
<div
|
||||
key={item.title}
|
||||
className="rounded-2xl border border-[#E7E5E4] bg-white p-6 hover:shadow-md hover:shadow-black/[0.03] transition-all"
|
||||
className="rounded-2xl border border-[#E8E3DC] bg-white p-6 hover:shadow-md hover:shadow-[#2D3436]/[0.03] transition-all"
|
||||
>
|
||||
<item.icon className="size-6 text-[#E07A3A] mb-4" />
|
||||
<item.icon className="size-6 text-[#6B8F71] mb-4" />
|
||||
<h3 className="font-heading font-bold text-base mb-1.5">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-sm text-[#78716C] leading-relaxed">
|
||||
<p className="text-sm text-[#8A8F87] leading-relaxed">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -366,23 +366,23 @@ export default function HomePage() {
|
||||
|
||||
{/* ─── CTA Section ─── */}
|
||||
<section className="py-24 md:py-32 relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[#1C1917]" />
|
||||
{/* Orange glow */}
|
||||
<div className="absolute top-0 right-0 w-[500px] h-[500px] rounded-full bg-[#E07A3A]/10 blur-[120px] pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-0 w-[400px] h-[400px] rounded-full bg-[#0D7C66]/10 blur-[100px] pointer-events-none" />
|
||||
<div className="absolute inset-0 bg-[#2D3436]" />
|
||||
{/* Sage glow */}
|
||||
<div className="absolute top-0 right-0 w-[500px] h-[500px] rounded-full bg-[#6B8F71]/10 blur-[120px] pointer-events-none" />
|
||||
<div className="absolute bottom-0 left-0 w-[400px] h-[400px] rounded-full bg-[#C4856A]/10 blur-[100px] pointer-events-none" />
|
||||
|
||||
<div className="max-w-3xl mx-auto px-6 text-center relative">
|
||||
<h2 className="font-heading text-3xl md:text-5xl font-bold tracking-tight text-white">
|
||||
Ready to take control of your home?
|
||||
</h2>
|
||||
<p className="mt-5 text-lg text-[#A8A29E] max-w-xl mx-auto leading-relaxed">
|
||||
<p className="mt-5 text-lg text-[#9A9E97] max-w-xl mx-auto leading-relaxed">
|
||||
Join homeowners who've simplified their maintenance routine.
|
||||
Free to start, no credit card required.
|
||||
</p>
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-4">
|
||||
<Link
|
||||
href="/register"
|
||||
className="group inline-flex items-center gap-2 rounded-full bg-[#E07A3A] px-8 py-4 text-base font-semibold text-white shadow-lg shadow-[#E07A3A]/20 hover:bg-[#C4632A] transition-all"
|
||||
className="group inline-flex items-center gap-2 rounded-full bg-[#C4856A] px-8 py-4 text-base font-semibold text-white shadow-lg shadow-[#C4856A]/20 hover:bg-[#A86B52] transition-all"
|
||||
>
|
||||
Get Started — Free
|
||||
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
||||
@@ -398,7 +398,7 @@ export default function HomePage() {
|
||||
</section>
|
||||
|
||||
{/* ─── Footer ─── */}
|
||||
<footer className="bg-[#1C1917] border-t border-white/5 text-[#A8A29E]">
|
||||
<footer className="bg-[#2D3436] border-t border-white/5 text-[#9A9E97]">
|
||||
<div className="max-w-7xl mx-auto px-6 py-16">
|
||||
<div className="grid md:grid-cols-4 gap-10">
|
||||
{/* Brand */}
|
||||
|
||||
@@ -39,8 +39,8 @@ export function RecentActivity() {
|
||||
</div>
|
||||
) : notifications.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center py-10 text-center">
|
||||
<div className="size-11 rounded-xl bg-[#FFF3EB] flex items-center justify-center mb-3">
|
||||
<Coffee className="size-5 text-[#E07A3A]" />
|
||||
<div className="size-11 rounded-xl bg-primary/10 flex items-center justify-center mb-3">
|
||||
<Coffee className="size-5 text-primary" />
|
||||
</div>
|
||||
<p className="text-sm font-medium text-foreground">Nothing yet — all quiet!</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
|
||||
@@ -32,16 +32,16 @@ const stats = [
|
||||
key: "active",
|
||||
label: "Active",
|
||||
icon: ClipboardList,
|
||||
iconColor: "text-[#0D7C66]",
|
||||
bgColor: "bg-emerald-50 dark:bg-emerald-500/10",
|
||||
iconColor: "text-primary",
|
||||
bgColor: "bg-primary/10",
|
||||
prop: "active" as const,
|
||||
},
|
||||
{
|
||||
key: "completed",
|
||||
label: "Completed",
|
||||
icon: CheckCircle2,
|
||||
iconColor: "text-[#E07A3A]",
|
||||
bgColor: "bg-orange-50 dark:bg-orange-500/10",
|
||||
iconColor: "text-brand-clay",
|
||||
bgColor: "bg-brand-clay/10",
|
||||
prop: "completed" as const,
|
||||
},
|
||||
] as const;
|
||||
@@ -54,7 +54,7 @@ export function StatsCards({ overdue, dueSoon, active, completed }: StatsCardsPr
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{stats.map((stat) => (
|
||||
<Link key={stat.key} href={`${basePath}/tasks`}>
|
||||
<div className="group rounded-2xl border border-border bg-card p-5 hover:shadow-md hover:shadow-black/[0.03] transition-all hover:-translate-y-0.5 cursor-pointer">
|
||||
<div className="group rounded-2xl border border-border bg-card p-5 hover:shadow-[var(--shadow-warm-md)] transition-all hover:-translate-y-0.5 cursor-pointer">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className={`inline-flex items-center justify-center size-9 rounded-xl ${stat.bgColor}`}>
|
||||
<stat.icon className={`size-4 ${stat.iconColor}`} />
|
||||
|
||||
@@ -43,8 +43,8 @@ export function TaskCompletionChart({ data }: TaskCompletionChartProps) {
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="count"
|
||||
stroke="#E07A3A"
|
||||
fill="#E07A3A"
|
||||
stroke="#6B8F71"
|
||||
fill="#6B8F71"
|
||||
fillOpacity={0.1}
|
||||
strokeWidth={2}
|
||||
/>
|
||||
@@ -52,8 +52,8 @@ export function TaskCompletionChart({ data }: TaskCompletionChartProps) {
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center h-[300px] text-center">
|
||||
<div className="size-12 rounded-xl bg-[#ECFDF5] flex items-center justify-center mb-3">
|
||||
<TrendingUp className="size-5 text-[#0D7C66]" />
|
||||
<div className="size-12 rounded-xl bg-primary/10 flex items-center justify-center mb-3">
|
||||
<TrendingUp className="size-5 text-primary" />
|
||||
</div>
|
||||
<p className="text-sm font-medium text-foreground">Your progress chart lives here</p>
|
||||
<p className="text-xs text-muted-foreground mt-1 max-w-[260px] leading-relaxed">
|
||||
|
||||
@@ -11,7 +11,7 @@ export function DemoBanner() {
|
||||
if (dismissed) return null;
|
||||
|
||||
return (
|
||||
<div className="sticky top-0 z-50 flex items-center justify-center gap-3 border-b border-[#E07A3A]/20 bg-[#FFF3EB]/80 px-4 py-2.5 text-sm text-[#92400E] backdrop-blur-xl">
|
||||
<div className="sticky top-0 z-50 flex items-center justify-center gap-3 border-b border-brand-clay/20 bg-brand-clay-light/80 px-4 py-2.5 text-sm text-[#92400E] backdrop-blur-xl">
|
||||
<p className="font-medium">
|
||||
You're exploring Casera in demo mode. Changes aren't saved.
|
||||
</p>
|
||||
@@ -21,7 +21,7 @@ export function DemoBanner() {
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="absolute right-2 text-[#92400E] hover:bg-[#E07A3A]/10"
|
||||
className="absolute right-2 text-[#92400E] hover:bg-brand-clay/10"
|
||||
onClick={() => setDismissed(true)}
|
||||
aria-label="Dismiss banner"
|
||||
>
|
||||
|
||||
@@ -28,7 +28,7 @@ export function AuthFormWrapper({
|
||||
height={32}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span className="font-heading text-xl font-bold text-[#1C1917]">
|
||||
<span className="font-heading text-xl font-bold text-foreground">
|
||||
Casera
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
@@ -4,8 +4,6 @@ import { Monitor, Moon, Sun } from "lucide-react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { themes } from "@/lib/themes/theme-config";
|
||||
import { useThemeStore, type ColorMode } from "@/stores/theme";
|
||||
|
||||
const modeOptions: { value: ColorMode; label: string; icon: React.ElementType }[] = [
|
||||
@@ -15,48 +13,15 @@ const modeOptions: { value: ColorMode; label: string; icon: React.ElementType }[
|
||||
];
|
||||
|
||||
export function ThemePicker() {
|
||||
const { themeId, mode, setTheme, setMode } = useThemeStore();
|
||||
const { mode, setMode } = useThemeStore();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Appearance</CardTitle>
|
||||
<CardDescription>Choose a theme and color mode for the app.</CardDescription>
|
||||
<CardDescription>Choose a color mode for the app.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
{/* Theme swatches */}
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-3">Theme</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{themes.map((theme) => (
|
||||
<button
|
||||
key={theme.id}
|
||||
type="button"
|
||||
onClick={() => setTheme(theme.id)}
|
||||
className={cn(
|
||||
"group relative flex flex-col items-center gap-1.5 rounded-lg p-2 transition-colors hover:bg-accent",
|
||||
themeId === theme.id && "bg-accent"
|
||||
)}
|
||||
title={theme.name}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"size-8 rounded-full border-2 transition-all",
|
||||
themeId === theme.id
|
||||
? "border-foreground ring-2 ring-foreground ring-offset-2 ring-offset-background"
|
||||
: "border-transparent"
|
||||
)}
|
||||
style={{ backgroundColor: theme.light.primary }}
|
||||
/>
|
||||
<span className="text-xs text-muted-foreground group-hover:text-foreground">
|
||||
{theme.name}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mode toggle */}
|
||||
<CardContent>
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-3">Mode</p>
|
||||
<div className="inline-flex items-center rounded-lg border bg-muted p-1 gap-1">
|
||||
|
||||
@@ -10,8 +10,8 @@ import type { KanbanColumn as KanbanColumnType } from "@/lib/api/tasks";
|
||||
const COLUMN_COLORS: Record<string, string> = {
|
||||
overdue_tasks: "border-red-200 bg-red-50/40 dark:border-red-500/20 dark:bg-red-950/20",
|
||||
due_soon_tasks: "border-amber-200 bg-amber-50/40 dark:border-amber-500/20 dark:bg-amber-950/20",
|
||||
upcoming_tasks: "border-blue-200 bg-blue-50/40 dark:border-blue-500/20 dark:bg-blue-950/20",
|
||||
in_progress_tasks: "border-emerald-200 bg-emerald-50/40 dark:border-emerald-500/20 dark:bg-emerald-950/20",
|
||||
upcoming_tasks: "border-[#6B8F71]/20 bg-[#EDF2ED]/50 dark:border-[#8FB896]/20 dark:bg-[#8FB896]/5",
|
||||
in_progress_tasks: "border-[#C4856A]/20 bg-[#FDF3EE]/50 dark:border-[#D4A08A]/20 dark:bg-[#D4A08A]/5",
|
||||
completed_tasks: "border-stone-200 bg-stone-50/40 dark:border-stone-500/20 dark:bg-stone-950/20",
|
||||
cancelled_tasks: "border-slate-200 bg-slate-50/40 dark:border-slate-500/20 dark:bg-slate-950/20",
|
||||
};
|
||||
@@ -19,8 +19,8 @@ const COLUMN_COLORS: Record<string, string> = {
|
||||
const COLUMN_HEADER_COLORS: Record<string, string> = {
|
||||
overdue_tasks: "text-red-700 dark:text-red-400",
|
||||
due_soon_tasks: "text-amber-700 dark:text-amber-400",
|
||||
upcoming_tasks: "text-blue-700 dark:text-blue-400",
|
||||
in_progress_tasks: "text-emerald-700 dark:text-emerald-400",
|
||||
upcoming_tasks: "text-[#6B8F71] dark:text-[#8FB896]",
|
||||
in_progress_tasks: "text-[#C4856A] dark:text-[#D4A08A]",
|
||||
completed_tasks: "text-stone-600 dark:text-stone-400",
|
||||
cancelled_tasks: "text-slate-600 dark:text-slate-400",
|
||||
};
|
||||
@@ -28,8 +28,8 @@ const COLUMN_HEADER_COLORS: Record<string, string> = {
|
||||
const COUNT_BADGE_COLORS: Record<string, string> = {
|
||||
overdue_tasks: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300",
|
||||
due_soon_tasks: "bg-amber-100 text-amber-700 dark:bg-amber-900/50 dark:text-amber-300",
|
||||
upcoming_tasks: "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300",
|
||||
in_progress_tasks: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300",
|
||||
upcoming_tasks: "bg-[#6B8F71]/15 text-[#6B8F71] dark:bg-[#8FB896]/20 dark:text-[#8FB896]",
|
||||
in_progress_tasks: "bg-[#C4856A]/15 text-[#C4856A] dark:bg-[#D4A08A]/20 dark:text-[#D4A08A]",
|
||||
completed_tasks: "bg-stone-100 text-stone-700 dark:bg-stone-900/50 dark:text-stone-300",
|
||||
cancelled_tasks: "bg-slate-100 text-slate-700 dark:bg-slate-900/50 dark:text-slate-300",
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Sun, Moon, Monitor, Check } from "lucide-react";
|
||||
import { Sun, Moon, Monitor } from "lucide-react";
|
||||
import { useTheme, type ColorMode } from "@/lib/themes/use-theme";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -13,11 +13,10 @@ const modeOptions: { value: ColorMode; label: string; icon: React.ElementType }[
|
||||
/**
|
||||
* Theme switcher component.
|
||||
*
|
||||
* Shows a grid of 11 color swatches (one per theme) and a
|
||||
* light/dark/system segmented toggle.
|
||||
* Light/dark/system segmented toggle.
|
||||
*/
|
||||
export function ThemeSwitcher({ className }: { className?: string }) {
|
||||
const { themeId, mode, effectiveMode, themes, setTheme, setMode } = useTheme();
|
||||
const { mode, setMode } = useTheme();
|
||||
|
||||
return (
|
||||
<div className={cn("flex flex-col gap-4", className)}>
|
||||
@@ -40,42 +39,6 @@ export function ThemeSwitcher({ className }: { className?: string }) {
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Theme swatches */}
|
||||
<div className="grid grid-cols-6 gap-2 sm:grid-cols-11">
|
||||
{themes.map((theme) => {
|
||||
const isActive = theme.id === themeId;
|
||||
// Show the primary color for the effective mode so the swatch
|
||||
// preview matches what the user actually sees.
|
||||
const previewColor =
|
||||
effectiveMode === "dark"
|
||||
? theme.dark.primary
|
||||
: theme.light.primary;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={theme.id}
|
||||
type="button"
|
||||
title={theme.name}
|
||||
onClick={() => setTheme(theme.id)}
|
||||
className={cn(
|
||||
"relative flex h-8 w-8 items-center justify-center rounded-full border-2 transition-all",
|
||||
isActive
|
||||
? "border-foreground scale-110"
|
||||
: "border-transparent hover:scale-105 hover:border-muted-foreground/40"
|
||||
)}
|
||||
style={{ backgroundColor: previewColor }}
|
||||
>
|
||||
{isActive && (
|
||||
<Check
|
||||
className="h-4 w-4"
|
||||
style={{ color: theme[effectiveMode].textOnPrimary }}
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+20
-291
@@ -19,305 +19,34 @@ export interface ThemeDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* All 11 themes matching the KMM/iOS theme system.
|
||||
* Hex values are taken directly from ThemeColors.kt.
|
||||
* Single "Warm Sage" theme — the Casera brand palette.
|
||||
*/
|
||||
export const themes: ThemeDefinition[] = [
|
||||
{
|
||||
id: "default",
|
||||
name: "Default",
|
||||
description: "Warm orange with teal accents",
|
||||
name: "Warm Sage",
|
||||
description: "Calming sage with warm clay accents",
|
||||
light: {
|
||||
primary: "#E07A3A",
|
||||
secondary: "#0D7C66",
|
||||
accent: "#D4A574",
|
||||
error: "#DC2626",
|
||||
bgPrimary: "#FFFFFF",
|
||||
bgSecondary: "#F7F7F7",
|
||||
textPrimary: "#1C1917",
|
||||
textSecondary: "#78716C",
|
||||
primary: "#6B8F71",
|
||||
secondary: "#C4856A",
|
||||
accent: "#C4856A",
|
||||
error: "#C75B4A",
|
||||
bgPrimary: "#FAFAF7",
|
||||
bgSecondary: "#F2EFE9",
|
||||
textPrimary: "#2D3436",
|
||||
textSecondary: "#8A8F87",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#F0A070",
|
||||
secondary: "#4FC9AF",
|
||||
accent: "#DDB892",
|
||||
error: "#EF4444",
|
||||
bgPrimary: "#0A0A0A",
|
||||
bgSecondary: "#161616",
|
||||
textPrimary: "#FAFAFA",
|
||||
textSecondary: "#A1A1A1",
|
||||
textOnPrimary: "#0A0A0A",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "teal",
|
||||
name: "Teal",
|
||||
description: "Blue-green with warm accents",
|
||||
light: {
|
||||
primary: "#069FC3",
|
||||
secondary: "#0054A4",
|
||||
accent: "#EFC707",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#FFF0D0",
|
||||
bgSecondary: "#FFFFFF",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#60CCE2",
|
||||
secondary: "#60A5D8",
|
||||
accent: "#EFC707",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#091829",
|
||||
bgSecondary: "#1A2E3E",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "ocean",
|
||||
name: "Ocean",
|
||||
description: "Deep blues and coral tones",
|
||||
light: {
|
||||
primary: "#006B8F",
|
||||
secondary: "#008A8A",
|
||||
accent: "#FF7E50",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#E4EBF1",
|
||||
bgSecondary: "#BCCAD5",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#49B5D1",
|
||||
secondary: "#60D1C6",
|
||||
accent: "#FF7E50",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#161B22",
|
||||
bgSecondary: "#313A4B",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "forest",
|
||||
name: "Forest",
|
||||
description: "Earth greens and golden hues",
|
||||
light: {
|
||||
primary: "#2C5015",
|
||||
secondary: "#6B8E22",
|
||||
accent: "#FFD600",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#EBEEE2",
|
||||
bgSecondary: "#C1C8AD",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#93C66B",
|
||||
secondary: "#AFD182",
|
||||
accent: "#FFD600",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#181E17",
|
||||
bgSecondary: "#384436",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "sunset",
|
||||
name: "Sunset",
|
||||
description: "Warm oranges and reds",
|
||||
light: {
|
||||
primary: "#FF4500",
|
||||
secondary: "#FF6246",
|
||||
accent: "#FFD600",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#F7F0E8",
|
||||
bgSecondary: "#DCD0BA",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#FF9E60",
|
||||
secondary: "#FFAD7C",
|
||||
accent: "#FFD600",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#201813",
|
||||
bgSecondary: "#433329",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "monochrome",
|
||||
name: "Monochrome",
|
||||
description: "Elegant grayscale",
|
||||
light: {
|
||||
primary: "#333333",
|
||||
secondary: "#666666",
|
||||
accent: "#999999",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#F0F0F0",
|
||||
bgSecondary: "#D4D4D4",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#E5E5E5",
|
||||
secondary: "#BFBFBF",
|
||||
accent: "#D1D1D1",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#161616",
|
||||
bgSecondary: "#3B3B3B",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "lavender",
|
||||
name: "Lavender",
|
||||
description: "Soft purple with pink accents",
|
||||
light: {
|
||||
primary: "#6B418A",
|
||||
secondary: "#8A60AF",
|
||||
accent: "#E24982",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#F1EFF5",
|
||||
bgSecondary: "#D9D1DF",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#D1AFE2",
|
||||
secondary: "#DDBFEA",
|
||||
accent: "#FF9EC6",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#17131E",
|
||||
bgSecondary: "#393042",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "crimson",
|
||||
name: "Crimson",
|
||||
description: "Bold red with warm highlights",
|
||||
light: {
|
||||
primary: "#B51E28",
|
||||
secondary: "#992D38",
|
||||
accent: "#E26000",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#F6EDEB",
|
||||
bgSecondary: "#DECFCC",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#FF827C",
|
||||
secondary: "#F99993",
|
||||
accent: "#FFB56B",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#1B1215",
|
||||
bgSecondary: "#412E39",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "midnight",
|
||||
name: "Midnight",
|
||||
description: "Deep navy with sky blue",
|
||||
light: {
|
||||
primary: "#1E4993",
|
||||
secondary: "#2D60AF",
|
||||
accent: "#4993E2",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#EDF0F7",
|
||||
bgSecondary: "#CCD5E2",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#82B5EA",
|
||||
secondary: "#93C6F2",
|
||||
accent: "#9ED8FF",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#12161F",
|
||||
bgSecondary: "#2F3848",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "desert",
|
||||
name: "Desert",
|
||||
description: "Warm terracotta and sand tones",
|
||||
light: {
|
||||
primary: "#AF6049",
|
||||
secondary: "#9E7C60",
|
||||
accent: "#D1932D",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#F6F0EA",
|
||||
bgSecondary: "#E5D8C6",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#F2B593",
|
||||
secondary: "#EAD1AF",
|
||||
accent: "#FFD86B",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#1F1C16",
|
||||
bgSecondary: "#494138",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "mint",
|
||||
name: "Mint",
|
||||
description: "Fresh green with turquoise",
|
||||
light: {
|
||||
primary: "#38AF93",
|
||||
secondary: "#60C6AF",
|
||||
accent: "#2D9EAF",
|
||||
error: "#DD1C1A",
|
||||
bgPrimary: "#EDF6F0",
|
||||
bgSecondary: "#D1E2D8",
|
||||
textPrimary: "#111111",
|
||||
textSecondary: "#444444",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
},
|
||||
dark: {
|
||||
primary: "#93F2D8",
|
||||
secondary: "#BFF9EA",
|
||||
accent: "#6BEAF2",
|
||||
error: "#FF5244",
|
||||
bgPrimary: "#161F1F",
|
||||
bgSecondary: "#384949",
|
||||
textPrimary: "#F5F5F5",
|
||||
textSecondary: "#C6C6C6",
|
||||
textOnPrimary: "#FFFFFF",
|
||||
primary: "#8FB896",
|
||||
secondary: "#D4A08A",
|
||||
accent: "#D4A08A",
|
||||
error: "#E07A6B",
|
||||
bgPrimary: "#1A1D1A",
|
||||
bgSecondary: "#2A2E2A",
|
||||
textPrimary: "#E8E5DF",
|
||||
textSecondary: "#9A9E97",
|
||||
textOnPrimary: "#1A1D1A",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4,14 +4,8 @@ import { useEffect } from "react";
|
||||
import { useThemeStore } from "@/stores/theme";
|
||||
|
||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||
const themeId = useThemeStore((s) => s.themeId);
|
||||
const mode = useThemeStore((s) => s.mode);
|
||||
|
||||
// Sync data-theme attribute
|
||||
useEffect(() => {
|
||||
document.documentElement.setAttribute("data-theme", themeId);
|
||||
}, [themeId]);
|
||||
|
||||
// Sync dark class based on mode + system preference
|
||||
useEffect(() => {
|
||||
const applyDarkClass = (isDark: boolean) => {
|
||||
@@ -41,22 +35,5 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||
return () => mql.removeEventListener("change", handler);
|
||||
}, [mode]);
|
||||
|
||||
// On mount, migrate any stale persisted state to light mode
|
||||
useEffect(() => {
|
||||
const stored = localStorage.getItem("casera-theme");
|
||||
if (stored) {
|
||||
try {
|
||||
const parsed = JSON.parse(stored);
|
||||
if (parsed?.state?.mode === "system") {
|
||||
parsed.state.mode = "light";
|
||||
localStorage.setItem("casera-theme", JSON.stringify(parsed));
|
||||
useThemeStore.getState().setMode("light");
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { themes, getThemeById, type ThemeDefinition } from "./theme-config";
|
||||
* (accounting for system preference), and setters.
|
||||
*/
|
||||
export function useTheme() {
|
||||
const { themeId, mode, setTheme, setMode } = useThemeStore();
|
||||
const { mode, setMode } = useThemeStore();
|
||||
|
||||
const [effectiveMode, setEffectiveMode] = useState<"light" | "dark">("light");
|
||||
|
||||
@@ -28,11 +28,9 @@ export function useTheme() {
|
||||
return () => mql.removeEventListener("change", handler);
|
||||
}, [mode]);
|
||||
|
||||
const currentTheme: ThemeDefinition = getThemeById(themeId);
|
||||
const currentTheme: ThemeDefinition = getThemeById("default");
|
||||
|
||||
return {
|
||||
/** Current theme ID string */
|
||||
themeId,
|
||||
/** Current mode setting (light | dark | system) */
|
||||
mode,
|
||||
/** Resolved mode after considering system preference */
|
||||
@@ -41,8 +39,6 @@ export function useTheme() {
|
||||
currentTheme,
|
||||
/** All available theme definitions */
|
||||
themes,
|
||||
/** Set the active theme by ID */
|
||||
setTheme,
|
||||
/** Set the color mode */
|
||||
setMode,
|
||||
};
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { DEFAULT_THEME_ID } from "@/lib/themes/theme-config";
|
||||
|
||||
export type ColorMode = "light" | "dark" | "system";
|
||||
|
||||
interface ThemeState {
|
||||
themeId: string;
|
||||
mode: ColorMode;
|
||||
setTheme: (themeId: string) => void;
|
||||
setMode: (mode: ColorMode) => void;
|
||||
}
|
||||
|
||||
export const useThemeStore = create<ThemeState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
themeId: DEFAULT_THEME_ID,
|
||||
mode: "light",
|
||||
setTheme: (themeId: string) => set({ themeId }),
|
||||
setMode: (mode: ColorMode) => set({ mode }),
|
||||
}),
|
||||
{
|
||||
|
||||
+44
-878
@@ -1,9 +1,7 @@
|
||||
/*
|
||||
* Casera multi-theme design system
|
||||
* 11 themes x 2 modes (light/dark) = 22 palettes
|
||||
* Casera "Warm Sage" design system
|
||||
* Single brand palette — light + dark mode
|
||||
* Maps to shadcn/ui CSS variables and custom app variables
|
||||
*
|
||||
* Spacing and radius tokens are theme-independent.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -24,27 +22,19 @@
|
||||
--radius-xxl: 24px;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Helper: map app vars to shadcn vars */
|
||||
/* Each theme block sets --color-* vars, then this maps them. */
|
||||
/* We inline shadcn mapping directly in each theme block for */
|
||||
/* specificity, so this section documents the pattern. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Default — Warm orange brand with teal accents */
|
||||
/* Light mode (default) */
|
||||
/* ================================================================== */
|
||||
[data-theme="default"],
|
||||
:root {
|
||||
/* App color tokens – light */
|
||||
--color-primary: #E07A3A;
|
||||
--color-secondary: #0D7C66;
|
||||
--color-accent: #D4A574;
|
||||
--color-error: #DC2626;
|
||||
--color-bg-primary: #FFFFFF;
|
||||
--color-bg-secondary: #F7F7F7;
|
||||
--color-text-primary: #1C1917;
|
||||
--color-text-secondary: #78716C;
|
||||
--color-primary: #6B8F71;
|
||||
--color-secondary: #C4856A;
|
||||
--color-accent: #C4856A;
|
||||
--color-error: #C75B4A;
|
||||
--color-bg-primary: #FAFAF7;
|
||||
--color-bg-secondary: #F2EFE9;
|
||||
--color-text-primary: #2D3436;
|
||||
--color-text-secondary: #8A8F87;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
/* shadcn overrides */
|
||||
@@ -63,8 +53,8 @@
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: #E8E8E8;
|
||||
--input: #E8E8E8;
|
||||
--border: #E8E3DC;
|
||||
--input: #E8E3DC;
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: #FFFFFF;
|
||||
@@ -73,21 +63,30 @@
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-secondary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: #E7E5E4;
|
||||
--sidebar-border: #E8E3DC;
|
||||
--sidebar-ring: var(--color-primary);
|
||||
|
||||
/* Chart palette */
|
||||
--chart-1: #6B8F71;
|
||||
--chart-2: #C4856A;
|
||||
--chart-3: #8FB896;
|
||||
--chart-4: #D4A08A;
|
||||
--chart-5: #A3C4A8;
|
||||
}
|
||||
|
||||
[data-theme="default"].dark,
|
||||
.dark[data-theme="default"] {
|
||||
--color-primary: #F0A070;
|
||||
--color-secondary: #4FC9AF;
|
||||
--color-accent: #DDB892;
|
||||
--color-error: #EF4444;
|
||||
--color-bg-primary: #0A0A0A;
|
||||
--color-bg-secondary: #161616;
|
||||
--color-text-primary: #FAFAFA;
|
||||
--color-text-secondary: #A1A1A1;
|
||||
--color-text-on-primary: #0A0A0A;
|
||||
/* ================================================================== */
|
||||
/* Dark mode */
|
||||
/* ================================================================== */
|
||||
.dark {
|
||||
--color-primary: #8FB896;
|
||||
--color-secondary: #D4A08A;
|
||||
--color-accent: #D4A08A;
|
||||
--color-error: #E07A6B;
|
||||
--color-bg-primary: #1A1D1A;
|
||||
--color-bg-secondary: #2A2E2A;
|
||||
--color-text-primary: #E8E5DF;
|
||||
--color-text-secondary: #9A9E97;
|
||||
--color-text-on-primary: #1A1D1A;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
@@ -97,9 +96,9 @@
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: #141414;
|
||||
--card: #232823;
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: #141414;
|
||||
--popover: #232823;
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
@@ -108,7 +107,7 @@
|
||||
--input: rgba(255, 255, 255, 0.12);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: #141414;
|
||||
--sidebar: #232823;
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
@@ -116,844 +115,11 @@
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: rgba(255, 255, 255, 0.1);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Teal — Blue-green with warm accents */
|
||||
/* ================================================================== */
|
||||
[data-theme="teal"] {
|
||||
--color-primary: #069FC3;
|
||||
--color-secondary: #0054A4;
|
||||
--color-accent: #EFC707;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #FFF0D0;
|
||||
--color-bg-secondary: #FFFFFF;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="teal"].dark,
|
||||
.dark[data-theme="teal"] {
|
||||
--color-primary: #60CCE2;
|
||||
--color-secondary: #60A5D8;
|
||||
--color-accent: #EFC707;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #091829;
|
||||
--color-bg-secondary: #1A2E3E;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Ocean — Deep blues and coral tones */
|
||||
/* ================================================================== */
|
||||
[data-theme="ocean"] {
|
||||
--color-primary: #006B8F;
|
||||
--color-secondary: #008A8A;
|
||||
--color-accent: #FF7E50;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #E4EBF1;
|
||||
--color-bg-secondary: #BCCAD5;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="ocean"].dark,
|
||||
.dark[data-theme="ocean"] {
|
||||
--color-primary: #49B5D1;
|
||||
--color-secondary: #60D1C6;
|
||||
--color-accent: #FF7E50;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #161B22;
|
||||
--color-bg-secondary: #313A4B;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Forest — Earth greens and golden hues */
|
||||
/* ================================================================== */
|
||||
[data-theme="forest"] {
|
||||
--color-primary: #2C5015;
|
||||
--color-secondary: #6B8E22;
|
||||
--color-accent: #FFD600;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #EBEEE2;
|
||||
--color-bg-secondary: #C1C8AD;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="forest"].dark,
|
||||
.dark[data-theme="forest"] {
|
||||
--color-primary: #93C66B;
|
||||
--color-secondary: #AFD182;
|
||||
--color-accent: #FFD600;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #181E17;
|
||||
--color-bg-secondary: #384436;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Sunset — Warm oranges and reds */
|
||||
/* ================================================================== */
|
||||
[data-theme="sunset"] {
|
||||
--color-primary: #FF4500;
|
||||
--color-secondary: #FF6246;
|
||||
--color-accent: #FFD600;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #F7F0E8;
|
||||
--color-bg-secondary: #DCD0BA;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="sunset"].dark,
|
||||
.dark[data-theme="sunset"] {
|
||||
--color-primary: #FF9E60;
|
||||
--color-secondary: #FFAD7C;
|
||||
--color-accent: #FFD600;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #201813;
|
||||
--color-bg-secondary: #433329;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Monochrome — Elegant grayscale */
|
||||
/* ================================================================== */
|
||||
[data-theme="monochrome"] {
|
||||
--color-primary: #333333;
|
||||
--color-secondary: #666666;
|
||||
--color-accent: #999999;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #F0F0F0;
|
||||
--color-bg-secondary: #D4D4D4;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="monochrome"].dark,
|
||||
.dark[data-theme="monochrome"] {
|
||||
--color-primary: #E5E5E5;
|
||||
--color-secondary: #BFBFBF;
|
||||
--color-accent: #D1D1D1;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #161616;
|
||||
--color-bg-secondary: #3B3B3B;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Lavender — Soft purple with pink accents */
|
||||
/* ================================================================== */
|
||||
[data-theme="lavender"] {
|
||||
--color-primary: #6B418A;
|
||||
--color-secondary: #8A60AF;
|
||||
--color-accent: #E24982;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #F1EFF5;
|
||||
--color-bg-secondary: #D9D1DF;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="lavender"].dark,
|
||||
.dark[data-theme="lavender"] {
|
||||
--color-primary: #D1AFE2;
|
||||
--color-secondary: #DDBFEA;
|
||||
--color-accent: #FF9EC6;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #17131E;
|
||||
--color-bg-secondary: #393042;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Crimson — Bold red with warm highlights */
|
||||
/* ================================================================== */
|
||||
[data-theme="crimson"] {
|
||||
--color-primary: #B51E28;
|
||||
--color-secondary: #992D38;
|
||||
--color-accent: #E26000;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #F6EDEB;
|
||||
--color-bg-secondary: #DECFCC;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="crimson"].dark,
|
||||
.dark[data-theme="crimson"] {
|
||||
--color-primary: #FF827C;
|
||||
--color-secondary: #F99993;
|
||||
--color-accent: #FFB56B;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #1B1215;
|
||||
--color-bg-secondary: #412E39;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Midnight — Deep navy with sky blue */
|
||||
/* ================================================================== */
|
||||
[data-theme="midnight"] {
|
||||
--color-primary: #1E4993;
|
||||
--color-secondary: #2D60AF;
|
||||
--color-accent: #4993E2;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #EDF0F7;
|
||||
--color-bg-secondary: #CCD5E2;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="midnight"].dark,
|
||||
.dark[data-theme="midnight"] {
|
||||
--color-primary: #82B5EA;
|
||||
--color-secondary: #93C6F2;
|
||||
--color-accent: #9ED8FF;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #12161F;
|
||||
--color-bg-secondary: #2F3848;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Desert — Warm terracotta and sand tones */
|
||||
/* ================================================================== */
|
||||
[data-theme="desert"] {
|
||||
--color-primary: #AF6049;
|
||||
--color-secondary: #9E7C60;
|
||||
--color-accent: #D1932D;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #F6F0EA;
|
||||
--color-bg-secondary: #E5D8C6;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="desert"].dark,
|
||||
.dark[data-theme="desert"] {
|
||||
--color-primary: #F2B593;
|
||||
--color-secondary: #EAD1AF;
|
||||
--color-accent: #FFD86B;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #1F1C16;
|
||||
--color-bg-secondary: #494138;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* THEME: Mint — Fresh green with turquoise */
|
||||
/* ================================================================== */
|
||||
[data-theme="mint"] {
|
||||
--color-primary: #38AF93;
|
||||
--color-secondary: #60C6AF;
|
||||
--color-accent: #2D9EAF;
|
||||
--color-error: #DD1C1A;
|
||||
--color-bg-primary: #EDF6F0;
|
||||
--color-bg-secondary: #D1E2D8;
|
||||
--color-text-primary: #111111;
|
||||
--color-text-secondary: #444444;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-primary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
}
|
||||
|
||||
[data-theme="mint"].dark,
|
||||
.dark[data-theme="mint"] {
|
||||
--color-primary: #93F2D8;
|
||||
--color-secondary: #BFF9EA;
|
||||
--color-accent: #6BEAF2;
|
||||
--color-error: #FF5244;
|
||||
--color-bg-primary: #161F1F;
|
||||
--color-bg-secondary: #384949;
|
||||
--color-text-primary: #F5F5F5;
|
||||
--color-text-secondary: #C6C6C6;
|
||||
--color-text-on-primary: #FFFFFF;
|
||||
|
||||
--primary: var(--color-primary);
|
||||
--primary-foreground: var(--color-text-on-primary);
|
||||
--secondary: var(--color-bg-secondary);
|
||||
--secondary-foreground: var(--color-text-primary);
|
||||
--accent: var(--color-bg-secondary);
|
||||
--accent-foreground: var(--color-text-primary);
|
||||
--background: var(--color-bg-primary);
|
||||
--foreground: var(--color-text-primary);
|
||||
--card: var(--color-bg-secondary);
|
||||
--card-foreground: var(--color-text-primary);
|
||||
--popover: var(--color-bg-secondary);
|
||||
--popover-foreground: var(--color-text-primary);
|
||||
--muted: var(--color-bg-secondary);
|
||||
--muted-foreground: var(--color-text-secondary);
|
||||
--destructive: var(--color-error);
|
||||
--border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--input: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
|
||||
--ring: var(--color-primary);
|
||||
|
||||
--sidebar: var(--color-bg-secondary);
|
||||
--sidebar-foreground: var(--color-text-primary);
|
||||
--sidebar-primary: var(--color-primary);
|
||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||
--sidebar-accent: var(--color-bg-primary);
|
||||
--sidebar-accent-foreground: var(--color-text-primary);
|
||||
--sidebar-border: color-mix(in srgb, var(--color-text-primary) 12%, transparent);
|
||||
--sidebar-ring: var(--color-primary);
|
||||
|
||||
/* Chart palette */
|
||||
--chart-1: #8FB896;
|
||||
--chart-2: #D4A08A;
|
||||
--chart-3: #6B8F71;
|
||||
--chart-4: #C4856A;
|
||||
--chart-5: #A3C4A8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user