diff --git a/src/apps/officer-web/App.tsx b/src/apps/officer-web/App.tsx
index 1f7f0cb4..26b88784 100644
--- a/src/apps/officer-web/App.tsx
+++ b/src/apps/officer-web/App.tsx
@@ -55,8 +55,8 @@ export function App() {
} />
} />
} />
- {plugins?.FileBrowser !== false && } />}
- {plugins?.Terminal !== false && } />}
+ } />
+ } />
} />
} />
} />
diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/Appearance.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/Appearance.tsx
deleted file mode 100644
index 8951767d..00000000
--- a/src/apps/officer-web/Screens/Dashboard/Settings/Appearance.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Palette, Sun, Moon } from 'lucide-react';
-import { useTheme } from '@/components/ui/ThemeProvider';
-import { Card } from '@/components/Card';
-import { useSettings } from '@/state/useSettings';
-
-export const Appearance = () => {
- const { settings, saveSettings } = useSettings();
- const { theme, setTheme } = useTheme();
-
- const handleThemeChange = (newTheme: string) => {
- setTheme(newTheme);
- saveSettings({ ...settings, appearance: { ...settings.appearance, theme: newTheme } });
- };
-
- return (
-
-
-
-
-
Theme
-
-
-
-
-
-
- );
-};
diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/Appearance.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/Appearance.tsx
new file mode 100644
index 00000000..61da9b0d
--- /dev/null
+++ b/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/Appearance.tsx
@@ -0,0 +1,31 @@
+import { useSettings } from '@/state/useSettings';
+import { themes } from 'themes';
+
+export const Appearance = () => {
+ const { settings, saveSettings } = useSettings();
+
+ const handleColorThemeChange = (colorTheme: string) => {
+ saveSettings({ ...settings, appearance: { ...settings.appearance, colorTheme } });
+ };
+
+ const activeColorTheme = settings.appearance.colorTheme ?? 'DuckPond';
+
+ return (
+
+ {themes.map((t) => (
+
+ ))}
+
+ );
+};
diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/index.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/index.tsx
index edc27261..eaacaaf0 100644
--- a/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/index.tsx
+++ b/src/apps/officer-web/Screens/Dashboard/Settings/ProfileSettings/index.tsx
@@ -1,5 +1,5 @@
import { useState, useEffect, useRef, useMemo } from 'react';
-import { Search, User, Lock, Globe, ListChecks } from 'lucide-react';
+import { Search, User, Lock, Globe, ListChecks, Palette } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion';
import { Card } from '@/components/Card';
@@ -8,6 +8,7 @@ import { UserData } from './UserData';
import { ChangePassword } from './ChangePassword';
import { Languages } from './Languages';
import { TaskDefaults } from './TaskDefaults';
+import { Appearance } from './Appearance';
const sections = [
{
@@ -17,6 +18,13 @@ const sections = [
description: 'Update your name and avatar.',
content: ,
},
+ {
+ key: 'appearance',
+ icon: Palette,
+ title: 'Appearance',
+ description: 'Color theme and light/dark mode.',
+ content: ,
+ },
{
key: 'tasks',
icon: ListChecks,
diff --git a/src/apps/officer-web/Screens/Dashboard/Settings/index.tsx b/src/apps/officer-web/Screens/Dashboard/Settings/index.tsx
index ffc67ded..2ed14cd2 100644
--- a/src/apps/officer-web/Screens/Dashboard/Settings/index.tsx
+++ b/src/apps/officer-web/Screens/Dashboard/Settings/index.tsx
@@ -2,7 +2,6 @@ import { Link } from 'react-router';
import { Bot, ChevronRight } from 'lucide-react';
import { Card } from '@/components/Card';
import { DashboardLayout } from '../Layout';
-import { Appearance } from './Appearance';
export const Settings = () => {
return (
@@ -23,7 +22,6 @@ export const Settings = () => {
-
diff --git a/src/apps/officer-web/frontend.tsx b/src/apps/officer-web/frontend.tsx
index 890a64ce..bdfa1a22 100644
--- a/src/apps/officer-web/frontend.tsx
+++ b/src/apps/officer-web/frontend.tsx
@@ -7,6 +7,17 @@ import { Toaster } from '@/components/ui/toaster';
import { Toaster as Sonner } from 'sonner';
import { TooltipProvider } from '@/components/ui/tooltip';
import 'themes/DuckPond/client';
+import 'themes/TokyoNight/client';
+import 'themes/CatppuccinLatte/client';
+import 'themes/CatppuccinMocha/client';
+import 'themes/Everforest/client';
+import 'themes/Gruvbox/client';
+import 'themes/Kanagawa/client';
+import 'themes/MatteBlack/client';
+import 'themes/Nord/client';
+import 'themes/OsakaJade/client';
+import 'themes/Ristretto/client';
+import 'themes/RosePine/client';
import './styles/index.css';
const headLinks = [
diff --git a/src/apps/officer-web/state/types/user-settings.ts b/src/apps/officer-web/state/types/user-settings.ts
index cb89eb27..74d4b406 100644
--- a/src/apps/officer-web/state/types/user-settings.ts
+++ b/src/apps/officer-web/state/types/user-settings.ts
@@ -16,6 +16,7 @@ export type UserSettings = {
};
appearance: {
theme: string;
+ colorTheme: string;
};
languages: {
spoken: string[];
@@ -44,6 +45,7 @@ export const DEFAULT_SETTINGS: UserSettings = {
},
appearance: {
theme: 'light',
+ colorTheme: 'DuckPond',
},
languages: {
spoken: ['en'],
diff --git a/src/apps/officer-web/state/useThemeSync.ts b/src/apps/officer-web/state/useThemeSync.ts
index 100d6e58..177d2a9c 100644
--- a/src/apps/officer-web/state/useThemeSync.ts
+++ b/src/apps/officer-web/state/useThemeSync.ts
@@ -1,32 +1,48 @@
-import { useEffect, useRef } from 'react';
+import { useEffect } from 'react';
import { useTheme } from '@/components/ui/ThemeProvider';
import { useSettings } from './useSettings';
-import { DEFAULT_SETTINGS } from './types/user-settings';
+
+const THEME_MODES: Record = {
+ DuckPond: 'light',
+ TokyoNight: 'dark',
+ CatppuccinLatte: 'light',
+ CatppuccinMocha: 'dark',
+ Everforest: 'dark',
+ Gruvbox: 'dark',
+ Kanagawa: 'dark',
+ MatteBlack: 'dark',
+ Nord: 'dark',
+ OsakaJade: 'dark',
+ Ristretto: 'dark',
+ RosePine: 'dark',
+};
+
+const BG_IMAGES: Record = {
+ DuckPond: 'url(/static/landscape1.jpg)',
+};
export const useThemeSync = () => {
- const { settings, saveSettings } = useSettings();
+ const { settings } = useSettings();
const { setTheme } = useTheme();
- const migrated = useRef(false);
useEffect(() => {
if (!settings) return;
+ const colorTheme = settings.appearance.colorTheme ?? 'DuckPond';
+ const root = document.documentElement;
- // One-time migration: if settings are default and localStorage has a theme, save it
- if (!migrated.current) {
- migrated.current = true;
- const lsTheme = localStorage.getItem('officer-theme');
- if (
- lsTheme &&
- settings.appearance.theme === DEFAULT_SETTINGS.appearance.theme &&
- lsTheme !== settings.appearance.theme
- ) {
- const updated = { ...settings, appearance: { ...settings.appearance, theme: lsTheme } };
- saveSettings(updated);
- setTheme(lsTheme);
- return;
- }
+ // Set data attribute for CSS scoping (DuckPond uses :root as default)
+ if (colorTheme === 'DuckPond') {
+ root.removeAttribute('data-color-theme');
+ } else {
+ root.setAttribute('data-color-theme', colorTheme);
}
- setTheme(settings.appearance.theme);
- }, [settings?.appearance.theme]);
+ // Set light/dark class based on theme mode
+ const mode = THEME_MODES[colorTheme] ?? 'light';
+ setTheme(mode);
+
+ // Set background image
+ const bgImage = BG_IMAGES[colorTheme] ?? 'none';
+ root.style.setProperty('--page-bg-image', bgImage);
+ }, [settings?.appearance?.colorTheme]);
};
diff --git a/src/workspaces/themes/CatppuccinLatte/client.ts b/src/workspaces/themes/CatppuccinLatte/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinLatte/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/CatppuccinLatte/index.ts b/src/workspaces/themes/CatppuccinLatte/index.ts
new file mode 100644
index 00000000..425bfc34
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinLatte/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'CatppuccinLatte', name: 'Catppuccin Latte', description: 'Warm pastel tones on a creamy light canvas.' };
diff --git a/src/workspaces/themes/CatppuccinLatte/prose.css b/src/workspaces/themes/CatppuccinLatte/prose.css
new file mode 100644
index 00000000..ca562fa8
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinLatte/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="CatppuccinLatte"] .file-viewer-md {
+ color: #4c4f69;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md h1 {
+ border-bottom-color: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md h2 {
+ border-bottom-color: rgba(204, 208, 218, 0.3);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md a {
+ color: #1e66f5;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md a:hover {
+ color: #04a5e5;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md strong {
+ color: #4c4f69;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md blockquote {
+ border-left-color: #1e66f5;
+ background: rgba(30, 102, 245, 0.06);
+ color: #6c6f85;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md li::marker {
+ color: #1e66f5;
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md hr {
+ background: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md th {
+ background: rgba(30, 102, 245, 0.08);
+ border-color: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md td {
+ border-color: rgba(204, 208, 218, 0.3);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(204, 208, 218, 0.1);
+}
+
+[data-color-theme="CatppuccinLatte"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #1e66f5;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="CatppuccinLatte"] .skill-md {
+ color: #4c4f69;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md h1 {
+ border-bottom-color: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md h2 {
+ border-bottom-color: rgba(204, 208, 218, 0.3);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md a {
+ color: #1e66f5;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md a:hover {
+ color: #04a5e5;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md strong {
+ color: #4c4f69;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md blockquote {
+ border-left-color: #1e66f5;
+ background: rgba(30, 102, 245, 0.06);
+ color: #6c6f85;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md li::marker {
+ color: #1e66f5;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md code {
+ background: rgba(30, 102, 245, 0.1);
+ color: #1e66f5;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md pre {
+ background: #e6e9ef;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md pre code {
+ color: #4c4f69;
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md hr {
+ background: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md th {
+ background: rgba(30, 102, 245, 0.08);
+ border-color: rgba(204, 208, 218, 0.4);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md td {
+ border-color: rgba(204, 208, 218, 0.3);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md tr:nth-child(even) {
+ background: rgba(204, 208, 218, 0.1);
+}
+
+[data-color-theme="CatppuccinLatte"] .skill-md input[type="checkbox"] {
+ accent-color: #1e66f5;
+}
diff --git a/src/workspaces/themes/CatppuccinLatte/variables.css b/src/workspaces/themes/CatppuccinLatte/variables.css
new file mode 100644
index 00000000..6fe4dd30
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinLatte/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="CatppuccinLatte"] {
+ /* Brand colors */
+ --duck-yellow: #df8e1d;
+ --duck-orange: #d20f39;
+ --duck-teal: #1e66f5;
+ --duck-forest: #6c6f85;
+ --duck-dark: #4c4f69;
+ --duck-beige: #dce0e8;
+
+ /* Page background */
+ --pixel-grid-color: rgba(30, 102, 245, 0.08);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(255, 255, 255, 0.1);
+ --glass-border: rgba(30, 102, 245, 0.2);
+ --dock-bg: rgba(0, 0, 0, 0.15);
+ --dock-border: rgba(30, 102, 245, 0.1);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.75);
+
+ /* Card component */
+ --card-bg: rgba(230, 233, 239, 0.92);
+ --card-grid-color: rgba(30, 102, 245, 0.06);
+
+ --cta: 219.9 91.5% 53.9%;
+ --cta-foreground: 220 23.1% 94.9%;
+
+ --naturegreen: 197.1 96.6% 45.7%;
+ --naturegreen-foreground: 220 23.1% 94.9%;
+
+ --background: 220 23.1% 94.9%;
+ --foreground: 233.8 16% 35.5%;
+
+ --card: 220 22% 92%;
+ --card-foreground: 233.8 16% 35.5%;
+
+ --popover: 220 22% 92%;
+ --popover-foreground: 233.8 16% 35.5%;
+
+ --primary: 219.9 91.5% 53.9%;
+ --primary-foreground: 220 23.1% 94.9%;
+
+ --secondary: 222.9 15.9% 82.7%;
+ --secondary-foreground: 233.8 16% 35.5%;
+
+ --muted: 220 20.7% 88.6%;
+ --muted-foreground: 232.8 10.4% 47.3%;
+
+ --accent: 197.1 96.6% 45.7%;
+ --accent-foreground: 220 23.1% 94.9%;
+
+ --destructive: 347.1 86.7% 44.1%;
+ --destructive-foreground: 220 23.1% 94.9%;
+
+ --success: 109.2 57.6% 39.8%;
+ --success-foreground: 220 23.1% 94.9%;
+
+ --brand: 219.9 91.5% 53.9%;
+ --brand-foreground: 220 23.1% 94.9%;
+ --brand-muted: 220 20.7% 88.6%;
+
+ --warning: 34.9 77% 49.4%;
+ --warning-foreground: 233.8 16% 35.5%;
+
+ --border: 222.9 15.9% 82.7%;
+ --input: 222.9 15.9% 82.7%;
+ --ring: 219.9 91.5% 53.9%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 219.9 91.5% 53.9%;
+ --chart-secondary: 34.9 77% 49.4%;
+
+ /* Status colors */
+ --status-success: 109.2 57.6% 39.8%;
+ --status-warning: 34.9 77% 49.4%;
+ --status-in-progress: 219.9 91.5% 53.9%;
+
+ --sidebar-background: 220 22% 92%;
+ --sidebar-foreground: 232.8 10.4% 47.3%;
+ --sidebar-primary: 219.9 91.5% 53.9%;
+ --sidebar-primary-foreground: 220 23.1% 94.9%;
+ --sidebar-accent: 220 20.7% 88.6%;
+ --sidebar-accent-foreground: 233.8 16% 35.5%;
+ --sidebar-border: 222.9 15.9% 82.7%;
+ --sidebar-ring: 219.9 91.5% 53.9%;
+
+ /* Hover Effect */
+ --ctahover: 197.1 96.6% 45.7%;
+ }
+}
diff --git a/src/workspaces/themes/CatppuccinMocha/client.ts b/src/workspaces/themes/CatppuccinMocha/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinMocha/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/CatppuccinMocha/index.ts b/src/workspaces/themes/CatppuccinMocha/index.ts
new file mode 100644
index 00000000..508cbd11
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinMocha/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'CatppuccinMocha', name: 'Catppuccin Mocha', description: 'Rich dark chocolate with pastel neon accents.' };
diff --git a/src/workspaces/themes/CatppuccinMocha/prose.css b/src/workspaces/themes/CatppuccinMocha/prose.css
new file mode 100644
index 00000000..eead51e2
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinMocha/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="CatppuccinMocha"] .file-viewer-md {
+ color: #cdd6f4;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md h1 {
+ border-bottom-color: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md h2 {
+ border-bottom-color: rgba(69, 71, 90, 0.3);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md a {
+ color: #89b4fa;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md a:hover {
+ color: #89dceb;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md strong {
+ color: #cdd6f4;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md blockquote {
+ border-left-color: #89b4fa;
+ background: rgba(137, 180, 250, 0.06);
+ color: #7f849c;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md li::marker {
+ color: #89b4fa;
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md hr {
+ background: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md th {
+ background: rgba(137, 180, 250, 0.08);
+ border-color: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md td {
+ border-color: rgba(69, 71, 90, 0.3);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(69, 71, 90, 0.1);
+}
+
+[data-color-theme="CatppuccinMocha"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #89b4fa;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="CatppuccinMocha"] .skill-md {
+ color: #cdd6f4;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md h1 {
+ border-bottom-color: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md h2 {
+ border-bottom-color: rgba(69, 71, 90, 0.3);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md a {
+ color: #89b4fa;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md a:hover {
+ color: #89dceb;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md strong {
+ color: #cdd6f4;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md blockquote {
+ border-left-color: #89b4fa;
+ background: rgba(137, 180, 250, 0.06);
+ color: #7f849c;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md li::marker {
+ color: #89b4fa;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md code {
+ background: rgba(137, 180, 250, 0.1);
+ color: #89b4fa;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md pre {
+ background: #181825;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md pre code {
+ color: #cdd6f4;
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md hr {
+ background: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md th {
+ background: rgba(137, 180, 250, 0.08);
+ border-color: rgba(69, 71, 90, 0.4);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md td {
+ border-color: rgba(69, 71, 90, 0.3);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md tr:nth-child(even) {
+ background: rgba(69, 71, 90, 0.1);
+}
+
+[data-color-theme="CatppuccinMocha"] .skill-md input[type="checkbox"] {
+ accent-color: #89b4fa;
+}
diff --git a/src/workspaces/themes/CatppuccinMocha/variables.css b/src/workspaces/themes/CatppuccinMocha/variables.css
new file mode 100644
index 00000000..f8105097
--- /dev/null
+++ b/src/workspaces/themes/CatppuccinMocha/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="CatppuccinMocha"] {
+ /* Brand colors */
+ --duck-yellow: #f9e2af;
+ --duck-orange: #fab387;
+ --duck-teal: #89b4fa;
+ --duck-forest: #7f849c;
+ --duck-dark: #cdd6f4;
+ --duck-beige: #313244;
+
+ /* Page background */
+ --pixel-grid-color: rgba(137, 180, 250, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(137, 180, 250, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(137, 180, 250, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(24, 24, 37, 0.92);
+ --card-grid-color: rgba(137, 180, 250, 0.04);
+
+ --cta: 217.2 91.9% 75.9%;
+ --cta-foreground: 240 21.1% 14.9%;
+
+ --naturegreen: 189.2 71% 72.9%;
+ --naturegreen-foreground: 240 21.1% 14.9%;
+
+ --background: 240 21.1% 14.9%;
+ --foreground: 226.2 63.9% 88%;
+
+ --card: 240 21.3% 12%;
+ --card-foreground: 226.2 63.9% 88%;
+
+ --popover: 240 21.3% 12%;
+ --popover-foreground: 226.2 63.9% 88%;
+
+ --primary: 217.2 91.9% 75.9%;
+ --primary-foreground: 240 21.1% 14.9%;
+
+ --secondary: 234.3 13.2% 31.2%;
+ --secondary-foreground: 226.2 63.9% 88%;
+
+ --muted: 236.8 16.2% 22.9%;
+ --muted-foreground: 229.7 12.8% 55.5%;
+
+ --accent: 189.2 71% 72.9%;
+ --accent-foreground: 240 21.1% 14.9%;
+
+ --destructive: 343.3 81.2% 74.9%;
+ --destructive-foreground: 240 21.1% 14.9%;
+
+ --success: 115.5 54.1% 76.1%;
+ --success-foreground: 240 21.1% 14.9%;
+
+ --brand: 217.2 91.9% 75.9%;
+ --brand-foreground: 240 21.1% 14.9%;
+ --brand-muted: 236.8 16.2% 22.9%;
+
+ --warning: 41.4 86% 83.1%;
+ --warning-foreground: 240 21.1% 14.9%;
+
+ --border: 234.3 13.2% 31.2%;
+ --input: 234.3 13.2% 31.2%;
+ --ring: 217.2 91.9% 75.9%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 217.2 91.9% 75.9%;
+ --chart-secondary: 41.4 86% 83.1%;
+
+ /* Status colors */
+ --status-success: 115.5 54.1% 76.1%;
+ --status-warning: 41.4 86% 83.1%;
+ --status-in-progress: 217.2 91.9% 75.9%;
+
+ --sidebar-background: 240 21.3% 12%;
+ --sidebar-foreground: 229.7 12.8% 55.5%;
+ --sidebar-primary: 217.2 91.9% 75.9%;
+ --sidebar-primary-foreground: 240 21.1% 14.9%;
+ --sidebar-accent: 236.8 16.2% 22.9%;
+ --sidebar-accent-foreground: 226.2 63.9% 88%;
+ --sidebar-border: 234.3 13.2% 31.2%;
+ --sidebar-ring: 217.2 91.9% 75.9%;
+
+ /* Hover Effect */
+ --ctahover: 189.2 71% 72.9%;
+ }
+}
diff --git a/src/workspaces/themes/Everforest/client.ts b/src/workspaces/themes/Everforest/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/Everforest/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/Everforest/index.ts b/src/workspaces/themes/Everforest/index.ts
new file mode 100644
index 00000000..0ce52f3f
--- /dev/null
+++ b/src/workspaces/themes/Everforest/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'Everforest', name: 'Everforest', description: 'Soft earthy greens from a quiet forest floor.' };
diff --git a/src/workspaces/themes/Everforest/prose.css b/src/workspaces/themes/Everforest/prose.css
new file mode 100644
index 00000000..923d23d9
--- /dev/null
+++ b/src/workspaces/themes/Everforest/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="Everforest"] .file-viewer-md {
+ color: #d3c6aa;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md h1 {
+ border-bottom-color: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md h2 {
+ border-bottom-color: rgba(61, 72, 77, 0.3);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md a {
+ color: #a7c080;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md a:hover {
+ color: #83c092;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md strong {
+ color: #d3c6aa;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md blockquote {
+ border-left-color: #a7c080;
+ background: rgba(167, 192, 128, 0.06);
+ color: #859289;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md li::marker {
+ color: #a7c080;
+}
+
+[data-color-theme="Everforest"] .file-viewer-md hr {
+ background: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md th {
+ background: rgba(167, 192, 128, 0.08);
+ border-color: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md td {
+ border-color: rgba(61, 72, 77, 0.3);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(61, 72, 77, 0.1);
+}
+
+[data-color-theme="Everforest"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #a7c080;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="Everforest"] .skill-md {
+ color: #d3c6aa;
+}
+
+[data-color-theme="Everforest"] .skill-md h1 {
+ border-bottom-color: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .skill-md h2 {
+ border-bottom-color: rgba(61, 72, 77, 0.3);
+}
+
+[data-color-theme="Everforest"] .skill-md a {
+ color: #a7c080;
+}
+
+[data-color-theme="Everforest"] .skill-md a:hover {
+ color: #83c092;
+}
+
+[data-color-theme="Everforest"] .skill-md strong {
+ color: #d3c6aa;
+}
+
+[data-color-theme="Everforest"] .skill-md blockquote {
+ border-left-color: #a7c080;
+ background: rgba(167, 192, 128, 0.06);
+ color: #859289;
+}
+
+[data-color-theme="Everforest"] .skill-md li::marker {
+ color: #a7c080;
+}
+
+[data-color-theme="Everforest"] .skill-md code {
+ background: rgba(167, 192, 128, 0.1);
+ color: #a7c080;
+}
+
+[data-color-theme="Everforest"] .skill-md pre {
+ background: #272e33;
+}
+
+[data-color-theme="Everforest"] .skill-md pre code {
+ color: #d3c6aa;
+}
+
+[data-color-theme="Everforest"] .skill-md hr {
+ background: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .skill-md th {
+ background: rgba(167, 192, 128, 0.08);
+ border-color: rgba(61, 72, 77, 0.4);
+}
+
+[data-color-theme="Everforest"] .skill-md td {
+ border-color: rgba(61, 72, 77, 0.3);
+}
+
+[data-color-theme="Everforest"] .skill-md tr:nth-child(even) {
+ background: rgba(61, 72, 77, 0.1);
+}
+
+[data-color-theme="Everforest"] .skill-md input[type="checkbox"] {
+ accent-color: #a7c080;
+}
diff --git a/src/workspaces/themes/Everforest/variables.css b/src/workspaces/themes/Everforest/variables.css
new file mode 100644
index 00000000..0970a235
--- /dev/null
+++ b/src/workspaces/themes/Everforest/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="Everforest"] {
+ /* Brand colors */
+ --duck-yellow: #dbbc7f;
+ --duck-orange: #e69875;
+ --duck-teal: #a7c080;
+ --duck-forest: #859289;
+ --duck-dark: #d3c6aa;
+ --duck-beige: #374247;
+
+ /* Page background */
+ --pixel-grid-color: rgba(167, 192, 128, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(167, 192, 128, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(167, 192, 128, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(39, 46, 51, 0.92);
+ --card-grid-color: rgba(167, 192, 128, 0.04);
+
+ --cta: 83.4 33.7% 62.7%;
+ --cta-foreground: 205.7 13.5% 20.4%;
+
+ --naturegreen: 134.8 32.6% 63.3%;
+ --naturegreen-foreground: 205.7 13.5% 20.4%;
+
+ --background: 205.7 13.5% 20.4%;
+ --foreground: 41 31.8% 74.7%;
+
+ --card: 205 13.3% 17.6%;
+ --card-foreground: 41 31.8% 74.7%;
+
+ --popover: 205 13.3% 17.6%;
+ --popover-foreground: 41 31.8% 74.7%;
+
+ --primary: 83.4 33.7% 62.7%;
+ --primary-foreground: 205.7 13.5% 20.4%;
+
+ --secondary: 198.8 11.6% 27.1%;
+ --secondary-foreground: 41 31.8% 74.7%;
+
+ --muted: 198.8 12.7% 24.7%;
+ --muted-foreground: 138.5 5.6% 54.7%;
+
+ --accent: 134.8 32.6% 63.3%;
+ --accent-foreground: 205.7 13.5% 20.4%;
+
+ --destructive: 358.8 67.5% 69.8%;
+ --destructive-foreground: 41 31.8% 74.7%;
+
+ --success: 134.8 32.6% 63.3%;
+ --success-foreground: 205.7 13.5% 20.4%;
+
+ --brand: 83.4 33.7% 62.7%;
+ --brand-foreground: 205.7 13.5% 20.4%;
+ --brand-muted: 198.8 12.7% 24.7%;
+
+ --warning: 39.8 56.1% 67.8%;
+ --warning-foreground: 205.7 13.5% 20.4%;
+
+ --border: 198.8 11.6% 27.1%;
+ --input: 198.8 11.6% 27.1%;
+ --ring: 83.4 33.7% 62.7%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 83.4 33.7% 62.7%;
+ --chart-secondary: 39.8 56.1% 67.8%;
+
+ /* Status colors */
+ --status-success: 134.8 32.6% 63.3%;
+ --status-warning: 39.8 56.1% 67.8%;
+ --status-in-progress: 83.4 33.7% 62.7%;
+
+ --sidebar-background: 205 13.3% 17.6%;
+ --sidebar-foreground: 138.5 5.6% 54.7%;
+ --sidebar-primary: 83.4 33.7% 62.7%;
+ --sidebar-primary-foreground: 205.7 13.5% 20.4%;
+ --sidebar-accent: 198.8 12.7% 24.7%;
+ --sidebar-accent-foreground: 41 31.8% 74.7%;
+ --sidebar-border: 198.8 11.6% 27.1%;
+ --sidebar-ring: 83.4 33.7% 62.7%;
+
+ /* Hover Effect */
+ --ctahover: 134.8 32.6% 63.3%;
+ }
+}
diff --git a/src/workspaces/themes/Gruvbox/client.ts b/src/workspaces/themes/Gruvbox/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/Gruvbox/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/Gruvbox/index.ts b/src/workspaces/themes/Gruvbox/index.ts
new file mode 100644
index 00000000..44b1a4eb
--- /dev/null
+++ b/src/workspaces/themes/Gruvbox/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'Gruvbox', name: 'Gruvbox', description: 'Retro warm tones with earthy browns and muted accents.' };
diff --git a/src/workspaces/themes/Gruvbox/prose.css b/src/workspaces/themes/Gruvbox/prose.css
new file mode 100644
index 00000000..943ef0e0
--- /dev/null
+++ b/src/workspaces/themes/Gruvbox/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="Gruvbox"] .file-viewer-md {
+ color: #ebdbb2;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md h1 {
+ border-bottom-color: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md h2 {
+ border-bottom-color: rgba(80, 73, 69, 0.3);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md a {
+ color: #83a598;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md a:hover {
+ color: #8ec07c;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md strong {
+ color: #ebdbb2;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md blockquote {
+ border-left-color: #83a598;
+ background: rgba(131, 165, 152, 0.06);
+ color: #a89984;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md li::marker {
+ color: #83a598;
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md hr {
+ background: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md th {
+ background: rgba(131, 165, 152, 0.08);
+ border-color: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md td {
+ border-color: rgba(80, 73, 69, 0.3);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(80, 73, 69, 0.1);
+}
+
+[data-color-theme="Gruvbox"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #83a598;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="Gruvbox"] .skill-md {
+ color: #ebdbb2;
+}
+
+[data-color-theme="Gruvbox"] .skill-md h1 {
+ border-bottom-color: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .skill-md h2 {
+ border-bottom-color: rgba(80, 73, 69, 0.3);
+}
+
+[data-color-theme="Gruvbox"] .skill-md a {
+ color: #83a598;
+}
+
+[data-color-theme="Gruvbox"] .skill-md a:hover {
+ color: #8ec07c;
+}
+
+[data-color-theme="Gruvbox"] .skill-md strong {
+ color: #ebdbb2;
+}
+
+[data-color-theme="Gruvbox"] .skill-md blockquote {
+ border-left-color: #83a598;
+ background: rgba(131, 165, 152, 0.06);
+ color: #a89984;
+}
+
+[data-color-theme="Gruvbox"] .skill-md li::marker {
+ color: #83a598;
+}
+
+[data-color-theme="Gruvbox"] .skill-md code {
+ background: rgba(131, 165, 152, 0.1);
+ color: #83a598;
+}
+
+[data-color-theme="Gruvbox"] .skill-md pre {
+ background: #1d2021;
+}
+
+[data-color-theme="Gruvbox"] .skill-md pre code {
+ color: #ebdbb2;
+}
+
+[data-color-theme="Gruvbox"] .skill-md hr {
+ background: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .skill-md th {
+ background: rgba(131, 165, 152, 0.08);
+ border-color: rgba(80, 73, 69, 0.4);
+}
+
+[data-color-theme="Gruvbox"] .skill-md td {
+ border-color: rgba(80, 73, 69, 0.3);
+}
+
+[data-color-theme="Gruvbox"] .skill-md tr:nth-child(even) {
+ background: rgba(80, 73, 69, 0.1);
+}
+
+[data-color-theme="Gruvbox"] .skill-md input[type="checkbox"] {
+ accent-color: #83a598;
+}
diff --git a/src/workspaces/themes/Gruvbox/variables.css b/src/workspaces/themes/Gruvbox/variables.css
new file mode 100644
index 00000000..c803901d
--- /dev/null
+++ b/src/workspaces/themes/Gruvbox/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="Gruvbox"] {
+ /* Brand colors */
+ --duck-yellow: #fabd2f;
+ --duck-orange: #fe8019;
+ --duck-teal: #83a598;
+ --duck-forest: #a89984;
+ --duck-dark: #ebdbb2;
+ --duck-beige: #3c3836;
+
+ /* Page background */
+ --pixel-grid-color: rgba(131, 165, 152, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(131, 165, 152, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(131, 165, 152, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(29, 32, 33, 0.92);
+ --card-grid-color: rgba(131, 165, 152, 0.04);
+
+ --cta: 157.1 15.9% 58%;
+ --cta-foreground: 0 0% 15.7%;
+
+ --naturegreen: 104.1 35.1% 62%;
+ --naturegreen-foreground: 0 0% 15.7%;
+
+ --background: 0 0% 15.7%;
+ --foreground: 43.2 58.8% 81%;
+
+ --card: 195 6.5% 12.2%;
+ --card-foreground: 43.2 58.8% 81%;
+
+ --popover: 195 6.5% 12.2%;
+ --popover-foreground: 43.2 58.8% 81%;
+
+ --primary: 157.1 15.9% 58%;
+ --primary-foreground: 0 0% 15.7%;
+
+ --secondary: 21.8 7.4% 29.2%;
+ --secondary-foreground: 43.2 58.8% 81%;
+
+ --muted: 20 5.3% 22.4%;
+ --muted-foreground: 35 17.1% 58.8%;
+
+ --accent: 104.1 35.1% 62%;
+ --accent-foreground: 0 0% 15.7%;
+
+ --destructive: 6.3 96.1% 59.4%;
+ --destructive-foreground: 43.2 58.8% 81%;
+
+ --success: 61.2 66.2% 44.1%;
+ --success-foreground: 0 0% 15.7%;
+
+ --brand: 157.1 15.9% 58%;
+ --brand-foreground: 0 0% 15.7%;
+ --brand-muted: 20 5.3% 22.4%;
+
+ --warning: 42 95.3% 58.2%;
+ --warning-foreground: 0 0% 15.7%;
+
+ --border: 21.8 7.4% 29.2%;
+ --input: 21.8 7.4% 29.2%;
+ --ring: 157.1 15.9% 58%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 157.1 15.9% 58%;
+ --chart-secondary: 42 95.3% 58.2%;
+
+ /* Status colors */
+ --status-success: 61.2 66.2% 44.1%;
+ --status-warning: 42 95.3% 58.2%;
+ --status-in-progress: 157.1 15.9% 58%;
+
+ --sidebar-background: 195 6.5% 12.2%;
+ --sidebar-foreground: 35 17.1% 58.8%;
+ --sidebar-primary: 157.1 15.9% 58%;
+ --sidebar-primary-foreground: 0 0% 15.7%;
+ --sidebar-accent: 20 5.3% 22.4%;
+ --sidebar-accent-foreground: 43.2 58.8% 81%;
+ --sidebar-border: 21.8 7.4% 29.2%;
+ --sidebar-ring: 157.1 15.9% 58%;
+
+ /* Hover Effect */
+ --ctahover: 104.1 35.1% 62%;
+ }
+}
diff --git a/src/workspaces/themes/Kanagawa/client.ts b/src/workspaces/themes/Kanagawa/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/Kanagawa/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/Kanagawa/index.ts b/src/workspaces/themes/Kanagawa/index.ts
new file mode 100644
index 00000000..cd729bda
--- /dev/null
+++ b/src/workspaces/themes/Kanagawa/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'Kanagawa', name: 'Kanagawa', description: 'Deep indigo waves and ink-wash inspired hues.' };
diff --git a/src/workspaces/themes/Kanagawa/prose.css b/src/workspaces/themes/Kanagawa/prose.css
new file mode 100644
index 00000000..8d347167
--- /dev/null
+++ b/src/workspaces/themes/Kanagawa/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="Kanagawa"] .file-viewer-md {
+ color: #dcd7ba;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md h1 {
+ border-bottom-color: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md h2 {
+ border-bottom-color: rgba(42, 42, 55, 0.3);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md a {
+ color: #7e9cd8;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md a:hover {
+ color: #7fb4ca;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md strong {
+ color: #dcd7ba;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md blockquote {
+ border-left-color: #7e9cd8;
+ background: rgba(126, 156, 216, 0.06);
+ color: #727169;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md li::marker {
+ color: #7e9cd8;
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md hr {
+ background: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md th {
+ background: rgba(126, 156, 216, 0.08);
+ border-color: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md td {
+ border-color: rgba(42, 42, 55, 0.3);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(42, 42, 55, 0.1);
+}
+
+[data-color-theme="Kanagawa"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #7e9cd8;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="Kanagawa"] .skill-md {
+ color: #dcd7ba;
+}
+
+[data-color-theme="Kanagawa"] .skill-md h1 {
+ border-bottom-color: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .skill-md h2 {
+ border-bottom-color: rgba(42, 42, 55, 0.3);
+}
+
+[data-color-theme="Kanagawa"] .skill-md a {
+ color: #7e9cd8;
+}
+
+[data-color-theme="Kanagawa"] .skill-md a:hover {
+ color: #7fb4ca;
+}
+
+[data-color-theme="Kanagawa"] .skill-md strong {
+ color: #dcd7ba;
+}
+
+[data-color-theme="Kanagawa"] .skill-md blockquote {
+ border-left-color: #7e9cd8;
+ background: rgba(126, 156, 216, 0.06);
+ color: #727169;
+}
+
+[data-color-theme="Kanagawa"] .skill-md li::marker {
+ color: #7e9cd8;
+}
+
+[data-color-theme="Kanagawa"] .skill-md code {
+ background: rgba(126, 156, 216, 0.1);
+ color: #7e9cd8;
+}
+
+[data-color-theme="Kanagawa"] .skill-md pre {
+ background: #16161d;
+}
+
+[data-color-theme="Kanagawa"] .skill-md pre code {
+ color: #dcd7ba;
+}
+
+[data-color-theme="Kanagawa"] .skill-md hr {
+ background: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .skill-md th {
+ background: rgba(126, 156, 216, 0.08);
+ border-color: rgba(42, 42, 55, 0.4);
+}
+
+[data-color-theme="Kanagawa"] .skill-md td {
+ border-color: rgba(42, 42, 55, 0.3);
+}
+
+[data-color-theme="Kanagawa"] .skill-md tr:nth-child(even) {
+ background: rgba(42, 42, 55, 0.1);
+}
+
+[data-color-theme="Kanagawa"] .skill-md input[type="checkbox"] {
+ accent-color: #7e9cd8;
+}
diff --git a/src/workspaces/themes/Kanagawa/variables.css b/src/workspaces/themes/Kanagawa/variables.css
new file mode 100644
index 00000000..3737ca1a
--- /dev/null
+++ b/src/workspaces/themes/Kanagawa/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="Kanagawa"] {
+ /* Brand colors */
+ --duck-yellow: #ffa066;
+ --duck-orange: #ff5d62;
+ --duck-teal: #7e9cd8;
+ --duck-forest: #727169;
+ --duck-dark: #dcd7ba;
+ --duck-beige: #223249;
+
+ /* Page background */
+ --pixel-grid-color: rgba(126, 156, 216, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(126, 156, 216, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(126, 156, 216, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(22, 22, 29, 0.92);
+ --card-grid-color: rgba(126, 156, 216, 0.04);
+
+ --cta: 220 53.6% 67.1%;
+ --cta-foreground: 240 12.7% 13.9%;
+
+ --naturegreen: 197.6 41.4% 64.5%;
+ --naturegreen-foreground: 240 12.7% 13.9%;
+
+ --background: 240 12.7% 13.9%;
+ --foreground: 51.2 32.7% 79.6%;
+
+ --card: 240 13.7% 10%;
+ --card-foreground: 51.2 32.7% 79.6%;
+
+ --popover: 240 13.7% 10%;
+ --popover-foreground: 51.2 32.7% 79.6%;
+
+ --primary: 220 53.6% 67.1%;
+ --primary-foreground: 240 12.7% 13.9%;
+
+ --secondary: 240 13.4% 19%;
+ --secondary-foreground: 51.2 32.7% 79.6%;
+
+ --muted: 215.4 36.4% 21%;
+ --muted-foreground: 53.3 4.1% 42.9%;
+
+ --accent: 197.6 41.4% 64.5%;
+ --accent-foreground: 240 12.7% 13.9%;
+
+ --destructive: 0 81% 52.5%;
+ --destructive-foreground: 51.2 32.7% 79.6%;
+
+ --success: 86.6 36.7% 57.8%;
+ --success-foreground: 240 12.7% 13.9%;
+
+ --brand: 220 53.6% 67.1%;
+ --brand-foreground: 240 12.7% 13.9%;
+ --brand-muted: 215.4 36.4% 21%;
+
+ --warning: 22.7 100% 70%;
+ --warning-foreground: 240 12.7% 13.9%;
+
+ --border: 240 13.4% 19%;
+ --input: 240 13.4% 19%;
+ --ring: 220 53.6% 67.1%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 220 53.6% 67.1%;
+ --chart-secondary: 22.7 100% 70%;
+
+ /* Status colors */
+ --status-success: 86.6 36.7% 57.8%;
+ --status-warning: 22.7 100% 70%;
+ --status-in-progress: 220 53.6% 67.1%;
+
+ --sidebar-background: 240 13.7% 10%;
+ --sidebar-foreground: 53.3 4.1% 42.9%;
+ --sidebar-primary: 220 53.6% 67.1%;
+ --sidebar-primary-foreground: 240 12.7% 13.9%;
+ --sidebar-accent: 215.4 36.4% 21%;
+ --sidebar-accent-foreground: 51.2 32.7% 79.6%;
+ --sidebar-border: 240 13.4% 19%;
+ --sidebar-ring: 220 53.6% 67.1%;
+
+ /* Hover Effect */
+ --ctahover: 197.6 41.4% 64.5%;
+ }
+}
diff --git a/src/workspaces/themes/MatteBlack/client.ts b/src/workspaces/themes/MatteBlack/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/MatteBlack/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/MatteBlack/index.ts b/src/workspaces/themes/MatteBlack/index.ts
new file mode 100644
index 00000000..9e06c02e
--- /dev/null
+++ b/src/workspaces/themes/MatteBlack/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'MatteBlack', name: 'Matte Black', description: 'Pure minimal monochrome with a matte finish.' };
diff --git a/src/workspaces/themes/MatteBlack/prose.css b/src/workspaces/themes/MatteBlack/prose.css
new file mode 100644
index 00000000..a3135306
--- /dev/null
+++ b/src/workspaces/themes/MatteBlack/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="MatteBlack"] .file-viewer-md {
+ color: #e0e0e0;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md h1 {
+ border-bottom-color: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md h2 {
+ border-bottom-color: rgba(42, 42, 42, 0.3);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md a {
+ color: #ffffff;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md a:hover {
+ color: #d0d0d0;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md strong {
+ color: #e0e0e0;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md blockquote {
+ border-left-color: #ffffff;
+ background: rgba(255, 255, 255, 0.06);
+ color: #9a9a9a;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md li::marker {
+ color: #ffffff;
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md hr {
+ background: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md th {
+ background: rgba(255, 255, 255, 0.08);
+ border-color: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md td {
+ border-color: rgba(42, 42, 42, 0.3);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(42, 42, 42, 0.1);
+}
+
+[data-color-theme="MatteBlack"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #ffffff;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="MatteBlack"] .skill-md {
+ color: #e0e0e0;
+}
+
+[data-color-theme="MatteBlack"] .skill-md h1 {
+ border-bottom-color: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .skill-md h2 {
+ border-bottom-color: rgba(42, 42, 42, 0.3);
+}
+
+[data-color-theme="MatteBlack"] .skill-md a {
+ color: #ffffff;
+}
+
+[data-color-theme="MatteBlack"] .skill-md a:hover {
+ color: #d0d0d0;
+}
+
+[data-color-theme="MatteBlack"] .skill-md strong {
+ color: #e0e0e0;
+}
+
+[data-color-theme="MatteBlack"] .skill-md blockquote {
+ border-left-color: #ffffff;
+ background: rgba(255, 255, 255, 0.06);
+ color: #9a9a9a;
+}
+
+[data-color-theme="MatteBlack"] .skill-md li::marker {
+ color: #ffffff;
+}
+
+[data-color-theme="MatteBlack"] .skill-md code {
+ background: rgba(255, 255, 255, 0.1);
+ color: #ffffff;
+}
+
+[data-color-theme="MatteBlack"] .skill-md pre {
+ background: #121212;
+}
+
+[data-color-theme="MatteBlack"] .skill-md pre code {
+ color: #e0e0e0;
+}
+
+[data-color-theme="MatteBlack"] .skill-md hr {
+ background: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .skill-md th {
+ background: rgba(255, 255, 255, 0.08);
+ border-color: rgba(42, 42, 42, 0.4);
+}
+
+[data-color-theme="MatteBlack"] .skill-md td {
+ border-color: rgba(42, 42, 42, 0.3);
+}
+
+[data-color-theme="MatteBlack"] .skill-md tr:nth-child(even) {
+ background: rgba(42, 42, 42, 0.1);
+}
+
+[data-color-theme="MatteBlack"] .skill-md input[type="checkbox"] {
+ accent-color: #ffffff;
+}
diff --git a/src/workspaces/themes/MatteBlack/variables.css b/src/workspaces/themes/MatteBlack/variables.css
new file mode 100644
index 00000000..06e532b4
--- /dev/null
+++ b/src/workspaces/themes/MatteBlack/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="MatteBlack"] {
+ /* Brand colors */
+ --duck-yellow: #e0e0e0;
+ --duck-orange: #cccccc;
+ --duck-teal: #ffffff;
+ --duck-forest: #9a9a9a;
+ --duck-dark: #e0e0e0;
+ --duck-beige: #1a1a1a;
+
+ /* Page background */
+ --pixel-grid-color: rgba(255, 255, 255, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(255, 255, 255, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(255, 255, 255, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(18, 18, 18, 0.92);
+ --card-grid-color: rgba(255, 255, 255, 0.04);
+
+ --cta: 0 0% 100%;
+ --cta-foreground: 0 0% 3.9%;
+
+ --naturegreen: 0 0% 81.6%;
+ --naturegreen-foreground: 0 0% 3.9%;
+
+ --background: 0 0% 3.9%;
+ --foreground: 0 0% 87.8%;
+
+ --card: 0 0% 7.1%;
+ --card-foreground: 0 0% 87.8%;
+
+ --popover: 0 0% 7.1%;
+ --popover-foreground: 0 0% 87.8%;
+
+ --primary: 0 0% 100%;
+ --primary-foreground: 0 0% 3.9%;
+
+ --secondary: 0 0% 16.5%;
+ --secondary-foreground: 0 0% 87.8%;
+
+ --muted: 0 0% 10.2%;
+ --muted-foreground: 0 0% 60.4%;
+
+ --accent: 0 0% 81.6%;
+ --accent-foreground: 0 0% 3.9%;
+
+ --destructive: 0 100% 63.3%;
+ --destructive-foreground: 0 0% 87.8%;
+
+ --success: 0 0% 60%;
+ --success-foreground: 0 0% 3.9%;
+
+ --brand: 0 0% 100%;
+ --brand-foreground: 0 0% 3.9%;
+ --brand-muted: 0 0% 10.2%;
+
+ --warning: 0 0% 80%;
+ --warning-foreground: 0 0% 3.9%;
+
+ --border: 0 0% 16.5%;
+ --input: 0 0% 16.5%;
+ --ring: 0 0% 100%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 0 0% 100%;
+ --chart-secondary: 0 0% 80%;
+
+ /* Status colors */
+ --status-success: 0 0% 60%;
+ --status-warning: 0 0% 80%;
+ --status-in-progress: 0 0% 100%;
+
+ --sidebar-background: 0 0% 7.1%;
+ --sidebar-foreground: 0 0% 60.4%;
+ --sidebar-primary: 0 0% 100%;
+ --sidebar-primary-foreground: 0 0% 3.9%;
+ --sidebar-accent: 0 0% 10.2%;
+ --sidebar-accent-foreground: 0 0% 87.8%;
+ --sidebar-border: 0 0% 16.5%;
+ --sidebar-ring: 0 0% 100%;
+
+ /* Hover Effect */
+ --ctahover: 0 0% 81.6%;
+ }
+}
diff --git a/src/workspaces/themes/Nord/client.ts b/src/workspaces/themes/Nord/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/Nord/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/Nord/index.ts b/src/workspaces/themes/Nord/index.ts
new file mode 100644
index 00000000..e85dc88b
--- /dev/null
+++ b/src/workspaces/themes/Nord/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'Nord', name: 'Nord', description: 'Cool arctic blues and frosty Nordic tones.' };
diff --git a/src/workspaces/themes/Nord/prose.css b/src/workspaces/themes/Nord/prose.css
new file mode 100644
index 00000000..f901fc71
--- /dev/null
+++ b/src/workspaces/themes/Nord/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="Nord"] .file-viewer-md {
+ color: #eceff4;
+}
+
+[data-color-theme="Nord"] .file-viewer-md h1 {
+ border-bottom-color: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .file-viewer-md h2 {
+ border-bottom-color: rgba(67, 76, 94, 0.3);
+}
+
+[data-color-theme="Nord"] .file-viewer-md a {
+ color: #88c0d0;
+}
+
+[data-color-theme="Nord"] .file-viewer-md a:hover {
+ color: #8fbcbb;
+}
+
+[data-color-theme="Nord"] .file-viewer-md strong {
+ color: #eceff4;
+}
+
+[data-color-theme="Nord"] .file-viewer-md blockquote {
+ border-left-color: #88c0d0;
+ background: rgba(136, 192, 208, 0.06);
+ color: #d8dee9;
+}
+
+[data-color-theme="Nord"] .file-viewer-md li::marker {
+ color: #88c0d0;
+}
+
+[data-color-theme="Nord"] .file-viewer-md hr {
+ background: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .file-viewer-md th {
+ background: rgba(136, 192, 208, 0.08);
+ border-color: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .file-viewer-md td {
+ border-color: rgba(67, 76, 94, 0.3);
+}
+
+[data-color-theme="Nord"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(67, 76, 94, 0.1);
+}
+
+[data-color-theme="Nord"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #88c0d0;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="Nord"] .skill-md {
+ color: #eceff4;
+}
+
+[data-color-theme="Nord"] .skill-md h1 {
+ border-bottom-color: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .skill-md h2 {
+ border-bottom-color: rgba(67, 76, 94, 0.3);
+}
+
+[data-color-theme="Nord"] .skill-md a {
+ color: #88c0d0;
+}
+
+[data-color-theme="Nord"] .skill-md a:hover {
+ color: #8fbcbb;
+}
+
+[data-color-theme="Nord"] .skill-md strong {
+ color: #eceff4;
+}
+
+[data-color-theme="Nord"] .skill-md blockquote {
+ border-left-color: #88c0d0;
+ background: rgba(136, 192, 208, 0.06);
+ color: #d8dee9;
+}
+
+[data-color-theme="Nord"] .skill-md li::marker {
+ color: #88c0d0;
+}
+
+[data-color-theme="Nord"] .skill-md code {
+ background: rgba(136, 192, 208, 0.1);
+ color: #88c0d0;
+}
+
+[data-color-theme="Nord"] .skill-md pre {
+ background: #3b4252;
+}
+
+[data-color-theme="Nord"] .skill-md pre code {
+ color: #eceff4;
+}
+
+[data-color-theme="Nord"] .skill-md hr {
+ background: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .skill-md th {
+ background: rgba(136, 192, 208, 0.08);
+ border-color: rgba(67, 76, 94, 0.4);
+}
+
+[data-color-theme="Nord"] .skill-md td {
+ border-color: rgba(67, 76, 94, 0.3);
+}
+
+[data-color-theme="Nord"] .skill-md tr:nth-child(even) {
+ background: rgba(67, 76, 94, 0.1);
+}
+
+[data-color-theme="Nord"] .skill-md input[type="checkbox"] {
+ accent-color: #88c0d0;
+}
diff --git a/src/workspaces/themes/Nord/variables.css b/src/workspaces/themes/Nord/variables.css
new file mode 100644
index 00000000..430ec2a2
--- /dev/null
+++ b/src/workspaces/themes/Nord/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="Nord"] {
+ /* Brand colors */
+ --duck-yellow: #ebcb8b;
+ --duck-orange: #d08770;
+ --duck-teal: #88c0d0;
+ --duck-forest: #d8dee9;
+ --duck-dark: #eceff4;
+ --duck-beige: #3b4252;
+
+ /* Page background */
+ --pixel-grid-color: rgba(136, 192, 208, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(136, 192, 208, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(136, 192, 208, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(59, 66, 82, 0.92);
+ --card-grid-color: rgba(136, 192, 208, 0.04);
+
+ --cta: 193.3 43.4% 67.5%;
+ --cta-foreground: 220 16.4% 21.6%;
+
+ --naturegreen: 178.7 25.1% 64.9%;
+ --naturegreen-foreground: 220 16.4% 21.6%;
+
+ --background: 220 16.4% 21.6%;
+ --foreground: 217.5 26.7% 94.1%;
+
+ --card: 221.7 16.3% 27.6%;
+ --card-foreground: 217.5 26.7% 94.1%;
+
+ --popover: 221.7 16.3% 27.6%;
+ --popover-foreground: 217.5 26.7% 94.1%;
+
+ --primary: 193.3 43.4% 67.5%;
+ --primary-foreground: 220 16.4% 21.6%;
+
+ --secondary: 220 16.8% 31.6%;
+ --secondary-foreground: 217.5 26.7% 94.1%;
+
+ --muted: 221.7 16.3% 27.6%;
+ --muted-foreground: 218.8 27.9% 88%;
+
+ --accent: 178.7 25.1% 64.9%;
+ --accent-foreground: 220 16.4% 21.6%;
+
+ --destructive: 354.3 42.3% 56.5%;
+ --destructive-foreground: 217.5 26.7% 94.1%;
+
+ --success: 92.4 27.8% 64.7%;
+ --success-foreground: 220 16.4% 21.6%;
+
+ --brand: 193.3 43.4% 67.5%;
+ --brand-foreground: 220 16.4% 21.6%;
+ --brand-muted: 221.7 16.3% 27.6%;
+
+ --warning: 40 70.6% 73.3%;
+ --warning-foreground: 220 16.4% 21.6%;
+
+ --border: 220 16.8% 31.6%;
+ --input: 220 16.8% 31.6%;
+ --ring: 193.3 43.4% 67.5%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 193.3 43.4% 67.5%;
+ --chart-secondary: 40 70.6% 73.3%;
+
+ /* Status colors */
+ --status-success: 92.4 27.8% 64.7%;
+ --status-warning: 40 70.6% 73.3%;
+ --status-in-progress: 193.3 43.4% 67.5%;
+
+ --sidebar-background: 221.7 16.3% 27.6%;
+ --sidebar-foreground: 218.8 27.9% 88%;
+ --sidebar-primary: 193.3 43.4% 67.5%;
+ --sidebar-primary-foreground: 220 16.4% 21.6%;
+ --sidebar-accent: 220 16.8% 31.6%;
+ --sidebar-accent-foreground: 217.5 26.7% 94.1%;
+ --sidebar-border: 220 16.5% 35.7%;
+ --sidebar-ring: 193.3 43.4% 67.5%;
+
+ /* Hover Effect */
+ --ctahover: 178.7 25.1% 64.9%;
+ }
+}
diff --git a/src/workspaces/themes/OsakaJade/client.ts b/src/workspaces/themes/OsakaJade/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/OsakaJade/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/OsakaJade/index.ts b/src/workspaces/themes/OsakaJade/index.ts
new file mode 100644
index 00000000..bff47123
--- /dev/null
+++ b/src/workspaces/themes/OsakaJade/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'OsakaJade', name: 'Osaka Jade', description: 'Electric jade and neon cyan on a midnight canvas.' };
diff --git a/src/workspaces/themes/OsakaJade/prose.css b/src/workspaces/themes/OsakaJade/prose.css
new file mode 100644
index 00000000..3c66d7a2
--- /dev/null
+++ b/src/workspaces/themes/OsakaJade/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="OsakaJade"] .file-viewer-md {
+ color: #c5cdd9;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md h1 {
+ border-bottom-color: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md h2 {
+ border-bottom-color: rgba(41, 46, 66, 0.3);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md a {
+ color: #2ac3de;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md a:hover {
+ color: #0db9d7;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md strong {
+ color: #c5cdd9;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md blockquote {
+ border-left-color: #2ac3de;
+ background: rgba(42, 195, 222, 0.06);
+ color: #565f89;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md li::marker {
+ color: #2ac3de;
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md hr {
+ background: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md th {
+ background: rgba(42, 195, 222, 0.08);
+ border-color: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md td {
+ border-color: rgba(41, 46, 66, 0.3);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(41, 46, 66, 0.1);
+}
+
+[data-color-theme="OsakaJade"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #2ac3de;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="OsakaJade"] .skill-md {
+ color: #c5cdd9;
+}
+
+[data-color-theme="OsakaJade"] .skill-md h1 {
+ border-bottom-color: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .skill-md h2 {
+ border-bottom-color: rgba(41, 46, 66, 0.3);
+}
+
+[data-color-theme="OsakaJade"] .skill-md a {
+ color: #2ac3de;
+}
+
+[data-color-theme="OsakaJade"] .skill-md a:hover {
+ color: #0db9d7;
+}
+
+[data-color-theme="OsakaJade"] .skill-md strong {
+ color: #c5cdd9;
+}
+
+[data-color-theme="OsakaJade"] .skill-md blockquote {
+ border-left-color: #2ac3de;
+ background: rgba(42, 195, 222, 0.06);
+ color: #565f89;
+}
+
+[data-color-theme="OsakaJade"] .skill-md li::marker {
+ color: #2ac3de;
+}
+
+[data-color-theme="OsakaJade"] .skill-md code {
+ background: rgba(42, 195, 222, 0.1);
+ color: #2ac3de;
+}
+
+[data-color-theme="OsakaJade"] .skill-md pre {
+ background: #16161e;
+}
+
+[data-color-theme="OsakaJade"] .skill-md pre code {
+ color: #c5cdd9;
+}
+
+[data-color-theme="OsakaJade"] .skill-md hr {
+ background: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .skill-md th {
+ background: rgba(42, 195, 222, 0.08);
+ border-color: rgba(41, 46, 66, 0.4);
+}
+
+[data-color-theme="OsakaJade"] .skill-md td {
+ border-color: rgba(41, 46, 66, 0.3);
+}
+
+[data-color-theme="OsakaJade"] .skill-md tr:nth-child(even) {
+ background: rgba(41, 46, 66, 0.1);
+}
+
+[data-color-theme="OsakaJade"] .skill-md input[type="checkbox"] {
+ accent-color: #2ac3de;
+}
diff --git a/src/workspaces/themes/OsakaJade/variables.css b/src/workspaces/themes/OsakaJade/variables.css
new file mode 100644
index 00000000..3e327911
--- /dev/null
+++ b/src/workspaces/themes/OsakaJade/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="OsakaJade"] {
+ /* Brand colors */
+ --duck-yellow: #e0af68;
+ --duck-orange: #f7768e;
+ --duck-teal: #2ac3de;
+ --duck-forest: #565f89;
+ --duck-dark: #c5cdd9;
+ --duck-beige: #1f2335;
+
+ /* Page background */
+ --pixel-grid-color: rgba(42, 195, 222, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(42, 195, 222, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(42, 195, 222, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(22, 22, 30, 0.92);
+ --card-grid-color: rgba(42, 195, 222, 0.04);
+
+ --cta: 189 73.2% 51.8%;
+ --cta-foreground: 235 18.8% 12.5%;
+
+ --naturegreen: 188.9 88.6% 44.7%;
+ --naturegreen-foreground: 235 18.8% 12.5%;
+
+ --background: 235 18.8% 12.5%;
+ --foreground: 216 20.8% 81.2%;
+
+ --card: 240 15.4% 10.2%;
+ --card-foreground: 216 20.8% 81.2%;
+
+ --popover: 240 15.4% 10.2%;
+ --popover-foreground: 216 20.8% 81.2%;
+
+ --primary: 189 73.2% 51.8%;
+ --primary-foreground: 235 18.8% 12.5%;
+
+ --secondary: 228 23.4% 21%;
+ --secondary-foreground: 216 20.8% 81.2%;
+
+ --muted: 229.1 26.2% 16.5%;
+ --muted-foreground: 229.4 22.9% 43.7%;
+
+ --accent: 188.9 88.6% 44.7%;
+ --accent-foreground: 235 18.8% 12.5%;
+
+ --destructive: 348.8 89% 71.6%;
+ --destructive-foreground: 216 20.8% 81.2%;
+
+ --success: 88.8 50.5% 61.2%;
+ --success-foreground: 235 18.8% 12.5%;
+
+ --brand: 189 73.2% 51.8%;
+ --brand-foreground: 235 18.8% 12.5%;
+ --brand-muted: 229.1 26.2% 16.5%;
+
+ --warning: 35.5 65.9% 64.3%;
+ --warning-foreground: 235 18.8% 12.5%;
+
+ --border: 228 23.4% 21%;
+ --input: 228 23.4% 21%;
+ --ring: 189 73.2% 51.8%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 189 73.2% 51.8%;
+ --chart-secondary: 35.5 65.9% 64.3%;
+
+ /* Status colors */
+ --status-success: 88.8 50.5% 61.2%;
+ --status-warning: 35.5 65.9% 64.3%;
+ --status-in-progress: 189 73.2% 51.8%;
+
+ --sidebar-background: 240 15.4% 10.2%;
+ --sidebar-foreground: 229.4 22.9% 43.7%;
+ --sidebar-primary: 189 73.2% 51.8%;
+ --sidebar-primary-foreground: 235 18.8% 12.5%;
+ --sidebar-accent: 229.1 26.2% 16.5%;
+ --sidebar-accent-foreground: 216 20.8% 81.2%;
+ --sidebar-border: 228 23.4% 21%;
+ --sidebar-ring: 189 73.2% 51.8%;
+
+ /* Hover Effect */
+ --ctahover: 188.9 88.6% 44.7%;
+ }
+}
diff --git a/src/workspaces/themes/Ristretto/client.ts b/src/workspaces/themes/Ristretto/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/Ristretto/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/Ristretto/index.ts b/src/workspaces/themes/Ristretto/index.ts
new file mode 100644
index 00000000..396948c7
--- /dev/null
+++ b/src/workspaces/themes/Ristretto/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'Ristretto', name: 'Ristretto', description: 'Warm coffee tones with amber and burnt orange.' };
diff --git a/src/workspaces/themes/Ristretto/prose.css b/src/workspaces/themes/Ristretto/prose.css
new file mode 100644
index 00000000..1c572188
--- /dev/null
+++ b/src/workspaces/themes/Ristretto/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="Ristretto"] .file-viewer-md {
+ color: #ebe5df;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md h1 {
+ border-bottom-color: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md h2 {
+ border-bottom-color: rgba(95, 87, 79, 0.3);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md a {
+ color: #fc9867;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md a:hover {
+ color: #fbb360;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md strong {
+ color: #ebe5df;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md blockquote {
+ border-left-color: #fc9867;
+ background: rgba(252, 152, 103, 0.06);
+ color: #ada49d;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md li::marker {
+ color: #fc9867;
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md hr {
+ background: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md th {
+ background: rgba(252, 152, 103, 0.08);
+ border-color: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md td {
+ border-color: rgba(95, 87, 79, 0.3);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(95, 87, 79, 0.1);
+}
+
+[data-color-theme="Ristretto"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #fc9867;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="Ristretto"] .skill-md {
+ color: #ebe5df;
+}
+
+[data-color-theme="Ristretto"] .skill-md h1 {
+ border-bottom-color: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .skill-md h2 {
+ border-bottom-color: rgba(95, 87, 79, 0.3);
+}
+
+[data-color-theme="Ristretto"] .skill-md a {
+ color: #fc9867;
+}
+
+[data-color-theme="Ristretto"] .skill-md a:hover {
+ color: #fbb360;
+}
+
+[data-color-theme="Ristretto"] .skill-md strong {
+ color: #ebe5df;
+}
+
+[data-color-theme="Ristretto"] .skill-md blockquote {
+ border-left-color: #fc9867;
+ background: rgba(252, 152, 103, 0.06);
+ color: #ada49d;
+}
+
+[data-color-theme="Ristretto"] .skill-md li::marker {
+ color: #fc9867;
+}
+
+[data-color-theme="Ristretto"] .skill-md code {
+ background: rgba(252, 152, 103, 0.1);
+ color: #fc9867;
+}
+
+[data-color-theme="Ristretto"] .skill-md pre {
+ background: #352f2a;
+}
+
+[data-color-theme="Ristretto"] .skill-md pre code {
+ color: #ebe5df;
+}
+
+[data-color-theme="Ristretto"] .skill-md hr {
+ background: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .skill-md th {
+ background: rgba(252, 152, 103, 0.08);
+ border-color: rgba(95, 87, 79, 0.4);
+}
+
+[data-color-theme="Ristretto"] .skill-md td {
+ border-color: rgba(95, 87, 79, 0.3);
+}
+
+[data-color-theme="Ristretto"] .skill-md tr:nth-child(even) {
+ background: rgba(95, 87, 79, 0.1);
+}
+
+[data-color-theme="Ristretto"] .skill-md input[type="checkbox"] {
+ accent-color: #fc9867;
+}
diff --git a/src/workspaces/themes/Ristretto/variables.css b/src/workspaces/themes/Ristretto/variables.css
new file mode 100644
index 00000000..1e01f9de
--- /dev/null
+++ b/src/workspaces/themes/Ristretto/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="Ristretto"] {
+ /* Brand colors */
+ --duck-yellow: #fbb360;
+ --duck-orange: #fc9867;
+ --duck-teal: #fc9867;
+ --duck-forest: #ada49d;
+ --duck-dark: #ebe5df;
+ --duck-beige: #4d4743;
+
+ /* Page background */
+ --pixel-grid-color: rgba(252, 152, 103, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(252, 152, 103, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(252, 152, 103, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(53, 47, 42, 0.92);
+ --card-grid-color: rgba(252, 152, 103, 0.04);
+
+ --cta: 19.7 96.1% 69.6%;
+ --cta-foreground: 34.3 5.8% 23.7%;
+
+ --naturegreen: 32.1 95.1% 68%;
+ --naturegreen-foreground: 34.3 5.8% 23.7%;
+
+ --background: 34.3 5.8% 23.7%;
+ --foreground: 30 23.1% 89.8%;
+
+ --card: 27.3 11.6% 18.6%;
+ --card-foreground: 30 23.1% 89.8%;
+
+ --popover: 27.3 11.6% 18.6%;
+ --popover-foreground: 30 23.1% 89.8%;
+
+ --primary: 19.7 96.1% 69.6%;
+ --primary-foreground: 34.3 5.8% 23.7%;
+
+ --secondary: 30 9.2% 34.1%;
+ --secondary-foreground: 30 23.1% 89.8%;
+
+ --muted: 24 6.9% 28.2%;
+ --muted-foreground: 26.3 8.9% 64.7%;
+
+ --accent: 32.1 95.1% 68%;
+ --accent-foreground: 34.3 5.8% 23.7%;
+
+ --destructive: 0 57.2% 63.3%;
+ --destructive-foreground: 30 23.1% 89.8%;
+
+ --success: 113.6 13.5% 59.2%;
+ --success-foreground: 34.3 5.8% 23.7%;
+
+ --brand: 19.7 96.1% 69.6%;
+ --brand-foreground: 34.3 5.8% 23.7%;
+ --brand-muted: 24 6.9% 28.2%;
+
+ --warning: 32.1 95.1% 68%;
+ --warning-foreground: 34.3 5.8% 23.7%;
+
+ --border: 30 9.2% 34.1%;
+ --input: 30 9.2% 34.1%;
+ --ring: 19.7 96.1% 69.6%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 19.7 96.1% 69.6%;
+ --chart-secondary: 32.1 95.1% 68%;
+
+ /* Status colors */
+ --status-success: 113.6 13.5% 59.2%;
+ --status-warning: 32.1 95.1% 68%;
+ --status-in-progress: 19.7 96.1% 69.6%;
+
+ --sidebar-background: 27.3 11.6% 18.6%;
+ --sidebar-foreground: 26.3 8.9% 64.7%;
+ --sidebar-primary: 19.7 96.1% 69.6%;
+ --sidebar-primary-foreground: 34.3 5.8% 23.7%;
+ --sidebar-accent: 24 6.9% 28.2%;
+ --sidebar-accent-foreground: 30 23.1% 89.8%;
+ --sidebar-border: 30 9.2% 34.1%;
+ --sidebar-ring: 19.7 96.1% 69.6%;
+
+ /* Hover Effect */
+ --ctahover: 32.1 95.1% 68%;
+ }
+}
diff --git a/src/workspaces/themes/RosePine/client.ts b/src/workspaces/themes/RosePine/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/RosePine/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/RosePine/index.ts b/src/workspaces/themes/RosePine/index.ts
new file mode 100644
index 00000000..b9c129e4
--- /dev/null
+++ b/src/workspaces/themes/RosePine/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'RosePine', name: 'Rose Pine', description: 'Romantic purples and dusty rose on a moonlit base.' };
diff --git a/src/workspaces/themes/RosePine/prose.css b/src/workspaces/themes/RosePine/prose.css
new file mode 100644
index 00000000..d64a14ce
--- /dev/null
+++ b/src/workspaces/themes/RosePine/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="RosePine"] .file-viewer-md {
+ color: #e0def4;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md h1 {
+ border-bottom-color: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md h2 {
+ border-bottom-color: rgba(38, 35, 58, 0.3);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md a {
+ color: #c4a7e7;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md a:hover {
+ color: #ebbcba;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md strong {
+ color: #e0def4;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md blockquote {
+ border-left-color: #c4a7e7;
+ background: rgba(196, 167, 231, 0.06);
+ color: #908caa;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md li::marker {
+ color: #c4a7e7;
+}
+
+[data-color-theme="RosePine"] .file-viewer-md hr {
+ background: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md th {
+ background: rgba(196, 167, 231, 0.08);
+ border-color: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md td {
+ border-color: rgba(38, 35, 58, 0.3);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(38, 35, 58, 0.1);
+}
+
+[data-color-theme="RosePine"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #c4a7e7;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="RosePine"] .skill-md {
+ color: #e0def4;
+}
+
+[data-color-theme="RosePine"] .skill-md h1 {
+ border-bottom-color: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .skill-md h2 {
+ border-bottom-color: rgba(38, 35, 58, 0.3);
+}
+
+[data-color-theme="RosePine"] .skill-md a {
+ color: #c4a7e7;
+}
+
+[data-color-theme="RosePine"] .skill-md a:hover {
+ color: #ebbcba;
+}
+
+[data-color-theme="RosePine"] .skill-md strong {
+ color: #e0def4;
+}
+
+[data-color-theme="RosePine"] .skill-md blockquote {
+ border-left-color: #c4a7e7;
+ background: rgba(196, 167, 231, 0.06);
+ color: #908caa;
+}
+
+[data-color-theme="RosePine"] .skill-md li::marker {
+ color: #c4a7e7;
+}
+
+[data-color-theme="RosePine"] .skill-md code {
+ background: rgba(196, 167, 231, 0.1);
+ color: #c4a7e7;
+}
+
+[data-color-theme="RosePine"] .skill-md pre {
+ background: #1f1d2e;
+}
+
+[data-color-theme="RosePine"] .skill-md pre code {
+ color: #e0def4;
+}
+
+[data-color-theme="RosePine"] .skill-md hr {
+ background: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .skill-md th {
+ background: rgba(196, 167, 231, 0.08);
+ border-color: rgba(38, 35, 58, 0.4);
+}
+
+[data-color-theme="RosePine"] .skill-md td {
+ border-color: rgba(38, 35, 58, 0.3);
+}
+
+[data-color-theme="RosePine"] .skill-md tr:nth-child(even) {
+ background: rgba(38, 35, 58, 0.1);
+}
+
+[data-color-theme="RosePine"] .skill-md input[type="checkbox"] {
+ accent-color: #c4a7e7;
+}
diff --git a/src/workspaces/themes/RosePine/variables.css b/src/workspaces/themes/RosePine/variables.css
new file mode 100644
index 00000000..1bd30dd6
--- /dev/null
+++ b/src/workspaces/themes/RosePine/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="RosePine"] {
+ /* Brand colors */
+ --duck-yellow: #f6c177;
+ --duck-orange: #eb6f92;
+ --duck-teal: #c4a7e7;
+ --duck-forest: #908caa;
+ --duck-dark: #e0def4;
+ --duck-beige: #26233a;
+
+ /* Page background */
+ --pixel-grid-color: rgba(196, 167, 231, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(196, 167, 231, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(196, 167, 231, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(31, 29, 46, 0.92);
+ --card-grid-color: rgba(196, 167, 231, 0.04);
+
+ --cta: 267.2 57.1% 78%;
+ --cta-foreground: 249.2 22% 11.6%;
+
+ --naturegreen: 2.4 55.1% 82.5%;
+ --naturegreen-foreground: 249.2 22% 11.6%;
+
+ --background: 249.2 22% 11.6%;
+ --foreground: 245.5 50% 91.4%;
+
+ --card: 247.1 22.7% 14.7%;
+ --card-foreground: 245.5 50% 91.4%;
+
+ --popover: 247.1 22.7% 14.7%;
+ --popover-foreground: 245.5 50% 91.4%;
+
+ --primary: 267.2 57.1% 78%;
+ --primary-foreground: 249.2 22% 11.6%;
+
+ --secondary: 247.8 24.7% 18.2%;
+ --secondary-foreground: 245.5 50% 91.4%;
+
+ --muted: 247.8 24.7% 18.2%;
+ --muted-foreground: 248 15% 60.8%;
+
+ --accent: 2.4 55.1% 82.5%;
+ --accent-foreground: 249.2 22% 11.6%;
+
+ --destructive: 343.1 75.6% 67.8%;
+ --destructive-foreground: 245.5 50% 91.4%;
+
+ --success: 189 43.5% 72.9%;
+ --success-foreground: 249.2 22% 11.6%;
+
+ --brand: 267.2 57.1% 78%;
+ --brand-foreground: 249.2 22% 11.6%;
+ --brand-muted: 247.8 24.7% 18.2%;
+
+ --warning: 35 87.6% 71.6%;
+ --warning-foreground: 249.2 22% 11.6%;
+
+ --border: 247.8 24.7% 18.2%;
+ --input: 247.8 24.7% 18.2%;
+ --ring: 267.2 57.1% 78%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 267.2 57.1% 78%;
+ --chart-secondary: 35 87.6% 71.6%;
+
+ /* Status colors */
+ --status-success: 189 43.5% 72.9%;
+ --status-warning: 35 87.6% 71.6%;
+ --status-in-progress: 267.2 57.1% 78%;
+
+ --sidebar-background: 247.1 22.7% 14.7%;
+ --sidebar-foreground: 248 15% 60.8%;
+ --sidebar-primary: 267.2 57.1% 78%;
+ --sidebar-primary-foreground: 249.2 22% 11.6%;
+ --sidebar-accent: 247.8 24.7% 18.2%;
+ --sidebar-accent-foreground: 245.5 50% 91.4%;
+ --sidebar-border: 248.6 14.7% 28%;
+ --sidebar-ring: 267.2 57.1% 78%;
+
+ /* Hover Effect */
+ --ctahover: 2.4 55.1% 82.5%;
+ }
+}
diff --git a/src/workspaces/themes/TokyoNight/client.ts b/src/workspaces/themes/TokyoNight/client.ts
new file mode 100644
index 00000000..a0bea0e6
--- /dev/null
+++ b/src/workspaces/themes/TokyoNight/client.ts
@@ -0,0 +1,2 @@
+import './variables.css';
+import './prose.css';
diff --git a/src/workspaces/themes/TokyoNight/index.ts b/src/workspaces/themes/TokyoNight/index.ts
new file mode 100644
index 00000000..6d99f07c
--- /dev/null
+++ b/src/workspaces/themes/TokyoNight/index.ts
@@ -0,0 +1 @@
+export const meta = { id: 'TokyoNight', name: 'Tokyo Night', description: 'Moonlight blues and soft purples from a Tokyo evening.' };
diff --git a/src/workspaces/themes/TokyoNight/prose.css b/src/workspaces/themes/TokyoNight/prose.css
new file mode 100644
index 00000000..bd0ef7e3
--- /dev/null
+++ b/src/workspaces/themes/TokyoNight/prose.css
@@ -0,0 +1,124 @@
+/* File Viewer — Markdown Prose */
+[data-color-theme="TokyoNight"] .file-viewer-md {
+ color: #c8d3f5;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md h1 {
+ border-bottom-color: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md h2 {
+ border-bottom-color: rgba(59, 66, 97, 0.3);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md a {
+ color: #82aaff;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md a:hover {
+ color: #86e1fc;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md strong {
+ color: #c8d3f5;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md blockquote {
+ border-left-color: #82aaff;
+ background: rgba(130, 170, 255, 0.06);
+ color: #828bb8;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md li::marker {
+ color: #82aaff;
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md hr {
+ background: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md th {
+ background: rgba(130, 170, 255, 0.08);
+ border-color: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md td {
+ border-color: rgba(59, 66, 97, 0.3);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md tr:nth-child(even) {
+ background: rgba(59, 66, 97, 0.1);
+}
+
+[data-color-theme="TokyoNight"] .file-viewer-md input[type="checkbox"] {
+ accent-color: #82aaff;
+}
+
+/* Skills — Markdown Prose */
+[data-color-theme="TokyoNight"] .skill-md {
+ color: #c8d3f5;
+}
+
+[data-color-theme="TokyoNight"] .skill-md h1 {
+ border-bottom-color: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .skill-md h2 {
+ border-bottom-color: rgba(59, 66, 97, 0.3);
+}
+
+[data-color-theme="TokyoNight"] .skill-md a {
+ color: #82aaff;
+}
+
+[data-color-theme="TokyoNight"] .skill-md a:hover {
+ color: #86e1fc;
+}
+
+[data-color-theme="TokyoNight"] .skill-md strong {
+ color: #c8d3f5;
+}
+
+[data-color-theme="TokyoNight"] .skill-md blockquote {
+ border-left-color: #82aaff;
+ background: rgba(130, 170, 255, 0.06);
+ color: #828bb8;
+}
+
+[data-color-theme="TokyoNight"] .skill-md li::marker {
+ color: #82aaff;
+}
+
+[data-color-theme="TokyoNight"] .skill-md code {
+ background: rgba(130, 170, 255, 0.1);
+ color: #82aaff;
+}
+
+[data-color-theme="TokyoNight"] .skill-md pre {
+ background: #1e2030;
+}
+
+[data-color-theme="TokyoNight"] .skill-md pre code {
+ color: #c8d3f5;
+}
+
+[data-color-theme="TokyoNight"] .skill-md hr {
+ background: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .skill-md th {
+ background: rgba(130, 170, 255, 0.08);
+ border-color: rgba(59, 66, 97, 0.4);
+}
+
+[data-color-theme="TokyoNight"] .skill-md td {
+ border-color: rgba(59, 66, 97, 0.3);
+}
+
+[data-color-theme="TokyoNight"] .skill-md tr:nth-child(even) {
+ background: rgba(59, 66, 97, 0.1);
+}
+
+[data-color-theme="TokyoNight"] .skill-md input[type="checkbox"] {
+ accent-color: #82aaff;
+}
diff --git a/src/workspaces/themes/TokyoNight/variables.css b/src/workspaces/themes/TokyoNight/variables.css
new file mode 100644
index 00000000..751d2884
--- /dev/null
+++ b/src/workspaces/themes/TokyoNight/variables.css
@@ -0,0 +1,92 @@
+@layer base {
+ [data-color-theme="TokyoNight"] {
+ /* Brand colors */
+ --duck-yellow: #ffc777;
+ --duck-orange: #ff966c;
+ --duck-teal: #82aaff;
+ --duck-forest: #828bb8;
+ --duck-dark: #c8d3f5;
+ --duck-beige: #2f334d;
+
+ /* Page background */
+ --pixel-grid-color: rgba(130, 170, 255, 0.06);
+
+ /* Glass surfaces */
+ --glass-bg: rgba(0, 0, 0, 0.25);
+ --glass-border: rgba(130, 170, 255, 0.12);
+ --dock-bg: rgba(0, 0, 0, 0.35);
+ --dock-border: rgba(130, 170, 255, 0.08);
+ --dock-tooltip-bg: rgba(0, 0, 0, 0.9);
+
+ /* Card component */
+ --card-bg: rgba(30, 32, 48, 0.92);
+ --card-grid-color: rgba(130, 170, 255, 0.04);
+
+ --cta: 220.8 100% 75.5%;
+ --cta-foreground: 232.5 22.9% 13.7%;
+
+ --naturegreen: 193.7 95.2% 75.7%;
+ --naturegreen-foreground: 232.5 22.9% 13.7%;
+
+ --background: 234 22.7% 17.3%;
+ --foreground: 225.3 69.2% 87.3%;
+
+ --card: 233.3 23.1% 15.3%;
+ --card-foreground: 225.3 69.2% 87.3%;
+
+ --popover: 233.3 23.1% 15.3%;
+ --popover-foreground: 225.3 69.2% 87.3%;
+
+ --primary: 220.8 100% 75.5%;
+ --primary-foreground: 232.5 22.9% 13.7%;
+
+ --secondary: 228.9 24.4% 30.6%;
+ --secondary-foreground: 225.3 69.2% 87.3%;
+
+ --muted: 232 24.2% 24.3%;
+ --muted-foreground: 230 27.6% 61.6%;
+
+ --accent: 193.7 95.2% 75.7%;
+ --accent-foreground: 232.5 22.9% 13.7%;
+
+ --destructive: 349.6 54.3% 50.2%;
+ --destructive-foreground: 225.3 69.2% 87.3%;
+
+ --success: 84.4 66.4% 73.1%;
+ --success-foreground: 232.5 22.9% 13.7%;
+
+ --brand: 220.8 100% 75.5%;
+ --brand-foreground: 232.5 22.9% 13.7%;
+ --brand-muted: 232 24.2% 24.3%;
+
+ --warning: 35.3 100% 73.3%;
+ --warning-foreground: 234 22.7% 17.3%;
+
+ --border: 228.9 24.4% 30.6%;
+ --input: 228.9 24.4% 30.6%;
+ --ring: 220.8 100% 75.5%;
+
+ --radius: 0.5rem;
+
+ /* Chart gradients */
+ --chart-primary: 220.8 100% 75.5%;
+ --chart-secondary: 35.3 100% 73.3%;
+
+ /* Status colors */
+ --status-success: 84.4 66.4% 73.1%;
+ --status-warning: 35.3 100% 73.3%;
+ --status-in-progress: 220.8 100% 75.5%;
+
+ --sidebar-background: 233.3 23.1% 15.3%;
+ --sidebar-foreground: 230 27.6% 61.6%;
+ --sidebar-primary: 220.8 100% 75.5%;
+ --sidebar-primary-foreground: 232.5 22.9% 13.7%;
+ --sidebar-accent: 232 24.2% 24.3%;
+ --sidebar-accent-foreground: 225.3 69.2% 87.3%;
+ --sidebar-border: 228.9 24.4% 30.6%;
+ --sidebar-ring: 220.8 100% 75.5%;
+
+ /* Hover Effect */
+ --ctahover: 193.7 95.2% 75.7%;
+ }
+}
diff --git a/src/workspaces/themes/index.ts b/src/workspaces/themes/index.ts
index 9e1282b5..36e127a7 100644
--- a/src/workspaces/themes/index.ts
+++ b/src/workspaces/themes/index.ts
@@ -1 +1,14 @@
-export const themes = [{ id: 'DuckPond', name: 'Duck Pond' }] as const;
+export const themes = [
+ { id: 'DuckPond', name: 'Duck Pond' },
+ { id: 'TokyoNight', name: 'Tokyo Night' },
+ { id: 'CatppuccinLatte', name: 'Catppuccin Latte' },
+ { id: 'CatppuccinMocha', name: 'Catppuccin Mocha' },
+ { id: 'Everforest', name: 'Everforest' },
+ { id: 'Gruvbox', name: 'Gruvbox' },
+ { id: 'Kanagawa', name: 'Kanagawa' },
+ { id: 'MatteBlack', name: 'Matte Black' },
+ { id: 'Nord', name: 'Nord' },
+ { id: 'OsakaJade', name: 'Osaka Jade' },
+ { id: 'Ristretto', name: 'Ristretto' },
+ { id: 'RosePine', name: 'Rose Pine' },
+] as const;
diff --git a/src/workspaces/themes/package.json b/src/workspaces/themes/package.json
index f0986315..e4d4f63a 100644
--- a/src/workspaces/themes/package.json
+++ b/src/workspaces/themes/package.json
@@ -4,6 +4,28 @@
"exports": {
".": "./index.ts",
"./DuckPond": "./DuckPond/index.ts",
- "./DuckPond/client": "./DuckPond/client.ts"
+ "./DuckPond/client": "./DuckPond/client.ts",
+ "./TokyoNight": "./TokyoNight/index.ts",
+ "./TokyoNight/client": "./TokyoNight/client.ts",
+ "./CatppuccinLatte": "./CatppuccinLatte/index.ts",
+ "./CatppuccinLatte/client": "./CatppuccinLatte/client.ts",
+ "./CatppuccinMocha": "./CatppuccinMocha/index.ts",
+ "./CatppuccinMocha/client": "./CatppuccinMocha/client.ts",
+ "./Everforest": "./Everforest/index.ts",
+ "./Everforest/client": "./Everforest/client.ts",
+ "./Gruvbox": "./Gruvbox/index.ts",
+ "./Gruvbox/client": "./Gruvbox/client.ts",
+ "./Kanagawa": "./Kanagawa/index.ts",
+ "./Kanagawa/client": "./Kanagawa/client.ts",
+ "./MatteBlack": "./MatteBlack/index.ts",
+ "./MatteBlack/client": "./MatteBlack/client.ts",
+ "./Nord": "./Nord/index.ts",
+ "./Nord/client": "./Nord/client.ts",
+ "./OsakaJade": "./OsakaJade/index.ts",
+ "./OsakaJade/client": "./OsakaJade/client.ts",
+ "./Ristretto": "./Ristretto/index.ts",
+ "./Ristretto/client": "./Ristretto/client.ts",
+ "./RosePine": "./RosePine/index.ts",
+ "./RosePine/client": "./RosePine/client.ts"
}
}