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 (
|
return (
|
||||||
<div className="min-h-screen flex bg-[#FAFAF7]">
|
<div className="min-h-screen flex bg-[#FAFAF7]">
|
||||||
{/* Left brand panel — hidden on mobile */}
|
{/* 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 */}
|
{/* 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 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-[#0D7C66]/10 blur-[80px] 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 */}
|
{/* Subtle grid */}
|
||||||
<div
|
<div
|
||||||
@@ -40,15 +40,15 @@ export default function AuthLayout({ children }: { children: React.ReactNode })
|
|||||||
<div className="relative">
|
<div className="relative">
|
||||||
<h2 className="font-heading text-3xl font-bold text-white leading-snug mb-4">
|
<h2 className="font-heading text-3xl font-bold text-white leading-snug mb-4">
|
||||||
Home maintenance,<br />
|
Home maintenance,<br />
|
||||||
<span className="text-[#E07A3A]">simplified.</span>
|
<span className="text-[#8FB896]">simplified.</span>
|
||||||
</h2>
|
</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
|
Track tasks, organize contractors, and store important
|
||||||
documents — all in one place built for homeowners.
|
documents — all in one place built for homeowners.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="relative text-xs text-[#78716C]">
|
<p className="relative text-xs text-[#8A8F87]">
|
||||||
© {new Date().getFullYear()} Casera
|
© {new Date().getFullYear()} Casera
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default function DemoLandingPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen flex-col items-center justify-center bg-[#FAFAF7] px-6 relative overflow-hidden">
|
<div className="flex min-h-screen flex-col items-center justify-center bg-[#FAFAF7] px-6 relative overflow-hidden">
|
||||||
{/* Decorative background */}
|
{/* 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 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-[#0D7C66]/[0.03] 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">
|
<div className="relative mx-auto max-w-lg text-center">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
@@ -21,16 +21,16 @@ export default function DemoLandingPage() {
|
|||||||
height={36}
|
height={36}
|
||||||
className="rounded-lg"
|
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
|
Casera
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Hero */}
|
{/* 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
|
See Casera in action
|
||||||
</h1>
|
</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 —
|
Explore the full app with sample data. No account needed —
|
||||||
just click and start exploring.
|
just click and start exploring.
|
||||||
</p>
|
</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">
|
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||||
<Link
|
<Link
|
||||||
href="/demo/app"
|
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" />
|
<Play className="size-4" />
|
||||||
Launch Demo
|
Launch Demo
|
||||||
@@ -48,9 +48,9 @@ export default function DemoLandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Login link */}
|
{/* Login link */}
|
||||||
<p className="mt-8 text-sm text-[#A8A29E]">
|
<p className="mt-8 text-sm text-[#9A9E97]">
|
||||||
Already have an account?{" "}
|
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
|
Sign In
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
+28
-13
@@ -49,25 +49,40 @@
|
|||||||
--radius-4xl: calc(var(--radius) + 16px);
|
--radius-4xl: calc(var(--radius) + 16px);
|
||||||
|
|
||||||
/* App-specific theme-aware Tailwind utilities */
|
/* App-specific theme-aware Tailwind utilities */
|
||||||
--color-bg-primary: #FFFFFF;
|
--color-bg-primary: var(--color-bg-primary);
|
||||||
--color-bg-secondary: #F7F7F7;
|
--color-bg-secondary: var(--color-bg-secondary);
|
||||||
--color-text-primary: #1C1917;
|
--color-text-primary: var(--color-text-primary);
|
||||||
--color-text-secondary: #78716C;
|
--color-text-secondary: var(--color-text-secondary);
|
||||||
--color-text-on-primary: #FFFFFF;
|
--color-text-on-primary: var(--color-text-on-primary);
|
||||||
--color-app-primary: var(--color-primary);
|
--color-app-primary: var(--color-primary);
|
||||||
--color-app-secondary: var(--color-secondary);
|
--color-app-secondary: var(--color-secondary);
|
||||||
--color-app-accent: var(--color-accent);
|
--color-app-accent: var(--color-accent);
|
||||||
--color-app-error: var(--color-error);
|
--color-app-error: var(--color-error);
|
||||||
|
|
||||||
/* Landing page brand colors (theme-independent) */
|
/* Brand colors — Warm Sage palette */
|
||||||
--color-brand-orange: #E07A3A;
|
--color-brand-sage: #6B8F71;
|
||||||
--color-brand-orange-dark: #C4632A;
|
--color-brand-sage-light: #EDF2ED;
|
||||||
--color-brand-orange-light: #FFF3EB;
|
--color-brand-clay: #C4856A;
|
||||||
--color-brand-teal: #0D7C66;
|
--color-brand-clay-light: #FDF3EE;
|
||||||
--color-brand-teal-light: #ECFDF5;
|
--color-brand-charcoal: #2D3436;
|
||||||
--color-brand-slate: #1C1917;
|
--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;
|
--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 */
|
/* Animation tokens */
|
||||||
--animate-fade-up: fade-up 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
|
--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;
|
--animate-fade-in: fade-in 0.6s ease both;
|
||||||
@@ -76,7 +91,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--radius: 0.625rem;
|
--radius: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
|
|||||||
+53
-53
@@ -18,14 +18,14 @@ const features = [
|
|||||||
title: "Smart Task Tracking",
|
title: "Smart Task Tracking",
|
||||||
description:
|
description:
|
||||||
"Kanban boards, recurring schedules, and due date reminders keep every repair and project on track.",
|
"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,
|
icon: HardHat,
|
||||||
title: "Contractor Rolodex",
|
title: "Contractor Rolodex",
|
||||||
description:
|
description:
|
||||||
"Store contact details, specialties, and notes for every service provider. Never lose a plumber's number again.",
|
"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,
|
icon: FileText,
|
||||||
@@ -82,9 +82,9 @@ const highlights = [
|
|||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
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 ─── */}
|
{/* ─── 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">
|
<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">
|
<Link href="/" className="flex items-center gap-2.5">
|
||||||
<Image
|
<Image
|
||||||
@@ -94,7 +94,7 @@ export default function HomePage() {
|
|||||||
height={32}
|
height={32}
|
||||||
className="rounded-lg"
|
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
|
Casera
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -102,19 +102,19 @@ export default function HomePage() {
|
|||||||
<div className="hidden md:flex items-center gap-8">
|
<div className="hidden md:flex items-center gap-8">
|
||||||
<a
|
<a
|
||||||
href="#features"
|
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
|
Features
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="#how-it-works"
|
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
|
How It Works
|
||||||
</a>
|
</a>
|
||||||
<Link
|
<Link
|
||||||
href="/demo"
|
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
|
Demo
|
||||||
</Link>
|
</Link>
|
||||||
@@ -123,13 +123,13 @@ export default function HomePage() {
|
|||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Link
|
<Link
|
||||||
href="/login"
|
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
|
Sign In
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/register"
|
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
|
Get Started
|
||||||
<ArrowRight className="size-3.5" />
|
<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">
|
<section className="relative pt-32 pb-24 md:pt-40 md:pb-32 overflow-hidden">
|
||||||
{/* Decorative background */}
|
{/* Decorative background */}
|
||||||
<div className="absolute inset-0 pointer-events-none">
|
<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 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-[#0D7C66]/[0.03] blur-3xl" />
|
<div className="absolute bottom-0 left-[-5%] w-[400px] h-[400px] rounded-full bg-[#C4856A]/[0.03] blur-3xl" />
|
||||||
{/* Subtle grid pattern */}
|
{/* Subtle grid pattern */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 opacity-[0.03]"
|
className="absolute inset-0 opacity-[0.03]"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage:
|
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",
|
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-7xl mx-auto px-6 relative">
|
||||||
<div className="max-w-3xl">
|
<div className="max-w-3xl">
|
||||||
{/* Badge */}
|
{/* 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">
|
<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-[#0D7C66] animate-pulse" />
|
<span className="inline-block size-2 rounded-full bg-[#6B8F71] animate-pulse" />
|
||||||
Now available for homeowners
|
Now available for homeowners
|
||||||
</div>
|
</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]">
|
<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,{" "}
|
Your home,{" "}
|
||||||
<span className="text-[#E07A3A]">perfectly maintained.</span>
|
<span className="text-[#6B8F71]">perfectly maintained.</span>
|
||||||
</h1>
|
</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
|
Track tasks, organize contractors, and store important
|
||||||
documents. Everything you need to keep your home running
|
documents. Everything you need to keep your home running
|
||||||
smoothly — in one place.
|
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">
|
<div className="animate-fade-up stagger-4 mt-10 flex flex-wrap gap-4">
|
||||||
<Link
|
<Link
|
||||||
href="/register"
|
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
|
Get Started — Free
|
||||||
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="/demo"
|
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
|
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>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</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="animate-fade-up stagger-5 hidden lg:block absolute top-12 right-6 w-[420px]">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* Main card */}
|
{/* 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="flex items-center gap-3 mb-4">
|
||||||
<div className="size-8 rounded-lg bg-[#FFF3EB] flex items-center justify-center">
|
<div className="size-8 rounded-lg bg-[#EDF2ED] flex items-center justify-center">
|
||||||
<CheckSquare className="size-4 text-[#E07A3A]" />
|
<CheckSquare className="size-4 text-[#6B8F71]" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-semibold">Upcoming Tasks</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>
|
</div>
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
{[
|
{[
|
||||||
{ task: "Replace HVAC filter", due: "Tomorrow", status: "bg-[#FEF3C7] text-[#92400E]" },
|
{ task: "Replace HVAC filter", due: "Tomorrow", status: "bg-[#FEF3C7] text-[#92400E]" },
|
||||||
{ task: "Schedule gutter cleaning", due: "Wed", status: "bg-[#ECFDF5] text-[#0D7C66]" },
|
{ task: "Schedule gutter cleaning", due: "Wed", status: "bg-[#EDF2ED] text-[#6B8F71]" },
|
||||||
{ task: "Check smoke detectors", due: "Fri", status: "bg-[#FFF3EB] text-[#E07A3A]" },
|
{ task: "Check smoke detectors", due: "Fri", status: "bg-[#FDF3EE] text-[#C4856A]" },
|
||||||
].map((item) => (
|
].map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.task}
|
key={item.task}
|
||||||
@@ -229,13 +229,13 @@ export default function HomePage() {
|
|||||||
|
|
||||||
{/* Floating stat card */}
|
{/* Floating stat card */}
|
||||||
<div
|
<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" }}
|
style={{ animation: "float 6s ease-in-out infinite" }}
|
||||||
>
|
>
|
||||||
<div className="text-xs text-[#A8A29E] mb-1">This Month</div>
|
<div className="text-xs text-[#8A8F87] mb-1">This Month</div>
|
||||||
<div className="text-2xl font-bold font-heading text-[#0D7C66]">12 Done</div>
|
<div className="text-2xl font-bold font-heading text-[#6B8F71]">12 Done</div>
|
||||||
<div className="mt-2 h-1.5 rounded-full bg-[#F7F7F7] overflow-hidden">
|
<div className="mt-2 h-1.5 rounded-full bg-[#F2EFE9] overflow-hidden">
|
||||||
<div className="h-full w-3/4 rounded-full bg-[#0D7C66]" />
|
<div className="h-full w-3/4 rounded-full bg-[#6B8F71]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -244,7 +244,7 @@ export default function HomePage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── Social proof strip ─── */}
|
{/* ─── 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">
|
<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" },
|
{ value: "Free", label: "to get started" },
|
||||||
@@ -252,10 +252,10 @@ export default function HomePage() {
|
|||||||
{ value: "All-in-one", label: "home management" },
|
{ value: "All-in-one", label: "home management" },
|
||||||
].map((stat) => (
|
].map((stat) => (
|
||||||
<div key={stat.label} className="flex items-baseline gap-2">
|
<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}
|
{stat.value}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm text-[#A8A29E]">{stat.label}</span>
|
<span className="text-sm text-[#8A8F87]">{stat.label}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -265,13 +265,13 @@ export default function HomePage() {
|
|||||||
<section id="features" className="py-24 md:py-32">
|
<section id="features" className="py-24 md:py-32">
|
||||||
<div className="max-w-7xl mx-auto px-6">
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
<div className="max-w-2xl mb-16">
|
<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
|
Features
|
||||||
</p>
|
</p>
|
||||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
||||||
Everything your home needs, nothing it doesn't.
|
Everything your home needs, nothing it doesn't.
|
||||||
</h2>
|
</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,
|
Casera brings all your home maintenance into one clear,
|
||||||
organized space. No bloat, no learning curve.
|
organized space. No bloat, no learning curve.
|
||||||
</p>
|
</p>
|
||||||
@@ -281,7 +281,7 @@ export default function HomePage() {
|
|||||||
{features.map((feature, i) => (
|
{features.map((feature, i) => (
|
||||||
<div
|
<div
|
||||||
key={feature.title}
|
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
|
<div
|
||||||
className={`inline-flex items-center justify-center size-12 rounded-xl ${feature.color} mb-5`}
|
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">
|
<h3 className="font-heading text-xl font-bold mb-2">
|
||||||
{feature.title}
|
{feature.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#78716C] leading-relaxed">
|
<p className="text-[#8A8F87] leading-relaxed">
|
||||||
{feature.description}
|
{feature.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -303,11 +303,11 @@ export default function HomePage() {
|
|||||||
{/* ─── How It Works ─── */}
|
{/* ─── How It Works ─── */}
|
||||||
<section
|
<section
|
||||||
id="how-it-works"
|
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="max-w-7xl mx-auto px-6 relative">
|
||||||
<div className="text-center max-w-2xl mx-auto mb-16">
|
<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
|
How It Works
|
||||||
</p>
|
</p>
|
||||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
<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">
|
<div className="grid md:grid-cols-3 gap-8 md:gap-12">
|
||||||
{steps.map((step) => (
|
{steps.map((step) => (
|
||||||
<div key={step.number} className="text-center md:text-left">
|
<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}
|
{step.number}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-heading text-xl font-bold mb-2">
|
<h3 className="font-heading text-xl font-bold mb-2">
|
||||||
{step.title}
|
{step.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#78716C] leading-relaxed">
|
<p className="text-[#8A8F87] leading-relaxed">
|
||||||
{step.description}
|
{step.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -340,7 +340,7 @@ export default function HomePage() {
|
|||||||
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
<h2 className="font-heading text-3xl md:text-4xl font-bold tracking-tight">
|
||||||
Built for real homeowners
|
Built for real homeowners
|
||||||
</h2>
|
</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.
|
Thoughtful details that make home maintenance feel manageable.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -349,13 +349,13 @@ export default function HomePage() {
|
|||||||
{highlights.map((item) => (
|
{highlights.map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.title}
|
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">
|
<h3 className="font-heading font-bold text-base mb-1.5">
|
||||||
{item.title}
|
{item.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-[#78716C] leading-relaxed">
|
<p className="text-sm text-[#8A8F87] leading-relaxed">
|
||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -366,23 +366,23 @@ export default function HomePage() {
|
|||||||
|
|
||||||
{/* ─── CTA Section ─── */}
|
{/* ─── CTA Section ─── */}
|
||||||
<section className="py-24 md:py-32 relative overflow-hidden">
|
<section className="py-24 md:py-32 relative overflow-hidden">
|
||||||
<div className="absolute inset-0 bg-[#1C1917]" />
|
<div className="absolute inset-0 bg-[#2D3436]" />
|
||||||
{/* Orange glow */}
|
{/* Sage 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 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-[#0D7C66]/10 blur-[100px] 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">
|
<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">
|
<h2 className="font-heading text-3xl md:text-5xl font-bold tracking-tight text-white">
|
||||||
Ready to take control of your home?
|
Ready to take control of your home?
|
||||||
</h2>
|
</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.
|
Join homeowners who've simplified their maintenance routine.
|
||||||
Free to start, no credit card required.
|
Free to start, no credit card required.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-10 flex flex-wrap justify-center gap-4">
|
<div className="mt-10 flex flex-wrap justify-center gap-4">
|
||||||
<Link
|
<Link
|
||||||
href="/register"
|
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
|
Get Started — Free
|
||||||
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
<ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
|
||||||
@@ -398,7 +398,7 @@ export default function HomePage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── Footer ─── */}
|
{/* ─── 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="max-w-7xl mx-auto px-6 py-16">
|
||||||
<div className="grid md:grid-cols-4 gap-10">
|
<div className="grid md:grid-cols-4 gap-10">
|
||||||
{/* Brand */}
|
{/* Brand */}
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ export function RecentActivity() {
|
|||||||
</div>
|
</div>
|
||||||
) : notifications.length === 0 ? (
|
) : notifications.length === 0 ? (
|
||||||
<div className="flex flex-col items-center justify-center py-10 text-center">
|
<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">
|
<div className="size-11 rounded-xl bg-primary/10 flex items-center justify-center mb-3">
|
||||||
<Coffee className="size-5 text-[#E07A3A]" />
|
<Coffee className="size-5 text-primary" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm font-medium text-foreground">Nothing yet — all quiet!</p>
|
<p className="text-sm font-medium text-foreground">Nothing yet — all quiet!</p>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
|
|||||||
@@ -32,16 +32,16 @@ const stats = [
|
|||||||
key: "active",
|
key: "active",
|
||||||
label: "Active",
|
label: "Active",
|
||||||
icon: ClipboardList,
|
icon: ClipboardList,
|
||||||
iconColor: "text-[#0D7C66]",
|
iconColor: "text-primary",
|
||||||
bgColor: "bg-emerald-50 dark:bg-emerald-500/10",
|
bgColor: "bg-primary/10",
|
||||||
prop: "active" as const,
|
prop: "active" as const,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "completed",
|
key: "completed",
|
||||||
label: "Completed",
|
label: "Completed",
|
||||||
icon: CheckCircle2,
|
icon: CheckCircle2,
|
||||||
iconColor: "text-[#E07A3A]",
|
iconColor: "text-brand-clay",
|
||||||
bgColor: "bg-orange-50 dark:bg-orange-500/10",
|
bgColor: "bg-brand-clay/10",
|
||||||
prop: "completed" as const,
|
prop: "completed" as const,
|
||||||
},
|
},
|
||||||
] 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">
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
{stats.map((stat) => (
|
{stats.map((stat) => (
|
||||||
<Link key={stat.key} href={`${basePath}/tasks`}>
|
<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="flex items-center gap-3 mb-3">
|
||||||
<div className={`inline-flex items-center justify-center size-9 rounded-xl ${stat.bgColor}`}>
|
<div className={`inline-flex items-center justify-center size-9 rounded-xl ${stat.bgColor}`}>
|
||||||
<stat.icon className={`size-4 ${stat.iconColor}`} />
|
<stat.icon className={`size-4 ${stat.iconColor}`} />
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ export function TaskCompletionChart({ data }: TaskCompletionChartProps) {
|
|||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="count"
|
dataKey="count"
|
||||||
stroke="#E07A3A"
|
stroke="#6B8F71"
|
||||||
fill="#E07A3A"
|
fill="#6B8F71"
|
||||||
fillOpacity={0.1}
|
fillOpacity={0.1}
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
@@ -52,8 +52,8 @@ export function TaskCompletionChart({ data }: TaskCompletionChartProps) {
|
|||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col items-center justify-center h-[300px] text-center">
|
<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">
|
<div className="size-12 rounded-xl bg-primary/10 flex items-center justify-center mb-3">
|
||||||
<TrendingUp className="size-5 text-[#0D7C66]" />
|
<TrendingUp className="size-5 text-primary" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm font-medium text-foreground">Your progress chart lives here</p>
|
<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">
|
<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;
|
if (dismissed) return null;
|
||||||
|
|
||||||
return (
|
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">
|
<p className="font-medium">
|
||||||
You're exploring Casera in demo mode. Changes aren't saved.
|
You're exploring Casera in demo mode. Changes aren't saved.
|
||||||
</p>
|
</p>
|
||||||
@@ -21,7 +21,7 @@ export function DemoBanner() {
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon-xs"
|
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)}
|
onClick={() => setDismissed(true)}
|
||||||
aria-label="Dismiss banner"
|
aria-label="Dismiss banner"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function AuthFormWrapper({
|
|||||||
height={32}
|
height={32}
|
||||||
className="rounded-lg"
|
className="rounded-lg"
|
||||||
/>
|
/>
|
||||||
<span className="font-heading text-xl font-bold text-[#1C1917]">
|
<span className="font-heading text-xl font-bold text-foreground">
|
||||||
Casera
|
Casera
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import { Monitor, Moon, Sun } from "lucide-react";
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
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";
|
import { useThemeStore, type ColorMode } from "@/stores/theme";
|
||||||
|
|
||||||
const modeOptions: { value: ColorMode; label: string; icon: React.ElementType }[] = [
|
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() {
|
export function ThemePicker() {
|
||||||
const { themeId, mode, setTheme, setMode } = useThemeStore();
|
const { mode, setMode } = useThemeStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Appearance</CardTitle>
|
<CardTitle>Appearance</CardTitle>
|
||||||
<CardDescription>Choose a theme and color mode for the app.</CardDescription>
|
<CardDescription>Choose a color mode for the app.</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-6">
|
<CardContent>
|
||||||
{/* 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 */}
|
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-medium mb-3">Mode</p>
|
<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">
|
<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> = {
|
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",
|
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",
|
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",
|
upcoming_tasks: "border-[#6B8F71]/20 bg-[#EDF2ED]/50 dark:border-[#8FB896]/20 dark:bg-[#8FB896]/5",
|
||||||
in_progress_tasks: "border-emerald-200 bg-emerald-50/40 dark:border-emerald-500/20 dark:bg-emerald-950/20",
|
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",
|
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",
|
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> = {
|
const COLUMN_HEADER_COLORS: Record<string, string> = {
|
||||||
overdue_tasks: "text-red-700 dark:text-red-400",
|
overdue_tasks: "text-red-700 dark:text-red-400",
|
||||||
due_soon_tasks: "text-amber-700 dark:text-amber-400",
|
due_soon_tasks: "text-amber-700 dark:text-amber-400",
|
||||||
upcoming_tasks: "text-blue-700 dark:text-blue-400",
|
upcoming_tasks: "text-[#6B8F71] dark:text-[#8FB896]",
|
||||||
in_progress_tasks: "text-emerald-700 dark:text-emerald-400",
|
in_progress_tasks: "text-[#C4856A] dark:text-[#D4A08A]",
|
||||||
completed_tasks: "text-stone-600 dark:text-stone-400",
|
completed_tasks: "text-stone-600 dark:text-stone-400",
|
||||||
cancelled_tasks: "text-slate-600 dark:text-slate-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> = {
|
const COUNT_BADGE_COLORS: Record<string, string> = {
|
||||||
overdue_tasks: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300",
|
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",
|
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",
|
upcoming_tasks: "bg-[#6B8F71]/15 text-[#6B8F71] dark:bg-[#8FB896]/20 dark:text-[#8FB896]",
|
||||||
in_progress_tasks: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300",
|
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",
|
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",
|
cancelled_tasks: "bg-slate-100 text-slate-700 dark:bg-slate-900/50 dark:text-slate-300",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"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 { useTheme, type ColorMode } from "@/lib/themes/use-theme";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
@@ -13,11 +13,10 @@ const modeOptions: { value: ColorMode; label: string; icon: React.ElementType }[
|
|||||||
/**
|
/**
|
||||||
* Theme switcher component.
|
* 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 }) {
|
export function ThemeSwitcher({ className }: { className?: string }) {
|
||||||
const { themeId, mode, effectiveMode, themes, setTheme, setMode } = useTheme();
|
const { mode, setMode } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn("flex flex-col gap-4", className)}>
|
<div className={cn("flex flex-col gap-4", className)}>
|
||||||
@@ -40,42 +39,6 @@ export function ThemeSwitcher({ className }: { className?: string }) {
|
|||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-291
@@ -19,305 +19,34 @@ export interface ThemeDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All 11 themes matching the KMM/iOS theme system.
|
* Single "Warm Sage" theme — the Casera brand palette.
|
||||||
* Hex values are taken directly from ThemeColors.kt.
|
|
||||||
*/
|
*/
|
||||||
export const themes: ThemeDefinition[] = [
|
export const themes: ThemeDefinition[] = [
|
||||||
{
|
{
|
||||||
id: "default",
|
id: "default",
|
||||||
name: "Default",
|
name: "Warm Sage",
|
||||||
description: "Warm orange with teal accents",
|
description: "Calming sage with warm clay accents",
|
||||||
light: {
|
light: {
|
||||||
primary: "#E07A3A",
|
primary: "#6B8F71",
|
||||||
secondary: "#0D7C66",
|
secondary: "#C4856A",
|
||||||
accent: "#D4A574",
|
accent: "#C4856A",
|
||||||
error: "#DC2626",
|
error: "#C75B4A",
|
||||||
bgPrimary: "#FFFFFF",
|
bgPrimary: "#FAFAF7",
|
||||||
bgSecondary: "#F7F7F7",
|
bgSecondary: "#F2EFE9",
|
||||||
textPrimary: "#1C1917",
|
textPrimary: "#2D3436",
|
||||||
textSecondary: "#78716C",
|
textSecondary: "#8A8F87",
|
||||||
textOnPrimary: "#FFFFFF",
|
textOnPrimary: "#FFFFFF",
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
primary: "#F0A070",
|
primary: "#8FB896",
|
||||||
secondary: "#4FC9AF",
|
secondary: "#D4A08A",
|
||||||
accent: "#DDB892",
|
accent: "#D4A08A",
|
||||||
error: "#EF4444",
|
error: "#E07A6B",
|
||||||
bgPrimary: "#0A0A0A",
|
bgPrimary: "#1A1D1A",
|
||||||
bgSecondary: "#161616",
|
bgSecondary: "#2A2E2A",
|
||||||
textPrimary: "#FAFAFA",
|
textPrimary: "#E8E5DF",
|
||||||
textSecondary: "#A1A1A1",
|
textSecondary: "#9A9E97",
|
||||||
textOnPrimary: "#0A0A0A",
|
textOnPrimary: "#1A1D1A",
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,14 +4,8 @@ import { useEffect } from "react";
|
|||||||
import { useThemeStore } from "@/stores/theme";
|
import { useThemeStore } from "@/stores/theme";
|
||||||
|
|
||||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
const themeId = useThemeStore((s) => s.themeId);
|
|
||||||
const mode = useThemeStore((s) => s.mode);
|
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
|
// Sync dark class based on mode + system preference
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const applyDarkClass = (isDark: boolean) => {
|
const applyDarkClass = (isDark: boolean) => {
|
||||||
@@ -41,22 +35,5 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||||||
return () => mql.removeEventListener("change", handler);
|
return () => mql.removeEventListener("change", handler);
|
||||||
}, [mode]);
|
}, [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}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { themes, getThemeById, type ThemeDefinition } from "./theme-config";
|
|||||||
* (accounting for system preference), and setters.
|
* (accounting for system preference), and setters.
|
||||||
*/
|
*/
|
||||||
export function useTheme() {
|
export function useTheme() {
|
||||||
const { themeId, mode, setTheme, setMode } = useThemeStore();
|
const { mode, setMode } = useThemeStore();
|
||||||
|
|
||||||
const [effectiveMode, setEffectiveMode] = useState<"light" | "dark">("light");
|
const [effectiveMode, setEffectiveMode] = useState<"light" | "dark">("light");
|
||||||
|
|
||||||
@@ -28,11 +28,9 @@ export function useTheme() {
|
|||||||
return () => mql.removeEventListener("change", handler);
|
return () => mql.removeEventListener("change", handler);
|
||||||
}, [mode]);
|
}, [mode]);
|
||||||
|
|
||||||
const currentTheme: ThemeDefinition = getThemeById(themeId);
|
const currentTheme: ThemeDefinition = getThemeById("default");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/** Current theme ID string */
|
|
||||||
themeId,
|
|
||||||
/** Current mode setting (light | dark | system) */
|
/** Current mode setting (light | dark | system) */
|
||||||
mode,
|
mode,
|
||||||
/** Resolved mode after considering system preference */
|
/** Resolved mode after considering system preference */
|
||||||
@@ -41,8 +39,6 @@ export function useTheme() {
|
|||||||
currentTheme,
|
currentTheme,
|
||||||
/** All available theme definitions */
|
/** All available theme definitions */
|
||||||
themes,
|
themes,
|
||||||
/** Set the active theme by ID */
|
|
||||||
setTheme,
|
|
||||||
/** Set the color mode */
|
/** Set the color mode */
|
||||||
setMode,
|
setMode,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,22 +1,17 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
import { DEFAULT_THEME_ID } from "@/lib/themes/theme-config";
|
|
||||||
|
|
||||||
export type ColorMode = "light" | "dark" | "system";
|
export type ColorMode = "light" | "dark" | "system";
|
||||||
|
|
||||||
interface ThemeState {
|
interface ThemeState {
|
||||||
themeId: string;
|
|
||||||
mode: ColorMode;
|
mode: ColorMode;
|
||||||
setTheme: (themeId: string) => void;
|
|
||||||
setMode: (mode: ColorMode) => void;
|
setMode: (mode: ColorMode) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useThemeStore = create<ThemeState>()(
|
export const useThemeStore = create<ThemeState>()(
|
||||||
persist(
|
persist(
|
||||||
(set) => ({
|
(set) => ({
|
||||||
themeId: DEFAULT_THEME_ID,
|
|
||||||
mode: "light",
|
mode: "light",
|
||||||
setTheme: (themeId: string) => set({ themeId }),
|
|
||||||
setMode: (mode: ColorMode) => set({ mode }),
|
setMode: (mode: ColorMode) => set({ mode }),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
|||||||
+44
-878
@@ -1,9 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Casera multi-theme design system
|
* Casera "Warm Sage" design system
|
||||||
* 11 themes x 2 modes (light/dark) = 22 palettes
|
* Single brand palette — light + dark mode
|
||||||
* Maps to shadcn/ui CSS variables and custom app variables
|
* Maps to shadcn/ui CSS variables and custom app variables
|
||||||
*
|
|
||||||
* Spacing and radius tokens are theme-independent.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -24,27 +22,19 @@
|
|||||||
--radius-xxl: 24px;
|
--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 {
|
:root {
|
||||||
/* App color tokens – light */
|
/* App color tokens – light */
|
||||||
--color-primary: #E07A3A;
|
--color-primary: #6B8F71;
|
||||||
--color-secondary: #0D7C66;
|
--color-secondary: #C4856A;
|
||||||
--color-accent: #D4A574;
|
--color-accent: #C4856A;
|
||||||
--color-error: #DC2626;
|
--color-error: #C75B4A;
|
||||||
--color-bg-primary: #FFFFFF;
|
--color-bg-primary: #FAFAF7;
|
||||||
--color-bg-secondary: #F7F7F7;
|
--color-bg-secondary: #F2EFE9;
|
||||||
--color-text-primary: #1C1917;
|
--color-text-primary: #2D3436;
|
||||||
--color-text-secondary: #78716C;
|
--color-text-secondary: #8A8F87;
|
||||||
--color-text-on-primary: #FFFFFF;
|
--color-text-on-primary: #FFFFFF;
|
||||||
|
|
||||||
/* shadcn overrides */
|
/* shadcn overrides */
|
||||||
@@ -63,8 +53,8 @@
|
|||||||
--muted: var(--color-bg-secondary);
|
--muted: var(--color-bg-secondary);
|
||||||
--muted-foreground: var(--color-text-secondary);
|
--muted-foreground: var(--color-text-secondary);
|
||||||
--destructive: var(--color-error);
|
--destructive: var(--color-error);
|
||||||
--border: #E8E8E8;
|
--border: #E8E3DC;
|
||||||
--input: #E8E8E8;
|
--input: #E8E3DC;
|
||||||
--ring: var(--color-primary);
|
--ring: var(--color-primary);
|
||||||
|
|
||||||
--sidebar: #FFFFFF;
|
--sidebar: #FFFFFF;
|
||||||
@@ -73,21 +63,30 @@
|
|||||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||||
--sidebar-accent: var(--color-bg-secondary);
|
--sidebar-accent: var(--color-bg-secondary);
|
||||||
--sidebar-accent-foreground: var(--color-text-primary);
|
--sidebar-accent-foreground: var(--color-text-primary);
|
||||||
--sidebar-border: #E7E5E4;
|
--sidebar-border: #E8E3DC;
|
||||||
--sidebar-ring: var(--color-primary);
|
--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"] {
|
/* Dark mode */
|
||||||
--color-primary: #F0A070;
|
/* ================================================================== */
|
||||||
--color-secondary: #4FC9AF;
|
.dark {
|
||||||
--color-accent: #DDB892;
|
--color-primary: #8FB896;
|
||||||
--color-error: #EF4444;
|
--color-secondary: #D4A08A;
|
||||||
--color-bg-primary: #0A0A0A;
|
--color-accent: #D4A08A;
|
||||||
--color-bg-secondary: #161616;
|
--color-error: #E07A6B;
|
||||||
--color-text-primary: #FAFAFA;
|
--color-bg-primary: #1A1D1A;
|
||||||
--color-text-secondary: #A1A1A1;
|
--color-bg-secondary: #2A2E2A;
|
||||||
--color-text-on-primary: #0A0A0A;
|
--color-text-primary: #E8E5DF;
|
||||||
|
--color-text-secondary: #9A9E97;
|
||||||
|
--color-text-on-primary: #1A1D1A;
|
||||||
|
|
||||||
--primary: var(--color-primary);
|
--primary: var(--color-primary);
|
||||||
--primary-foreground: var(--color-text-on-primary);
|
--primary-foreground: var(--color-text-on-primary);
|
||||||
@@ -97,9 +96,9 @@
|
|||||||
--accent-foreground: var(--color-text-primary);
|
--accent-foreground: var(--color-text-primary);
|
||||||
--background: var(--color-bg-primary);
|
--background: var(--color-bg-primary);
|
||||||
--foreground: var(--color-text-primary);
|
--foreground: var(--color-text-primary);
|
||||||
--card: #141414;
|
--card: #232823;
|
||||||
--card-foreground: var(--color-text-primary);
|
--card-foreground: var(--color-text-primary);
|
||||||
--popover: #141414;
|
--popover: #232823;
|
||||||
--popover-foreground: var(--color-text-primary);
|
--popover-foreground: var(--color-text-primary);
|
||||||
--muted: var(--color-bg-secondary);
|
--muted: var(--color-bg-secondary);
|
||||||
--muted-foreground: var(--color-text-secondary);
|
--muted-foreground: var(--color-text-secondary);
|
||||||
@@ -108,7 +107,7 @@
|
|||||||
--input: rgba(255, 255, 255, 0.12);
|
--input: rgba(255, 255, 255, 0.12);
|
||||||
--ring: var(--color-primary);
|
--ring: var(--color-primary);
|
||||||
|
|
||||||
--sidebar: #141414;
|
--sidebar: #232823;
|
||||||
--sidebar-foreground: var(--color-text-primary);
|
--sidebar-foreground: var(--color-text-primary);
|
||||||
--sidebar-primary: var(--color-primary);
|
--sidebar-primary: var(--color-primary);
|
||||||
--sidebar-primary-foreground: var(--color-text-on-primary);
|
--sidebar-primary-foreground: var(--color-text-on-primary);
|
||||||
@@ -116,844 +115,11 @@
|
|||||||
--sidebar-accent-foreground: var(--color-text-primary);
|
--sidebar-accent-foreground: var(--color-text-primary);
|
||||||
--sidebar-border: rgba(255, 255, 255, 0.1);
|
--sidebar-border: rgba(255, 255, 255, 0.1);
|
||||||
--sidebar-ring: var(--color-primary);
|
--sidebar-ring: var(--color-primary);
|
||||||
}
|
|
||||||
|
/* Chart palette */
|
||||||
/* ================================================================== */
|
--chart-1: #8FB896;
|
||||||
/* THEME: Teal — Blue-green with warm accents */
|
--chart-2: #D4A08A;
|
||||||
/* ================================================================== */
|
--chart-3: #6B8F71;
|
||||||
[data-theme="teal"] {
|
--chart-4: #C4856A;
|
||||||
--color-primary: #069FC3;
|
--chart-5: #A3C4A8;
|
||||||
--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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user