refactor: replace fs with secureFs for improved file handling

This commit updates various modules to utilize the secure file system operations from the secureFs module instead of the native fs module. Key changes include:

- Replaced fs imports with secureFs in multiple route handlers and services to enhance security and consistency in file operations.
- Added centralized validation for working directories in the sdk-options module to ensure all AI model invocations are secure.

These changes aim to improve the security and maintainability of file handling across the application.
This commit is contained in:
Test User
2025-12-21 01:32:26 -05:00
parent 2b5479ae0d
commit 077a63b03b
62 changed files with 4866 additions and 3350 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
import { Label } from "@/components/ui/label";
import { Palette } from "lucide-react";
import { themeOptions } from "@/config/theme-options";
import { cn } from "@/lib/utils";
import type { Theme, Project } from "../shared/types";
import { useState } from 'react';
import { Label } from '@/components/ui/label';
import { Palette, Moon, Sun } from 'lucide-react';
import { darkThemes, lightThemes } from '@/config/theme-options';
import { cn } from '@/lib/utils';
import type { Theme, Project } from '../shared/types';
interface AppearanceSectionProps {
effectiveTheme: Theme;
@@ -15,13 +16,17 @@ export function AppearanceSection({
currentProject,
onThemeChange,
}: AppearanceSectionProps) {
const [activeTab, setActiveTab] = useState<'dark' | 'light'>('dark');
const themesToShow = activeTab === 'dark' ? darkThemes : lightThemes;
return (
<div
className={cn(
"rounded-2xl overflow-hidden",
"border border-border/50",
"bg-gradient-to-br from-card/90 via-card/70 to-card/80 backdrop-blur-xl",
"shadow-sm shadow-black/5"
'rounded-2xl overflow-hidden',
'border border-border/50',
'bg-gradient-to-br from-card/90 via-card/70 to-card/80 backdrop-blur-xl',
'shadow-sm shadow-black/5'
)}
>
<div className="p-6 border-b border-border/50 bg-gradient-to-r from-transparent via-accent/5 to-transparent">
@@ -37,43 +42,69 @@ export function AppearanceSection({
</div>
<div className="p-6 space-y-4">
<div className="space-y-4">
<Label className="text-foreground font-medium">
Theme{" "}
<span className="text-muted-foreground font-normal">
{currentProject ? `(for ${currentProject.name})` : "(Global)"}
</span>
</Label>
<div className="flex items-center justify-between">
<Label className="text-foreground font-medium">
Theme{' '}
<span className="text-muted-foreground font-normal">
{currentProject ? `(for ${currentProject.name})` : '(Global)'}
</span>
</Label>
{/* Dark/Light Tabs */}
<div className="flex gap-1 p-1 rounded-lg bg-accent/30">
<button
onClick={() => setActiveTab('dark')}
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-all duration-200',
activeTab === 'dark'
? 'bg-brand-500 text-white shadow-sm'
: 'text-muted-foreground hover:text-foreground'
)}
>
<Moon className="w-3.5 h-3.5" />
Dark
</button>
<button
onClick={() => setActiveTab('light')}
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-all duration-200',
activeTab === 'light'
? 'bg-brand-500 text-white shadow-sm'
: 'text-muted-foreground hover:text-foreground'
)}
>
<Sun className="w-3.5 h-3.5" />
Light
</button>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{themeOptions.map(({ value, label, Icon, testId }) => {
{themesToShow.map(({ value, label, Icon, testId, color }) => {
const isActive = effectiveTheme === value;
return (
<button
key={value}
onClick={() => onThemeChange(value)}
className={cn(
"group flex items-center justify-center gap-2.5 px-4 py-3.5 rounded-xl",
"text-sm font-medium transition-all duration-200 ease-out",
'group flex items-center justify-center gap-2.5 px-4 py-3.5 rounded-xl',
'text-sm font-medium transition-all duration-200 ease-out',
isActive
? [
"bg-gradient-to-br from-brand-500/15 to-brand-600/10",
"border-2 border-brand-500/40",
"text-foreground",
"shadow-md shadow-brand-500/10",
'bg-gradient-to-br from-brand-500/15 to-brand-600/10',
'border-2 border-brand-500/40',
'text-foreground',
'shadow-md shadow-brand-500/10',
]
: [
"bg-accent/30 hover:bg-accent/50",
"border border-border/50 hover:border-border",
"text-muted-foreground hover:text-foreground",
"hover:shadow-sm",
'bg-accent/30 hover:bg-accent/50',
'border border-border/50 hover:border-border',
'text-muted-foreground hover:text-foreground',
'hover:shadow-sm',
],
"hover:scale-[1.02] active:scale-[0.98]"
'hover:scale-[1.02] active:scale-[0.98]'
)}
data-testid={testId}
>
<Icon className={cn(
"w-4 h-4 transition-all duration-200",
isActive ? "text-brand-500" : "group-hover:text-brand-400"
)} />
<Icon className="w-4 h-4 transition-all duration-200" style={{ color }} />
<span>{label}</span>
</button>
);

View File

@@ -1,4 +1,6 @@
// Shared TypeScript types for settings view components
// Theme type is now imported from the central theme-options config
export { type Theme } from '@/config/theme-options';
export interface CliStatus {
success: boolean;
@@ -17,31 +19,13 @@ export interface CliStatus {
error?: string;
}
export type Theme =
| "dark"
| "light"
| "retro"
| "dracula"
| "nord"
| "monokai"
| "tokyonight"
| "solarized"
| "gruvbox"
| "catppuccin"
| "onedark"
| "synthwave"
| "red"
| "cream"
| "sunset"
| "gray";
export type KanbanDetailLevel = "minimal" | "standard" | "detailed";
export type KanbanDetailLevel = 'minimal' | 'standard' | 'detailed';
export interface Project {
id: string;
name: string;
path: string;
theme?: Theme;
theme?: string;
}
export interface ApiKeys {

View File

@@ -1,8 +1,9 @@
import { Button } from "@/components/ui/button";
import { ArrowRight, ArrowLeft, Check } from "lucide-react";
import { themeOptions } from "@/config/theme-options";
import { useAppStore } from "@/store/app-store";
import { cn } from "@/lib/utils";
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { ArrowRight, ArrowLeft, Check, Moon, Sun } from 'lucide-react';
import { darkThemes, lightThemes } from '@/config/theme-options';
import { useAppStore } from '@/store/app-store';
import { cn } from '@/lib/utils';
interface ThemeStepProps {
onNext: () => void;
@@ -11,6 +12,7 @@ interface ThemeStepProps {
export function ThemeStep({ onNext, onBack }: ThemeStepProps) {
const { theme, setTheme, setPreviewTheme } = useAppStore();
const [activeTab, setActiveTab] = useState<'dark' | 'light'>('dark');
const handleThemeHover = (themeValue: string) => {
setPreviewTheme(themeValue as typeof theme);
@@ -25,19 +27,47 @@ export function ThemeStep({ onNext, onBack }: ThemeStepProps) {
setPreviewTheme(null);
};
const themesToShow = activeTab === 'dark' ? darkThemes : lightThemes;
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-3xl font-bold text-foreground mb-3">
Choose Your Theme
</h2>
<h2 className="text-3xl font-bold text-foreground mb-3">Choose Your Theme</h2>
<p className="text-muted-foreground max-w-md mx-auto">
Pick a theme that suits your style. Hover to preview, click to select.
</p>
</div>
{/* Dark/Light Tabs */}
<div className="flex justify-center gap-2">
<button
onClick={() => setActiveTab('dark')}
className={cn(
'flex items-center gap-2 px-6 py-2.5 rounded-lg font-medium transition-all duration-200',
activeTab === 'dark'
? 'bg-brand-500 text-white shadow-lg shadow-brand-500/25'
: 'bg-accent/50 text-muted-foreground hover:bg-accent hover:text-foreground'
)}
>
<Moon className="w-4 h-4" />
Dark Themes
</button>
<button
onClick={() => setActiveTab('light')}
className={cn(
'flex items-center gap-2 px-6 py-2.5 rounded-lg font-medium transition-all duration-200',
activeTab === 'light'
? 'bg-brand-500 text-white shadow-lg shadow-brand-500/25'
: 'bg-accent/50 text-muted-foreground hover:bg-accent hover:text-foreground'
)}
>
<Sun className="w-4 h-4" />
Light Themes
</button>
</div>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3">
{themeOptions.map((option) => {
{themesToShow.map((option) => {
const Icon = option.Icon;
const isSelected = theme === option.value;
@@ -49,11 +79,11 @@ export function ThemeStep({ onNext, onBack }: ThemeStepProps) {
onMouseLeave={handleThemeLeave}
onClick={() => handleThemeClick(option.value)}
className={cn(
"relative flex flex-col items-center gap-2 p-4 rounded-lg border-2 transition-all duration-200",
"hover:scale-105 hover:shadow-lg",
'relative flex flex-col items-center gap-2 p-4 rounded-lg border-2 transition-all duration-200',
'hover:scale-105 hover:shadow-lg',
isSelected
? "border-brand-500 bg-brand-500/10"
: "border-border hover:border-brand-400 bg-card"
? 'border-brand-500 bg-brand-500/10'
: 'border-border hover:border-brand-400 bg-card'
)}
>
{isSelected && (
@@ -61,10 +91,8 @@ export function ThemeStep({ onNext, onBack }: ThemeStepProps) {
<Check className="w-4 h-4 text-brand-500" />
</div>
)}
<Icon className="w-6 h-6 text-foreground" />
<span className="text-sm font-medium text-foreground">
{option.label}
</span>
<Icon className="w-6 h-6" style={{ color: option.color }} />
<span className="text-sm font-medium text-foreground">{option.label}</span>
</button>
);
})}

File diff suppressed because it is too large Load Diff

View File

@@ -2,115 +2,342 @@ import {
type LucideIcon,
Atom,
Cat,
Cherry,
CloudSun,
Coffee,
Eclipse,
Feather,
Flame,
Flower2,
Ghost,
Github,
Heart,
Leaf,
Moon,
Palmtree,
Radio,
Scroll,
Snowflake,
Sparkles,
Square,
Sun,
Sunrise,
Terminal,
Trees,
} from "lucide-react";
import { Theme } from "@/components/views/settings-view/shared/types";
Waves,
Wind,
} from 'lucide-react';
// Theme value type - all available themes
export type Theme =
// Dark themes (16)
| 'dark'
| 'retro'
| 'dracula'
| 'nord'
| 'monokai'
| 'tokyonight'
| 'solarized'
| 'gruvbox'
| 'catppuccin'
| 'onedark'
| 'synthwave'
| 'red'
| 'sunset'
| 'gray'
| 'forest'
| 'ocean'
// Light themes (16)
| 'light'
| 'cream'
| 'solarizedlight'
| 'github'
| 'paper'
| 'rose'
| 'mint'
| 'lavender'
| 'sand'
| 'sky'
| 'peach'
| 'snow'
| 'sepia'
| 'gruvboxlight'
| 'nordlight'
| 'blossom';
export interface ThemeOption {
value: Theme;
label: string;
Icon: LucideIcon;
testId: string;
isDark: boolean;
color: string; // Primary/brand color for icon display
}
// All theme options with dark/light categorization
export const themeOptions: ReadonlyArray<ThemeOption> = [
{ value: "dark", label: "Dark", Icon: Moon, testId: "dark-mode-button" },
{ value: "light", label: "Light", Icon: Sun, testId: "light-mode-button" },
// Dark themes (16)
{
value: "retro",
label: "Retro",
value: 'dark',
label: 'Dark',
Icon: Moon,
testId: 'dark-mode-button',
isDark: true,
color: '#3b82f6',
},
{
value: 'retro',
label: 'Retro',
Icon: Terminal,
testId: "retro-mode-button",
testId: 'retro-mode-button',
isDark: true,
color: '#22c55e',
},
{
value: "dracula",
label: "Dracula",
value: 'dracula',
label: 'Dracula',
Icon: Ghost,
testId: "dracula-mode-button",
testId: 'dracula-mode-button',
isDark: true,
color: '#bd93f9',
},
{
value: "nord",
label: "Nord",
value: 'nord',
label: 'Nord',
Icon: Snowflake,
testId: "nord-mode-button",
testId: 'nord-mode-button',
isDark: true,
color: '#88c0d0',
},
{
value: "monokai",
label: "Monokai",
value: 'monokai',
label: 'Monokai',
Icon: Flame,
testId: "monokai-mode-button",
testId: 'monokai-mode-button',
isDark: true,
color: '#f92672',
},
{
value: "tokyonight",
label: "Tokyo Night",
value: 'tokyonight',
label: 'Tokyo Night',
Icon: Sparkles,
testId: "tokyonight-mode-button",
testId: 'tokyonight-mode-button',
isDark: true,
color: '#bb9af7',
},
{
value: "solarized",
label: "Solarized",
value: 'solarized',
label: 'Solarized Dark',
Icon: Eclipse,
testId: "solarized-mode-button",
testId: 'solarized-mode-button',
isDark: true,
color: '#268bd2',
},
{
value: "gruvbox",
label: "Gruvbox",
value: 'gruvbox',
label: 'Gruvbox',
Icon: Trees,
testId: "gruvbox-mode-button",
testId: 'gruvbox-mode-button',
isDark: true,
color: '#fe8019',
},
{
value: "catppuccin",
label: "Catppuccin",
value: 'catppuccin',
label: 'Catppuccin',
Icon: Cat,
testId: "catppuccin-mode-button",
testId: 'catppuccin-mode-button',
isDark: true,
color: '#cba6f7',
},
{
value: "onedark",
label: "One Dark",
value: 'onedark',
label: 'One Dark',
Icon: Atom,
testId: "onedark-mode-button",
testId: 'onedark-mode-button',
isDark: true,
color: '#61afef',
},
{
value: "synthwave",
label: "Synthwave",
value: 'synthwave',
label: 'Synthwave',
Icon: Radio,
testId: "synthwave-mode-button",
testId: 'synthwave-mode-button',
isDark: true,
color: '#ff7edb',
},
{
value: "red",
label: "Red",
value: 'red',
label: 'Red',
Icon: Heart,
testId: "red-mode-button",
testId: 'red-mode-button',
isDark: true,
color: '#ef4444',
},
{
value: "cream",
label: "Cream",
Icon: Coffee,
testId: "cream-mode-button",
},
{
value: "sunset",
label: "Sunset",
value: 'sunset',
label: 'Sunset',
Icon: CloudSun,
testId: "sunset-mode-button",
testId: 'sunset-mode-button',
isDark: true,
color: '#f97316',
},
{
value: "gray",
label: "Gray",
value: 'gray',
label: 'Gray',
Icon: Square,
testId: "gray-mode-button",
testId: 'gray-mode-button',
isDark: true,
color: '#6b7280',
},
{
value: 'forest',
label: 'Forest',
Icon: Leaf,
testId: 'forest-mode-button',
isDark: true,
color: '#22c55e',
},
{
value: 'ocean',
label: 'Ocean',
Icon: Waves,
testId: 'ocean-mode-button',
isDark: true,
color: '#06b6d4',
},
// Light themes (16)
{
value: 'light',
label: 'Light',
Icon: Sun,
testId: 'light-mode-button',
isDark: false,
color: '#3b82f6',
},
{
value: 'cream',
label: 'Cream',
Icon: Coffee,
testId: 'cream-mode-button',
isDark: false,
color: '#b45309',
},
{
value: 'solarizedlight',
label: 'Solarized Light',
Icon: Sunrise,
testId: 'solarizedlight-mode-button',
isDark: false,
color: '#268bd2',
},
{
value: 'github',
label: 'GitHub',
Icon: Github,
testId: 'github-mode-button',
isDark: false,
color: '#0969da',
},
{
value: 'paper',
label: 'Paper',
Icon: Scroll,
testId: 'paper-mode-button',
isDark: false,
color: '#374151',
},
{
value: 'rose',
label: 'Rose',
Icon: Flower2,
testId: 'rose-mode-button',
isDark: false,
color: '#e11d48',
},
{
value: 'mint',
label: 'Mint',
Icon: Wind,
testId: 'mint-mode-button',
isDark: false,
color: '#0d9488',
},
{
value: 'lavender',
label: 'Lavender',
Icon: Feather,
testId: 'lavender-mode-button',
isDark: false,
color: '#8b5cf6',
},
{
value: 'sand',
label: 'Sand',
Icon: Palmtree,
testId: 'sand-mode-button',
isDark: false,
color: '#d97706',
},
{
value: 'sky',
label: 'Sky',
Icon: Sun,
testId: 'sky-mode-button',
isDark: false,
color: '#0284c7',
},
{
value: 'peach',
label: 'Peach',
Icon: Cherry,
testId: 'peach-mode-button',
isDark: false,
color: '#ea580c',
},
{
value: 'snow',
label: 'Snow',
Icon: Snowflake,
testId: 'snow-mode-button',
isDark: false,
color: '#3b82f6',
},
{
value: 'sepia',
label: 'Sepia',
Icon: Coffee,
testId: 'sepia-mode-button',
isDark: false,
color: '#92400e',
},
{
value: 'gruvboxlight',
label: 'Gruvbox Light',
Icon: Trees,
testId: 'gruvboxlight-mode-button',
isDark: false,
color: '#d65d0e',
},
{
value: 'nordlight',
label: 'Nord Light',
Icon: Snowflake,
testId: 'nordlight-mode-button',
isDark: false,
color: '#5e81ac',
},
{
value: 'blossom',
label: 'Blossom',
Icon: Cherry,
testId: 'blossom-mode-button',
isDark: false,
color: '#ec4899',
},
];
// Helper: Get only dark themes
export const darkThemes = themeOptions.filter((t) => t.isDark);
// Helper: Get only light themes
export const lightThemes = themeOptions.filter((t) => !t.isDark);

View File

@@ -1,28 +1,26 @@
import { createRootRoute, Outlet, useLocation, useNavigate } from "@tanstack/react-router";
import { useEffect, useState, useCallback } from "react";
import { Sidebar } from "@/components/layout/sidebar";
import { FileBrowserProvider, useFileBrowser, setGlobalFileBrowser } from "@/contexts/file-browser-context";
import { useAppStore } from "@/store/app-store";
import { useSetupStore } from "@/store/setup-store";
import { getElectronAPI } from "@/lib/electron";
import { Toaster } from "sonner";
import { ThemeOption, themeOptions } from "@/config/theme-options";
import { createRootRoute, Outlet, useLocation, useNavigate } from '@tanstack/react-router';
import { useEffect, useState, useCallback, useDeferredValue } from 'react';
import { Sidebar } from '@/components/layout/sidebar';
import {
FileBrowserProvider,
useFileBrowser,
setGlobalFileBrowser,
} from '@/contexts/file-browser-context';
import { useAppStore } from '@/store/app-store';
import { useSetupStore } from '@/store/setup-store';
import { getElectronAPI } from '@/lib/electron';
import { Toaster } from 'sonner';
import { ThemeOption, themeOptions } from '@/config/theme-options';
function RootLayoutContent() {
const location = useLocation();
const {
setIpcConnected,
theme,
currentProject,
previewTheme,
getEffectiveTheme,
} = useAppStore();
const { setIpcConnected, theme, currentProject, previewTheme, getEffectiveTheme } = useAppStore();
const { setupComplete } = useSetupStore();
const navigate = useNavigate();
const [isMounted, setIsMounted] = useState(false);
const [streamerPanelOpen, setStreamerPanelOpen] = useState(false);
const [setupHydrated, setSetupHydrated] = useState(() =>
useSetupStore.persist?.hasHydrated?.() ?? false
const [setupHydrated, setSetupHydrated] = useState(
() => useSetupStore.persist?.hasHydrated?.() ?? false
);
const { openFileBrowser } = useFileBrowser();
@@ -31,14 +29,14 @@ function RootLayoutContent() {
const activeElement = document.activeElement;
if (activeElement) {
const tagName = activeElement.tagName.toLowerCase();
if (tagName === "input" || tagName === "textarea" || tagName === "select") {
if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
return;
}
if (activeElement.getAttribute("contenteditable") === "true") {
if (activeElement.getAttribute('contenteditable') === 'true') {
return;
}
const role = activeElement.getAttribute("role");
if (role === "textbox" || role === "searchbox" || role === "combobox") {
const role = activeElement.getAttribute('role');
if (role === 'textbox' || role === 'searchbox' || role === 'combobox') {
return;
}
}
@@ -47,20 +45,22 @@ function RootLayoutContent() {
return;
}
if (event.key === "\\") {
if (event.key === '\\') {
event.preventDefault();
setStreamerPanelOpen((prev) => !prev);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleStreamerPanelShortcut);
window.addEventListener('keydown', handleStreamerPanelShortcut);
return () => {
window.removeEventListener("keydown", handleStreamerPanelShortcut);
window.removeEventListener('keydown', handleStreamerPanelShortcut);
};
}, [handleStreamerPanelShortcut]);
const effectiveTheme = getEffectiveTheme();
// Defer the theme value to keep UI responsive during rapid hover changes
const deferredTheme = useDeferredValue(effectiveTheme);
useEffect(() => {
setIsMounted(true);
@@ -78,7 +78,7 @@ function RootLayoutContent() {
});
return () => {
if (typeof unsubscribe === "function") {
if (typeof unsubscribe === 'function') {
unsubscribe();
}
};
@@ -88,10 +88,10 @@ function RootLayoutContent() {
useEffect(() => {
if (!setupHydrated) return;
if (!setupComplete && location.pathname !== "/setup") {
navigate({ to: "/setup" });
} else if (setupComplete && location.pathname === "/setup") {
navigate({ to: "/" });
if (!setupComplete && location.pathname !== '/setup') {
navigate({ to: '/setup' });
} else if (setupComplete && location.pathname === '/setup') {
navigate({ to: '/' });
}
}, [setupComplete, setupHydrated, location.pathname, navigate]);
@@ -105,9 +105,9 @@ function RootLayoutContent() {
try {
const api = getElectronAPI();
const result = await api.ping();
setIpcConnected(result === "pong");
setIpcConnected(result === 'pong');
} catch (error) {
console.error("IPC connection failed:", error);
console.error('IPC connection failed:', error);
setIpcConnected(false);
}
};
@@ -117,34 +117,34 @@ function RootLayoutContent() {
// Restore to board view if a project was previously open
useEffect(() => {
if (isMounted && currentProject && location.pathname === "/") {
navigate({ to: "/board" });
if (isMounted && currentProject && location.pathname === '/') {
navigate({ to: '/board' });
}
}, [isMounted, currentProject, location.pathname, navigate]);
// Apply theme class to document
// Apply theme class to document - use deferred value to avoid blocking UI
useEffect(() => {
const root = document.documentElement;
// Remove all theme classes dynamically from themeOptions
const themeClasses = themeOptions
.map((option) => option.value)
.filter((theme) => theme !== "system" as ThemeOption['value']);
.filter((theme) => theme !== ('system' as ThemeOption['value']));
root.classList.remove(...themeClasses);
if (effectiveTheme === "dark") {
root.classList.add("dark");
} else if (effectiveTheme === "system") {
const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
root.classList.add(isDark ? "dark" : "light");
} else if (effectiveTheme && effectiveTheme !== "light") {
root.classList.add(effectiveTheme);
if (deferredTheme === 'dark') {
root.classList.add('dark');
} else if (deferredTheme === 'system') {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
root.classList.add(isDark ? 'dark' : 'light');
} else if (deferredTheme && deferredTheme !== 'light') {
root.classList.add(deferredTheme);
} else {
root.classList.add("light");
root.classList.add('light');
}
}, [effectiveTheme, previewTheme, currentProject, theme]);
}, [deferredTheme]);
// Setup view is full-screen without sidebar
const isSetupRoute = location.pathname === "/setup";
const isSetupRoute = location.pathname === '/setup';
if (isSetupRoute) {
return (
@@ -159,7 +159,7 @@ function RootLayoutContent() {
<Sidebar />
<div
className="flex-1 flex flex-col overflow-hidden transition-all duration-300"
style={{ marginRight: streamerPanelOpen ? "250px" : "0" }}
style={{ marginRight: streamerPanelOpen ? '250px' : '0' }}
>
<Outlet />
</div>
@@ -167,7 +167,7 @@ function RootLayoutContent() {
{/* Hidden streamer panel - opens with "\" key, pushes content */}
<div
className={`fixed top-0 right-0 h-full w-[250px] bg-background border-l border-border transition-transform duration-300 ${
streamerPanelOpen ? "translate-x-0" : "translate-x-full"
streamerPanelOpen ? 'translate-x-0' : 'translate-x-full'
}`}
/>
<Toaster richColors position="bottom-right" />

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
@import "tailwindcss";
@import "tw-animate-css";
@import 'tailwindcss';
@import 'tw-animate-css';
/* Dark themes */
@custom-variant dark (&:is(.dark *));
@custom-variant retro (&:is(.retro *));
@custom-variant dracula (&:is(.dracula *));
@@ -13,9 +14,27 @@
@custom-variant onedark (&:is(.onedark *));
@custom-variant synthwave (&:is(.synthwave *));
@custom-variant red (&:is(.red *));
@custom-variant cream (&:is(.cream *));
@custom-variant sunset (&:is(.sunset *));
@custom-variant gray (&:is(.gray *));
@custom-variant forest (&:is(.forest *));
@custom-variant ocean (&:is(.ocean *));
/* Light themes */
@custom-variant cream (&:is(.cream *));
@custom-variant solarizedlight (&:is(.solarizedlight *));
@custom-variant github (&:is(.github *));
@custom-variant paper (&:is(.paper *));
@custom-variant rose (&:is(.rose *));
@custom-variant mint (&:is(.mint *));
@custom-variant lavender (&:is(.lavender *));
@custom-variant sand (&:is(.sand *));
@custom-variant sky (&:is(.sky *));
@custom-variant peach (&:is(.peach *));
@custom-variant snow (&:is(.snow *));
@custom-variant sepia (&:is(.sepia *));
@custom-variant gruvboxlight (&:is(.gruvboxlight *));
@custom-variant nordlight (&:is(.nordlight *));
@custom-variant blossom (&:is(.blossom *));
@theme inline {
--color-background: var(--background);
@@ -201,7 +220,7 @@
/* Card and popover backgrounds */
--card: oklch(0.14 0 0);
--card-foreground: oklch(1 0 0);
--popover: oklch(0.10 0 0);
--popover: oklch(0.1 0 0);
--popover-foreground: oklch(1 0 0);
/* Brand colors - purple/violet theme */
@@ -336,7 +355,6 @@
--running-indicator-text: oklch(0.6 0.22 265);
}
@layer base {
* {
@apply border-border outline-ring/50;
@@ -351,19 +369,19 @@
/* Ensure all clickable elements show pointer cursor */
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]),
[role='button']:not([aria-disabled='true']),
a[href],
input[type="button"]:not(:disabled),
input[type="submit"]:not(:disabled),
input[type="reset"]:not(:disabled),
input[type='button']:not(:disabled),
input[type='submit']:not(:disabled),
input[type='reset']:not(:disabled),
select:not(:disabled),
[tabindex]:not([tabindex="-1"]):not(:disabled) {
[tabindex]:not([tabindex='-1']):not(:disabled) {
cursor: pointer;
}
/* Disabled elements should show not-allowed cursor */
button:disabled,
[role="button"][aria-disabled="true"],
[role='button'][aria-disabled='true'],
input:disabled,
select:disabled,
textarea:disabled {
@@ -372,12 +390,44 @@
}
/* Custom scrollbar for dark themes */
:is(.dark, .retro, .dracula, .nord, .monokai, .tokyonight, .solarized, .gruvbox, .catppuccin, .onedark, .synthwave, .red, .sunset, .gray) ::-webkit-scrollbar {
:is(
.dark,
.retro,
.dracula,
.nord,
.monokai,
.tokyonight,
.solarized,
.gruvbox,
.catppuccin,
.onedark,
.synthwave,
.red,
.sunset,
.gray
)
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
:is(.dark, .retro, .dracula, .nord, .monokai, .tokyonight, .solarized, .gruvbox, .catppuccin, .onedark, .synthwave, .red, .sunset, .gray) ::-webkit-scrollbar-track {
:is(
.dark,
.retro,
.dracula,
.nord,
.monokai,
.tokyonight,
.solarized,
.gruvbox,
.catppuccin,
.onedark,
.synthwave,
.red,
.sunset,
.gray
)
::-webkit-scrollbar-track {
background: var(--muted);
}
@@ -392,11 +442,11 @@
/* Retro Scrollbar override */
.retro ::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 0;
background: var(--primary);
border-radius: 0;
}
.retro ::-webkit-scrollbar-track {
background: var(--background);
background: var(--background);
}
/* Red theme scrollbar */
@@ -518,8 +568,6 @@
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
/* Hover state utilities */
.hover-glass {
@@ -543,8 +591,6 @@
background: var(--background);
}
/* Action button utilities */
.bg-action-view {
background-color: var(--action-view);
@@ -588,8 +634,9 @@
}
.shadow-running-indicator\/50 {
box-shadow: 0 10px 15px -3px color-mix(in oklch, var(--running-indicator), transparent 50%),
0 4px 6px -4px color-mix(in oklch, var(--running-indicator), transparent 50%);
box-shadow:
0 10px 15px -3px color-mix(in oklch, var(--running-indicator), transparent 50%),
0 4px 6px -4px color-mix(in oklch, var(--running-indicator), transparent 50%);
}
.text-running-indicator {
@@ -632,132 +679,78 @@
/* Retro Overrides for Utilities */
.retro * {
border-radius: 0 !important;
border-radius: 0 !important;
}
/* Animated Outline Button Styles */
.animated-outline-gradient {
/* Default gradient - purple to blue */
background: conic-gradient(from 90deg at 50% 50%, #a855f7 0%, #3b82f6 50%, #a855f7 100%);
/* Default gradient - purple to blue */
background: conic-gradient(from 90deg at 50% 50%, #a855f7 0%, #3b82f6 50%, #a855f7 100%);
}
/* Light mode - deeper purple to blue gradient for better visibility */
/* Dark mode - purple to blue gradient */
/* Retro mode - unique scanline + neon effect */
@keyframes retro-glow {
from {
filter: brightness(1) drop-shadow(0 0 2px #00ff41);
}
to {
filter: brightness(1.2) drop-shadow(0 0 8px #00ff41);
}
from {
filter: brightness(1) drop-shadow(0 0 2px #00ff41);
}
to {
filter: brightness(1.2) drop-shadow(0 0 8px #00ff41);
}
}
/* Dracula animated-outline - purple/pink */
/* Nord animated-outline - frost blue */
/* Monokai animated-outline - pink/yellow */
/* Tokyo Night animated-outline - blue/magenta */
/* Solarized animated-outline - blue/cyan */
/* Gruvbox animated-outline - yellow/orange */
/* Catppuccin animated-outline - mauve/pink */
/* One Dark animated-outline - blue/magenta */
/* Synthwave animated-outline - hot pink/cyan with glow */
@keyframes synthwave-glow {
from {
filter: brightness(1) drop-shadow(0 0 3px #f97e72);
}
to {
filter: brightness(1.3) drop-shadow(0 0 10px #ff7edb);
}
from {
filter: brightness(1) drop-shadow(0 0 3px #f97e72);
}
to {
filter: brightness(1.3) drop-shadow(0 0 10px #ff7edb);
}
}
/* Slider Theme Styles */
/* Dracula slider */
/* Nord slider */
/* Monokai slider */
/* Tokyo Night slider */
/* Solarized slider */
/* Gruvbox slider */
/* Catppuccin slider */
/* One Dark slider */
/* Synthwave slider */
/* Line clamp utilities for text overflow prevention */
.line-clamp-2 {
display: -webkit-box;
@@ -807,136 +800,28 @@
/* Light theme - professional and readable */
/* Dark theme - high contrast */
/* Retro theme - neon green on black */
/* Dracula theme */
/* Nord theme */
/* Monokai theme */
/* Tokyo Night theme */
/* Solarized theme */
/* Gruvbox theme */
/* Catppuccin theme */
/* One Dark theme */
/* Synthwave theme */
/* XML Editor container styles */
.xml-editor {
position: relative;

View File

@@ -2,21 +2,39 @@
* Bundles all individual theme styles so the build pipeline
* doesn't tree-shake their CSS when imported dynamically.
*/
import "./themes/dark.css";
import "./themes/light.css";
import "./themes/retro.css";
import "./themes/dracula.css";
import "./themes/nord.css";
import "./themes/monokai.css";
import "./themes/tokyonight.css";
import "./themes/solarized.css";
import "./themes/gruvbox.css";
import "./themes/catppuccin.css";
import "./themes/onedark.css";
import "./themes/synthwave.css";
import "./themes/red.css";
import "./themes/cream.css";
import "./themes/sunset.css";
import "./themes/gray.css";
// Dark themes (16)
import './themes/dark.css';
import './themes/retro.css';
import './themes/dracula.css';
import './themes/nord.css';
import './themes/monokai.css';
import './themes/tokyonight.css';
import './themes/solarized.css';
import './themes/gruvbox.css';
import './themes/catppuccin.css';
import './themes/onedark.css';
import './themes/synthwave.css';
import './themes/red.css';
import './themes/sunset.css';
import './themes/gray.css';
import './themes/forest.css';
import './themes/ocean.css';
// Light themes (16)
import './themes/light.css';
import './themes/cream.css';
import './themes/solarizedlight.css';
import './themes/github.css';
import './themes/paper.css';
import './themes/rose.css';
import './themes/mint.css';
import './themes/lavender.css';
import './themes/sand.css';
import './themes/sky.css';
import './themes/peach.css';
import './themes/snow.css';
import './themes/sepia.css';
import './themes/gruvboxlight.css';
import './themes/nordlight.css';
import './themes/blossom.css';

View File

@@ -0,0 +1,92 @@
/* Blossom Theme - Cherry blossom pink */
.blossom {
--background: oklch(0.98 0.02 330);
--background-50: oklch(0.98 0.02 330 / 0.5);
--background-80: oklch(0.98 0.02 330 / 0.8);
--foreground: oklch(0.25 0.04 340);
--foreground-secondary: oklch(0.45 0.03 340);
--foreground-muted: oklch(0.55 0.025 340);
--card: oklch(0.99 0.015 330);
--card-foreground: oklch(0.25 0.04 340);
--popover: oklch(0.99 0.015 330);
--popover-foreground: oklch(0.25 0.04 340);
--primary: oklch(0.65 0.15 340);
--primary-foreground: oklch(0.99 0.015 330);
--brand-400: oklch(0.7 0.13 340);
--brand-500: oklch(0.65 0.15 340);
--brand-600: oklch(0.6 0.17 340);
--secondary: oklch(0.95 0.025 330);
--secondary-foreground: oklch(0.25 0.04 340);
--muted: oklch(0.94 0.028 330);
--muted-foreground: oklch(0.5 0.03 340);
--accent: oklch(0.92 0.032 330);
--accent-foreground: oklch(0.25 0.04 340);
--destructive: oklch(0.55 0.2 15);
--border: oklch(0.9 0.025 330);
--border-glass: oklch(0.65 0.15 340 / 0.15);
--input: oklch(0.98 0.018 330);
--ring: oklch(0.65 0.15 340);
--chart-1: oklch(0.65 0.15 340);
--chart-2: oklch(0.6 0.15 300);
--chart-3: oklch(0.55 0.15 15);
--chart-4: oklch(0.6 0.12 350);
--chart-5: oklch(0.55 0.1 280);
--sidebar: oklch(0.97 0.022 330);
--sidebar-foreground: oklch(0.25 0.04 340);
--sidebar-primary: oklch(0.65 0.15 340);
--sidebar-primary-foreground: oklch(0.99 0.015 330);
--sidebar-accent: oklch(0.94 0.028 330);
--sidebar-accent-foreground: oklch(0.25 0.04 340);
--sidebar-border: oklch(0.9 0.025 330);
--sidebar-ring: oklch(0.65 0.15 340);
--action-view: oklch(0.65 0.15 340);
--action-view-hover: oklch(0.6 0.17 340);
--action-followup: oklch(0.6 0.15 300);
--action-followup-hover: oklch(0.55 0.17 300);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.65 0.15 340);
--running-indicator-text: oklch(0.6 0.17 340);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 15);
--status-error-bg: oklch(0.55 0.2 15 / 0.15);
--status-info: oklch(0.55 0.15 230);
--status-info-bg: oklch(0.55 0.15 230 / 0.15);
--status-backlog: oklch(0.6 0.025 340);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.blossom .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.02 330),
oklch(0.97 0.025 330),
oklch(0.98 0.02 330)
);
}
.blossom .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #ec4899 0%, #f472b6 50%, #ec4899 100%);
}
.blossom .animated-outline-inner {
background: oklch(0.99 0.015 330) !important;
color: #ec4899 !important;
}

View File

@@ -0,0 +1,98 @@
/* Forest Theme - Deep green dark theme */
.forest {
--background: oklch(0.12 0.02 150);
--background-50: oklch(0.12 0.02 150 / 0.5);
--background-80: oklch(0.12 0.02 150 / 0.8);
--foreground: oklch(0.95 0.02 150);
--foreground-secondary: oklch(0.7 0.03 150);
--foreground-muted: oklch(0.6 0.03 150);
--card: oklch(0.16 0.025 150);
--card-foreground: oklch(0.95 0.02 150);
--popover: oklch(0.14 0.022 150);
--popover-foreground: oklch(0.95 0.02 150);
--primary: oklch(0.6 0.18 145);
--primary-foreground: oklch(0.12 0.02 150);
--brand-400: oklch(0.65 0.16 145);
--brand-500: oklch(0.6 0.18 145);
--brand-600: oklch(0.55 0.2 145);
--secondary: oklch(1 0 0 / 0.05);
--secondary-foreground: oklch(0.95 0.02 150);
--muted: oklch(0.2 0.03 150);
--muted-foreground: oklch(0.65 0.03 150);
--accent: oklch(1 0 0 / 0.08);
--accent-foreground: oklch(0.95 0.02 150);
--destructive: oklch(0.6 0.22 25);
--border: oklch(0.25 0.04 150);
--border-glass: oklch(1 0 0 / 0.1);
--input: oklch(0.14 0.022 150);
--ring: oklch(0.6 0.18 145);
--chart-1: oklch(0.6 0.18 145);
--chart-2: oklch(0.65 0.15 100);
--chart-3: oklch(0.7 0.12 180);
--chart-4: oklch(0.6 0.2 200);
--chart-5: oklch(0.55 0.15 50);
--sidebar: oklch(0.1 0.02 150 / 0.8);
--sidebar-foreground: oklch(0.95 0.02 150);
--sidebar-primary: oklch(0.6 0.18 145);
--sidebar-primary-foreground: oklch(0.12 0.02 150);
--sidebar-accent: oklch(1 0 0 / 0.05);
--sidebar-accent-foreground: oklch(0.95 0.02 150);
--sidebar-border: oklch(1 0 0 / 0.1);
--sidebar-ring: oklch(0.6 0.18 145);
--action-view: oklch(0.6 0.18 145);
--action-view-hover: oklch(0.55 0.2 145);
--action-followup: oklch(0.6 0.15 180);
--action-followup-hover: oklch(0.55 0.17 180);
--action-commit: oklch(0.6 0.18 145);
--action-commit-hover: oklch(0.55 0.2 145);
--action-verify: oklch(0.6 0.18 145);
--action-verify-hover: oklch(0.55 0.2 145);
--running-indicator: oklch(0.6 0.18 145);
--running-indicator-text: oklch(0.65 0.16 145);
--status-success: oklch(0.65 0.18 145);
--status-success-bg: oklch(0.65 0.18 145 / 0.2);
--status-warning: oklch(0.7 0.15 80);
--status-warning-bg: oklch(0.7 0.15 80 / 0.2);
--status-error: oklch(0.6 0.22 25);
--status-error-bg: oklch(0.6 0.22 25 / 0.2);
--status-info: oklch(0.6 0.15 180);
--status-info-bg: oklch(0.6 0.15 180 / 0.2);
--status-backlog: oklch(0.55 0.03 150);
--status-in-progress: oklch(0.7 0.15 80);
--status-waiting: oklch(0.65 0.12 60);
--shadow-xs: 0 1px 2px rgba(0, 20, 10, 0.3);
--shadow-sm: 0 1px 3px rgba(0, 20, 10, 0.4), 0 1px 2px rgba(0, 20, 10, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 20, 10, 0.4), 0 2px 4px -1px rgba(0, 20, 10, 0.3);
--shadow-lg: 0 10px 15px -3px rgba(0, 20, 10, 0.4), 0 4px 6px -2px rgba(0, 20, 10, 0.2);
--shadow-xl: 0 20px 25px -5px rgba(0, 20, 10, 0.5), 0 10px 10px -5px rgba(0, 20, 10, 0.3);
}
.forest .content-bg {
background: linear-gradient(
135deg,
oklch(0.12 0.02 150),
oklch(0.15 0.025 150),
oklch(0.12 0.02 150)
);
}
.forest .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #22c55e 0%, #16a34a 50%, #22c55e 100%);
}
.forest .animated-outline-inner {
background: oklch(0.16 0.025 150) !important;
color: #86efac !important;
}

View File

@@ -0,0 +1,87 @@
/* GitHub Light Theme */
.github {
--background: oklch(0.99 0 0);
--background-50: oklch(0.99 0 0 / 0.5);
--background-80: oklch(0.99 0 0 / 0.8);
--foreground: oklch(0.2 0 0);
--foreground-secondary: oklch(0.4 0 0);
--foreground-muted: oklch(0.55 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.2 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.2 0 0);
--primary: oklch(0.5 0.15 250);
--primary-foreground: oklch(1 0 0);
--brand-400: oklch(0.55 0.13 250);
--brand-500: oklch(0.5 0.15 250);
--brand-600: oklch(0.45 0.17 250);
--secondary: oklch(0.96 0 0);
--secondary-foreground: oklch(0.2 0 0);
--muted: oklch(0.96 0 0);
--muted-foreground: oklch(0.45 0 0);
--accent: oklch(0.94 0 0);
--accent-foreground: oklch(0.2 0 0);
--destructive: oklch(0.55 0.22 25);
--border: oklch(0.88 0 0);
--border-glass: oklch(0.2 0 0 / 0.1);
--input: oklch(0.98 0 0);
--ring: oklch(0.5 0.15 250);
--chart-1: oklch(0.5 0.15 250);
--chart-2: oklch(0.55 0.18 145);
--chart-3: oklch(0.6 0.15 45);
--chart-4: oklch(0.55 0.15 300);
--chart-5: oklch(0.55 0.18 25);
--sidebar: oklch(0.98 0 0);
--sidebar-foreground: oklch(0.2 0 0);
--sidebar-primary: oklch(0.5 0.15 250);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.94 0 0);
--sidebar-accent-foreground: oklch(0.2 0 0);
--sidebar-border: oklch(0.88 0 0);
--sidebar-ring: oklch(0.5 0.15 250);
--action-view: oklch(0.5 0.15 250);
--action-view-hover: oklch(0.45 0.17 250);
--action-followup: oklch(0.55 0.15 230);
--action-followup-hover: oklch(0.5 0.17 230);
--action-commit: oklch(0.55 0.18 145);
--action-commit-hover: oklch(0.5 0.2 145);
--action-verify: oklch(0.55 0.18 145);
--action-verify-hover: oklch(0.5 0.2 145);
--running-indicator: oklch(0.5 0.15 250);
--running-indicator-text: oklch(0.45 0.17 250);
--status-success: oklch(0.55 0.18 145);
--status-success-bg: oklch(0.55 0.18 145 / 0.15);
--status-warning: oklch(0.65 0.15 80);
--status-warning-bg: oklch(0.65 0.15 80 / 0.15);
--status-error: oklch(0.55 0.22 25);
--status-error-bg: oklch(0.55 0.22 25 / 0.15);
--status-info: oklch(0.5 0.15 250);
--status-info-bg: oklch(0.5 0.15 250 / 0.15);
--status-backlog: oklch(0.55 0 0);
--status-in-progress: oklch(0.65 0.15 80);
--status-waiting: oklch(0.6 0.12 50);
}
.github .content-bg {
background: linear-gradient(135deg, oklch(0.99 0 0), oklch(0.98 0 0), oklch(0.99 0 0));
}
.github .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #0969da 0%, #1f883d 50%, #0969da 100%);
}
.github .animated-outline-inner {
background: oklch(1 0 0) !important;
color: #0969da !important;
}

View File

@@ -0,0 +1,92 @@
/* Gruvbox Light Theme */
.gruvboxlight {
--background: oklch(0.96 0.02 85);
--background-50: oklch(0.96 0.02 85 / 0.5);
--background-80: oklch(0.96 0.02 85 / 0.8);
--foreground: oklch(0.25 0.04 65);
--foreground-secondary: oklch(0.4 0.04 65);
--foreground-muted: oklch(0.55 0.03 65);
--card: oklch(0.98 0.015 85);
--card-foreground: oklch(0.25 0.04 65);
--popover: oklch(0.97 0.018 85);
--popover-foreground: oklch(0.25 0.04 65);
--primary: oklch(0.55 0.15 70);
--primary-foreground: oklch(0.98 0.015 85);
--brand-400: oklch(0.6 0.13 70);
--brand-500: oklch(0.55 0.15 70);
--brand-600: oklch(0.5 0.17 70);
--secondary: oklch(0.93 0.025 85);
--secondary-foreground: oklch(0.25 0.04 65);
--muted: oklch(0.92 0.028 85);
--muted-foreground: oklch(0.5 0.03 65);
--accent: oklch(0.9 0.032 85);
--accent-foreground: oklch(0.25 0.04 65);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.87 0.03 85);
--border-glass: oklch(0.55 0.15 70 / 0.15);
--input: oklch(0.97 0.018 85);
--ring: oklch(0.55 0.15 70);
--chart-1: oklch(0.55 0.15 70);
--chart-2: oklch(0.55 0.18 25);
--chart-3: oklch(0.5 0.15 145);
--chart-4: oklch(0.55 0.15 230);
--chart-5: oklch(0.55 0.15 300);
--sidebar: oklch(0.95 0.022 85);
--sidebar-foreground: oklch(0.25 0.04 65);
--sidebar-primary: oklch(0.55 0.15 70);
--sidebar-primary-foreground: oklch(0.98 0.015 85);
--sidebar-accent: oklch(0.92 0.028 85);
--sidebar-accent-foreground: oklch(0.25 0.04 65);
--sidebar-border: oklch(0.87 0.03 85);
--sidebar-ring: oklch(0.55 0.15 70);
--action-view: oklch(0.55 0.15 70);
--action-view-hover: oklch(0.5 0.17 70);
--action-followup: oklch(0.55 0.15 230);
--action-followup-hover: oklch(0.5 0.17 230);
--action-commit: oklch(0.5 0.15 145);
--action-commit-hover: oklch(0.45 0.17 145);
--action-verify: oklch(0.5 0.15 145);
--action-verify-hover: oklch(0.45 0.17 145);
--running-indicator: oklch(0.55 0.15 70);
--running-indicator-text: oklch(0.5 0.17 70);
--status-success: oklch(0.5 0.15 145);
--status-success-bg: oklch(0.5 0.15 145 / 0.15);
--status-warning: oklch(0.6 0.15 70);
--status-warning-bg: oklch(0.6 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.15);
--status-info: oklch(0.55 0.15 230);
--status-info-bg: oklch(0.55 0.15 230 / 0.15);
--status-backlog: oklch(0.6 0.03 65);
--status-in-progress: oklch(0.6 0.15 70);
--status-waiting: oklch(0.58 0.12 55);
}
.gruvboxlight .content-bg {
background: linear-gradient(
135deg,
oklch(0.96 0.02 85),
oklch(0.95 0.025 85),
oklch(0.96 0.02 85)
);
}
.gruvboxlight .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #d79921 0%, #b57614 50%, #d79921 100%);
}
.gruvboxlight .animated-outline-inner {
background: oklch(0.98 0.015 85) !important;
color: #b57614 !important;
}

View File

@@ -0,0 +1,92 @@
/* Lavender Theme - Soft purple/lavender */
.lavender {
--background: oklch(0.97 0.02 285);
--background-50: oklch(0.97 0.02 285 / 0.5);
--background-80: oklch(0.97 0.02 285 / 0.8);
--foreground: oklch(0.25 0.04 285);
--foreground-secondary: oklch(0.45 0.04 285);
--foreground-muted: oklch(0.55 0.03 285);
--card: oklch(0.98 0.015 285);
--card-foreground: oklch(0.25 0.04 285);
--popover: oklch(0.98 0.015 285);
--popover-foreground: oklch(0.25 0.04 285);
--primary: oklch(0.55 0.18 280);
--primary-foreground: oklch(0.98 0.015 285);
--brand-400: oklch(0.6 0.16 280);
--brand-500: oklch(0.55 0.18 280);
--brand-600: oklch(0.5 0.2 280);
--secondary: oklch(0.94 0.025 285);
--secondary-foreground: oklch(0.25 0.04 285);
--muted: oklch(0.93 0.028 285);
--muted-foreground: oklch(0.5 0.04 285);
--accent: oklch(0.91 0.032 285);
--accent-foreground: oklch(0.25 0.04 285);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.88 0.025 285);
--border-glass: oklch(0.55 0.18 280 / 0.15);
--input: oklch(0.97 0.018 285);
--ring: oklch(0.55 0.18 280);
--chart-1: oklch(0.55 0.18 280);
--chart-2: oklch(0.6 0.15 320);
--chart-3: oklch(0.55 0.15 250);
--chart-4: oklch(0.6 0.12 200);
--chart-5: oklch(0.55 0.15 350);
--sidebar: oklch(0.96 0.022 285);
--sidebar-foreground: oklch(0.25 0.04 285);
--sidebar-primary: oklch(0.55 0.18 280);
--sidebar-primary-foreground: oklch(0.98 0.015 285);
--sidebar-accent: oklch(0.93 0.028 285);
--sidebar-accent-foreground: oklch(0.25 0.04 285);
--sidebar-border: oklch(0.88 0.025 285);
--sidebar-ring: oklch(0.55 0.18 280);
--action-view: oklch(0.55 0.18 280);
--action-view-hover: oklch(0.5 0.2 280);
--action-followup: oklch(0.55 0.15 250);
--action-followup-hover: oklch(0.5 0.17 250);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.55 0.18 280);
--running-indicator-text: oklch(0.5 0.2 280);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.15);
--status-info: oklch(0.55 0.15 250);
--status-info-bg: oklch(0.55 0.15 250 / 0.15);
--status-backlog: oklch(0.6 0.03 285);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.lavender .content-bg {
background: linear-gradient(
135deg,
oklch(0.97 0.02 285),
oklch(0.96 0.025 285),
oklch(0.97 0.02 285)
);
}
.lavender .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #a855f7 0%, #8b5cf6 50%, #a855f7 100%);
}
.lavender .animated-outline-inner {
background: oklch(0.98 0.015 285) !important;
color: #a855f7 !important;
}

View File

@@ -0,0 +1,92 @@
/* Mint Theme - Fresh mint green */
.mint {
--background: oklch(0.98 0.015 160);
--background-50: oklch(0.98 0.015 160 / 0.5);
--background-80: oklch(0.98 0.015 160 / 0.8);
--foreground: oklch(0.2 0.03 160);
--foreground-secondary: oklch(0.4 0.03 160);
--foreground-muted: oklch(0.55 0.02 160);
--card: oklch(0.99 0.01 160);
--card-foreground: oklch(0.2 0.03 160);
--popover: oklch(0.99 0.01 160);
--popover-foreground: oklch(0.2 0.03 160);
--primary: oklch(0.55 0.15 165);
--primary-foreground: oklch(0.99 0.01 160);
--brand-400: oklch(0.6 0.13 165);
--brand-500: oklch(0.55 0.15 165);
--brand-600: oklch(0.5 0.17 165);
--secondary: oklch(0.95 0.018 160);
--secondary-foreground: oklch(0.2 0.03 160);
--muted: oklch(0.94 0.02 160);
--muted-foreground: oklch(0.5 0.03 160);
--accent: oklch(0.92 0.025 160);
--accent-foreground: oklch(0.2 0.03 160);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.88 0.02 160);
--border-glass: oklch(0.55 0.15 165 / 0.15);
--input: oklch(0.98 0.012 160);
--ring: oklch(0.55 0.15 165);
--chart-1: oklch(0.55 0.15 165);
--chart-2: oklch(0.6 0.12 200);
--chart-3: oklch(0.55 0.15 140);
--chart-4: oklch(0.6 0.12 180);
--chart-5: oklch(0.55 0.1 230);
--sidebar: oklch(0.97 0.015 160);
--sidebar-foreground: oklch(0.2 0.03 160);
--sidebar-primary: oklch(0.55 0.15 165);
--sidebar-primary-foreground: oklch(0.99 0.01 160);
--sidebar-accent: oklch(0.94 0.02 160);
--sidebar-accent-foreground: oklch(0.2 0.03 160);
--sidebar-border: oklch(0.88 0.02 160);
--sidebar-ring: oklch(0.55 0.15 165);
--action-view: oklch(0.55 0.15 165);
--action-view-hover: oklch(0.5 0.17 165);
--action-followup: oklch(0.55 0.12 200);
--action-followup-hover: oklch(0.5 0.14 200);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.55 0.15 165);
--running-indicator-text: oklch(0.5 0.17 165);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.15);
--status-info: oklch(0.55 0.12 200);
--status-info-bg: oklch(0.55 0.12 200 / 0.15);
--status-backlog: oklch(0.6 0.02 160);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.mint .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.015 160),
oklch(0.97 0.018 160),
oklch(0.98 0.015 160)
);
}
.mint .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #10b981 0%, #14b8a6 50%, #10b981 100%);
}
.mint .animated-outline-inner {
background: oklch(0.99 0.01 160) !important;
color: #10b981 !important;
}

View File

@@ -0,0 +1,92 @@
/* Nord Light Theme */
.nordlight {
--background: oklch(0.97 0.01 220);
--background-50: oklch(0.97 0.01 220 / 0.5);
--background-80: oklch(0.97 0.01 220 / 0.8);
--foreground: oklch(0.25 0.03 220);
--foreground-secondary: oklch(0.45 0.025 220);
--foreground-muted: oklch(0.55 0.02 220);
--card: oklch(0.99 0.008 220);
--card-foreground: oklch(0.25 0.03 220);
--popover: oklch(0.98 0.01 220);
--popover-foreground: oklch(0.25 0.03 220);
--primary: oklch(0.55 0.12 225);
--primary-foreground: oklch(0.99 0.008 220);
--brand-400: oklch(0.6 0.1 225);
--brand-500: oklch(0.55 0.12 225);
--brand-600: oklch(0.5 0.14 225);
--secondary: oklch(0.94 0.012 220);
--secondary-foreground: oklch(0.25 0.03 220);
--muted: oklch(0.93 0.015 220);
--muted-foreground: oklch(0.5 0.025 220);
--accent: oklch(0.91 0.018 220);
--accent-foreground: oklch(0.25 0.03 220);
--destructive: oklch(0.55 0.18 25);
--border: oklch(0.88 0.015 220);
--border-glass: oklch(0.55 0.12 225 / 0.12);
--input: oklch(0.98 0.01 220);
--ring: oklch(0.55 0.12 225);
--chart-1: oklch(0.55 0.12 225);
--chart-2: oklch(0.55 0.15 25);
--chart-3: oklch(0.55 0.12 145);
--chart-4: oklch(0.55 0.12 300);
--chart-5: oklch(0.6 0.12 80);
--sidebar: oklch(0.96 0.01 220);
--sidebar-foreground: oklch(0.25 0.03 220);
--sidebar-primary: oklch(0.55 0.12 225);
--sidebar-primary-foreground: oklch(0.99 0.008 220);
--sidebar-accent: oklch(0.93 0.015 220);
--sidebar-accent-foreground: oklch(0.25 0.03 220);
--sidebar-border: oklch(0.88 0.015 220);
--sidebar-ring: oklch(0.55 0.12 225);
--action-view: oklch(0.55 0.12 225);
--action-view-hover: oklch(0.5 0.14 225);
--action-followup: oklch(0.55 0.12 200);
--action-followup-hover: oklch(0.5 0.14 200);
--action-commit: oklch(0.55 0.12 145);
--action-commit-hover: oklch(0.5 0.14 145);
--action-verify: oklch(0.55 0.12 145);
--action-verify-hover: oklch(0.5 0.14 145);
--running-indicator: oklch(0.55 0.12 225);
--running-indicator-text: oklch(0.5 0.14 225);
--status-success: oklch(0.55 0.12 145);
--status-success-bg: oklch(0.55 0.12 145 / 0.15);
--status-warning: oklch(0.65 0.12 80);
--status-warning-bg: oklch(0.65 0.12 80 / 0.15);
--status-error: oklch(0.55 0.18 25);
--status-error-bg: oklch(0.55 0.18 25 / 0.15);
--status-info: oklch(0.55 0.12 225);
--status-info-bg: oklch(0.55 0.12 225 / 0.15);
--status-backlog: oklch(0.6 0.02 220);
--status-in-progress: oklch(0.65 0.12 80);
--status-waiting: oklch(0.6 0.1 55);
}
.nordlight .content-bg {
background: linear-gradient(
135deg,
oklch(0.97 0.01 220),
oklch(0.96 0.012 220),
oklch(0.97 0.01 220)
);
}
.nordlight .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #5e81ac 0%, #81a1c1 50%, #5e81ac 100%);
}
.nordlight .animated-outline-inner {
background: oklch(0.99 0.008 220) !important;
color: #5e81ac !important;
}

View File

@@ -0,0 +1,98 @@
/* Ocean Theme - Deep blue dark theme */
.ocean {
--background: oklch(0.12 0.03 230);
--background-50: oklch(0.12 0.03 230 / 0.5);
--background-80: oklch(0.12 0.03 230 / 0.8);
--foreground: oklch(0.95 0.02 230);
--foreground-secondary: oklch(0.7 0.03 230);
--foreground-muted: oklch(0.6 0.03 230);
--card: oklch(0.16 0.035 230);
--card-foreground: oklch(0.95 0.02 230);
--popover: oklch(0.14 0.032 230);
--popover-foreground: oklch(0.95 0.02 230);
--primary: oklch(0.6 0.18 230);
--primary-foreground: oklch(0.12 0.03 230);
--brand-400: oklch(0.65 0.16 230);
--brand-500: oklch(0.6 0.18 230);
--brand-600: oklch(0.55 0.2 235);
--secondary: oklch(1 0 0 / 0.05);
--secondary-foreground: oklch(0.95 0.02 230);
--muted: oklch(0.2 0.04 230);
--muted-foreground: oklch(0.65 0.03 230);
--accent: oklch(1 0 0 / 0.08);
--accent-foreground: oklch(0.95 0.02 230);
--destructive: oklch(0.6 0.22 25);
--border: oklch(0.25 0.05 230);
--border-glass: oklch(1 0 0 / 0.1);
--input: oklch(0.14 0.032 230);
--ring: oklch(0.6 0.18 230);
--chart-1: oklch(0.6 0.18 230);
--chart-2: oklch(0.6 0.15 200);
--chart-3: oklch(0.65 0.15 180);
--chart-4: oklch(0.6 0.2 260);
--chart-5: oklch(0.55 0.15 300);
--sidebar: oklch(0.1 0.03 230 / 0.8);
--sidebar-foreground: oklch(0.95 0.02 230);
--sidebar-primary: oklch(0.6 0.18 230);
--sidebar-primary-foreground: oklch(0.12 0.03 230);
--sidebar-accent: oklch(1 0 0 / 0.05);
--sidebar-accent-foreground: oklch(0.95 0.02 230);
--sidebar-border: oklch(1 0 0 / 0.1);
--sidebar-ring: oklch(0.6 0.18 230);
--action-view: oklch(0.6 0.18 230);
--action-view-hover: oklch(0.55 0.2 235);
--action-followup: oklch(0.6 0.15 200);
--action-followup-hover: oklch(0.55 0.17 200);
--action-commit: oklch(0.6 0.15 180);
--action-commit-hover: oklch(0.55 0.17 180);
--action-verify: oklch(0.6 0.15 180);
--action-verify-hover: oklch(0.55 0.17 180);
--running-indicator: oklch(0.6 0.18 230);
--running-indicator-text: oklch(0.65 0.16 230);
--status-success: oklch(0.6 0.15 180);
--status-success-bg: oklch(0.6 0.15 180 / 0.2);
--status-warning: oklch(0.7 0.15 80);
--status-warning-bg: oklch(0.7 0.15 80 / 0.2);
--status-error: oklch(0.6 0.22 25);
--status-error-bg: oklch(0.6 0.22 25 / 0.2);
--status-info: oklch(0.6 0.18 230);
--status-info-bg: oklch(0.6 0.18 230 / 0.2);
--status-backlog: oklch(0.55 0.03 230);
--status-in-progress: oklch(0.7 0.15 80);
--status-waiting: oklch(0.65 0.12 60);
--shadow-xs: 0 1px 2px rgba(0, 10, 30, 0.3);
--shadow-sm: 0 1px 3px rgba(0, 10, 30, 0.4), 0 1px 2px rgba(0, 10, 30, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 10, 30, 0.4), 0 2px 4px -1px rgba(0, 10, 30, 0.3);
--shadow-lg: 0 10px 15px -3px rgba(0, 10, 30, 0.4), 0 4px 6px -2px rgba(0, 10, 30, 0.2);
--shadow-xl: 0 20px 25px -5px rgba(0, 10, 30, 0.5), 0 10px 10px -5px rgba(0, 10, 30, 0.3);
}
.ocean .content-bg {
background: linear-gradient(
135deg,
oklch(0.12 0.03 230),
oklch(0.15 0.035 230),
oklch(0.12 0.03 230)
);
}
.ocean .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #3b82f6 0%, #0ea5e9 50%, #3b82f6 100%);
}
.ocean .animated-outline-inner {
background: oklch(0.16 0.035 230) !important;
color: #93c5fd !important;
}

View File

@@ -0,0 +1,92 @@
/* Paper Theme - Clean minimal white */
.paper {
--background: oklch(0.99 0 0);
--background-50: oklch(0.99 0 0 / 0.5);
--background-80: oklch(0.99 0 0 / 0.8);
--foreground: oklch(0.15 0 0);
--foreground-secondary: oklch(0.35 0 0);
--foreground-muted: oklch(0.5 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.15 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.15 0 0);
--primary: oklch(0.3 0 0);
--primary-foreground: oklch(1 0 0);
--brand-400: oklch(0.35 0 0);
--brand-500: oklch(0.3 0 0);
--brand-600: oklch(0.25 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.15 0 0);
--muted: oklch(0.96 0 0);
--muted-foreground: oklch(0.45 0 0);
--accent: oklch(0.95 0 0);
--accent-foreground: oklch(0.15 0 0);
--destructive: oklch(0.5 0.2 25);
--border: oklch(0.9 0 0);
--border-glass: oklch(0.15 0 0 / 0.08);
--input: oklch(0.98 0 0);
--ring: oklch(0.3 0 0);
--chart-1: oklch(0.3 0 0);
--chart-2: oklch(0.5 0 0);
--chart-3: oklch(0.4 0 0);
--chart-4: oklch(0.6 0 0);
--chart-5: oklch(0.35 0 0);
--sidebar: oklch(0.98 0 0);
--sidebar-foreground: oklch(0.15 0 0);
--sidebar-primary: oklch(0.3 0 0);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.95 0 0);
--sidebar-accent-foreground: oklch(0.15 0 0);
--sidebar-border: oklch(0.9 0 0);
--sidebar-ring: oklch(0.3 0 0);
--action-view: oklch(0.3 0 0);
--action-view-hover: oklch(0.25 0 0);
--action-followup: oklch(0.4 0 0);
--action-followup-hover: oklch(0.35 0 0);
--action-commit: oklch(0.35 0.1 145);
--action-commit-hover: oklch(0.3 0.12 145);
--action-verify: oklch(0.35 0.1 145);
--action-verify-hover: oklch(0.3 0.12 145);
--running-indicator: oklch(0.3 0 0);
--running-indicator-text: oklch(0.25 0 0);
--status-success: oklch(0.4 0.15 145);
--status-success-bg: oklch(0.4 0.15 145 / 0.12);
--status-warning: oklch(0.55 0.15 70);
--status-warning-bg: oklch(0.55 0.15 70 / 0.12);
--status-error: oklch(0.5 0.2 25);
--status-error-bg: oklch(0.5 0.2 25 / 0.12);
--status-info: oklch(0.45 0.12 230);
--status-info-bg: oklch(0.45 0.12 230 / 0.12);
--status-backlog: oklch(0.55 0 0);
--status-in-progress: oklch(0.55 0.15 70);
--status-waiting: oklch(0.5 0.1 50);
}
.paper .content-bg {
background: linear-gradient(135deg, oklch(0.99 0 0), oklch(0.98 0 0), oklch(0.99 0 0));
}
.paper .animated-outline-gradient {
background: conic-gradient(
from 90deg at 50% 50%,
oklch(0.3 0 0) 0%,
oklch(0.5 0 0) 50%,
oklch(0.3 0 0) 100%
);
}
.paper .animated-outline-inner {
background: oklch(1 0 0) !important;
color: oklch(0.2 0 0) !important;
}

View File

@@ -0,0 +1,92 @@
/* Peach Theme - Soft peach/coral tones */
.peach {
--background: oklch(0.98 0.02 50);
--background-50: oklch(0.98 0.02 50 / 0.5);
--background-80: oklch(0.98 0.02 50 / 0.8);
--foreground: oklch(0.25 0.04 40);
--foreground-secondary: oklch(0.45 0.03 40);
--foreground-muted: oklch(0.55 0.03 40);
--card: oklch(0.99 0.015 50);
--card-foreground: oklch(0.25 0.04 40);
--popover: oklch(0.99 0.015 50);
--popover-foreground: oklch(0.25 0.04 40);
--primary: oklch(0.65 0.15 40);
--primary-foreground: oklch(0.99 0.015 50);
--brand-400: oklch(0.7 0.13 40);
--brand-500: oklch(0.65 0.15 40);
--brand-600: oklch(0.6 0.17 40);
--secondary: oklch(0.95 0.025 50);
--secondary-foreground: oklch(0.25 0.04 40);
--muted: oklch(0.94 0.028 50);
--muted-foreground: oklch(0.5 0.03 40);
--accent: oklch(0.92 0.032 50);
--accent-foreground: oklch(0.25 0.04 40);
--destructive: oklch(0.55 0.2 20);
--border: oklch(0.9 0.025 50);
--border-glass: oklch(0.65 0.15 40 / 0.15);
--input: oklch(0.98 0.018 50);
--ring: oklch(0.65 0.15 40);
--chart-1: oklch(0.65 0.15 40);
--chart-2: oklch(0.6 0.15 25);
--chart-3: oklch(0.6 0.12 70);
--chart-4: oklch(0.55 0.12 350);
--chart-5: oklch(0.55 0.1 100);
--sidebar: oklch(0.97 0.022 50);
--sidebar-foreground: oklch(0.25 0.04 40);
--sidebar-primary: oklch(0.65 0.15 40);
--sidebar-primary-foreground: oklch(0.99 0.015 50);
--sidebar-accent: oklch(0.94 0.028 50);
--sidebar-accent-foreground: oklch(0.25 0.04 40);
--sidebar-border: oklch(0.9 0.025 50);
--sidebar-ring: oklch(0.65 0.15 40);
--action-view: oklch(0.65 0.15 40);
--action-view-hover: oklch(0.6 0.17 40);
--action-followup: oklch(0.6 0.15 25);
--action-followup-hover: oklch(0.55 0.17 25);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.65 0.15 40);
--running-indicator-text: oklch(0.6 0.17 40);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 20);
--status-error-bg: oklch(0.55 0.2 20 / 0.15);
--status-info: oklch(0.55 0.12 230);
--status-info-bg: oklch(0.55 0.12 230 / 0.15);
--status-backlog: oklch(0.6 0.03 40);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.peach .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.02 50),
oklch(0.97 0.025 50),
oklch(0.98 0.02 50)
);
}
.peach .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #fb923c 0%, #f97316 50%, #fb923c 100%);
}
.peach .animated-outline-inner {
background: oklch(0.99 0.015 50) !important;
color: #f97316 !important;
}

View File

@@ -0,0 +1,92 @@
/* Rose Theme - Soft pink/rose tones */
.rose {
--background: oklch(0.98 0.01 350);
--background-50: oklch(0.98 0.01 350 / 0.5);
--background-80: oklch(0.98 0.01 350 / 0.8);
--foreground: oklch(0.25 0.03 350);
--foreground-secondary: oklch(0.45 0.03 350);
--foreground-muted: oklch(0.55 0.02 350);
--card: oklch(0.99 0.008 350);
--card-foreground: oklch(0.25 0.03 350);
--popover: oklch(0.99 0.008 350);
--popover-foreground: oklch(0.25 0.03 350);
--primary: oklch(0.6 0.18 350);
--primary-foreground: oklch(0.99 0.008 350);
--brand-400: oklch(0.65 0.16 350);
--brand-500: oklch(0.6 0.18 350);
--brand-600: oklch(0.55 0.2 350);
--secondary: oklch(0.95 0.015 350);
--secondary-foreground: oklch(0.25 0.03 350);
--muted: oklch(0.94 0.02 350);
--muted-foreground: oklch(0.5 0.03 350);
--accent: oklch(0.92 0.025 350);
--accent-foreground: oklch(0.25 0.03 350);
--destructive: oklch(0.55 0.2 15);
--border: oklch(0.9 0.02 350);
--border-glass: oklch(0.6 0.18 350 / 0.15);
--input: oklch(0.98 0.01 350);
--ring: oklch(0.6 0.18 350);
--chart-1: oklch(0.6 0.18 350);
--chart-2: oklch(0.65 0.15 320);
--chart-3: oklch(0.55 0.15 15);
--chart-4: oklch(0.6 0.15 280);
--chart-5: oklch(0.55 0.12 200);
--sidebar: oklch(0.97 0.012 350);
--sidebar-foreground: oklch(0.25 0.03 350);
--sidebar-primary: oklch(0.6 0.18 350);
--sidebar-primary-foreground: oklch(0.99 0.008 350);
--sidebar-accent: oklch(0.94 0.02 350);
--sidebar-accent-foreground: oklch(0.25 0.03 350);
--sidebar-border: oklch(0.9 0.02 350);
--sidebar-ring: oklch(0.6 0.18 350);
--action-view: oklch(0.6 0.18 350);
--action-view-hover: oklch(0.55 0.2 350);
--action-followup: oklch(0.6 0.15 320);
--action-followup-hover: oklch(0.55 0.17 320);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.6 0.18 350);
--running-indicator-text: oklch(0.55 0.2 350);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 15);
--status-error-bg: oklch(0.55 0.2 15 / 0.15);
--status-info: oklch(0.55 0.15 230);
--status-info-bg: oklch(0.55 0.15 230 / 0.15);
--status-backlog: oklch(0.6 0.02 350);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.rose .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.01 350),
oklch(0.97 0.015 350),
oklch(0.98 0.01 350)
);
}
.rose .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #f43f5e 0%, #ec4899 50%, #f43f5e 100%);
}
.rose .animated-outline-inner {
background: oklch(0.99 0.008 350) !important;
color: #f43f5e !important;
}

View File

@@ -0,0 +1,92 @@
/* Sand Theme - Sandy beige tones */
.sand {
--background: oklch(0.96 0.02 80);
--background-50: oklch(0.96 0.02 80 / 0.5);
--background-80: oklch(0.96 0.02 80 / 0.8);
--foreground: oklch(0.25 0.03 70);
--foreground-secondary: oklch(0.45 0.03 70);
--foreground-muted: oklch(0.55 0.02 70);
--card: oklch(0.98 0.015 80);
--card-foreground: oklch(0.25 0.03 70);
--popover: oklch(0.97 0.015 80);
--popover-foreground: oklch(0.25 0.03 70);
--primary: oklch(0.55 0.12 60);
--primary-foreground: oklch(0.98 0.015 80);
--brand-400: oklch(0.6 0.1 60);
--brand-500: oklch(0.55 0.12 60);
--brand-600: oklch(0.5 0.14 60);
--secondary: oklch(0.93 0.025 80);
--secondary-foreground: oklch(0.25 0.03 70);
--muted: oklch(0.92 0.028 80);
--muted-foreground: oklch(0.5 0.03 70);
--accent: oklch(0.9 0.03 80);
--accent-foreground: oklch(0.25 0.03 70);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.87 0.03 80);
--border-glass: oklch(0.55 0.12 60 / 0.15);
--input: oklch(0.97 0.018 80);
--ring: oklch(0.55 0.12 60);
--chart-1: oklch(0.55 0.12 60);
--chart-2: oklch(0.6 0.1 40);
--chart-3: oklch(0.55 0.1 100);
--chart-4: oklch(0.5 0.08 30);
--chart-5: oklch(0.55 0.08 120);
--sidebar: oklch(0.95 0.022 80);
--sidebar-foreground: oklch(0.25 0.03 70);
--sidebar-primary: oklch(0.55 0.12 60);
--sidebar-primary-foreground: oklch(0.98 0.015 80);
--sidebar-accent: oklch(0.92 0.028 80);
--sidebar-accent-foreground: oklch(0.25 0.03 70);
--sidebar-border: oklch(0.87 0.03 80);
--sidebar-ring: oklch(0.55 0.12 60);
--action-view: oklch(0.55 0.12 60);
--action-view-hover: oklch(0.5 0.14 60);
--action-followup: oklch(0.55 0.1 40);
--action-followup-hover: oklch(0.5 0.12 40);
--action-commit: oklch(0.55 0.12 130);
--action-commit-hover: oklch(0.5 0.14 130);
--action-verify: oklch(0.55 0.12 130);
--action-verify-hover: oklch(0.5 0.14 130);
--running-indicator: oklch(0.55 0.12 60);
--running-indicator-text: oklch(0.5 0.14 60);
--status-success: oklch(0.55 0.12 130);
--status-success-bg: oklch(0.55 0.12 130 / 0.15);
--status-warning: oklch(0.6 0.12 70);
--status-warning-bg: oklch(0.6 0.12 70 / 0.15);
--status-error: oklch(0.55 0.18 25);
--status-error-bg: oklch(0.55 0.18 25 / 0.15);
--status-info: oklch(0.5 0.12 230);
--status-info-bg: oklch(0.5 0.12 230 / 0.15);
--status-backlog: oklch(0.6 0.03 70);
--status-in-progress: oklch(0.6 0.12 70);
--status-waiting: oklch(0.58 0.1 55);
}
.sand .content-bg {
background: linear-gradient(
135deg,
oklch(0.96 0.02 80),
oklch(0.95 0.025 80),
oklch(0.96 0.02 80)
);
}
.sand .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #d97706 0%, #b45309 50%, #d97706 100%);
}
.sand .animated-outline-inner {
background: oklch(0.98 0.015 80) !important;
color: #d97706 !important;
}

View File

@@ -0,0 +1,92 @@
/* Sepia Theme - Warm sepia/parchment tones */
.sepia {
--background: oklch(0.95 0.025 70);
--background-50: oklch(0.95 0.025 70 / 0.5);
--background-80: oklch(0.95 0.025 70 / 0.8);
--foreground: oklch(0.25 0.04 50);
--foreground-secondary: oklch(0.45 0.03 50);
--foreground-muted: oklch(0.55 0.03 50);
--card: oklch(0.97 0.02 70);
--card-foreground: oklch(0.25 0.04 50);
--popover: oklch(0.96 0.022 70);
--popover-foreground: oklch(0.25 0.04 50);
--primary: oklch(0.5 0.12 50);
--primary-foreground: oklch(0.97 0.02 70);
--brand-400: oklch(0.55 0.1 50);
--brand-500: oklch(0.5 0.12 50);
--brand-600: oklch(0.45 0.14 50);
--secondary: oklch(0.92 0.028 70);
--secondary-foreground: oklch(0.25 0.04 50);
--muted: oklch(0.91 0.03 70);
--muted-foreground: oklch(0.5 0.03 50);
--accent: oklch(0.89 0.035 70);
--accent-foreground: oklch(0.25 0.04 50);
--destructive: oklch(0.55 0.18 25);
--border: oklch(0.86 0.035 70);
--border-glass: oklch(0.5 0.12 50 / 0.15);
--input: oklch(0.96 0.022 70);
--ring: oklch(0.5 0.12 50);
--chart-1: oklch(0.5 0.12 50);
--chart-2: oklch(0.55 0.1 35);
--chart-3: oklch(0.5 0.08 80);
--chart-4: oklch(0.45 0.1 30);
--chart-5: oklch(0.5 0.06 100);
--sidebar: oklch(0.94 0.026 70);
--sidebar-foreground: oklch(0.25 0.04 50);
--sidebar-primary: oklch(0.5 0.12 50);
--sidebar-primary-foreground: oklch(0.97 0.02 70);
--sidebar-accent: oklch(0.91 0.03 70);
--sidebar-accent-foreground: oklch(0.25 0.04 50);
--sidebar-border: oklch(0.86 0.035 70);
--sidebar-ring: oklch(0.5 0.12 50);
--action-view: oklch(0.5 0.12 50);
--action-view-hover: oklch(0.45 0.14 50);
--action-followup: oklch(0.5 0.1 35);
--action-followup-hover: oklch(0.45 0.12 35);
--action-commit: oklch(0.5 0.12 130);
--action-commit-hover: oklch(0.45 0.14 130);
--action-verify: oklch(0.5 0.12 130);
--action-verify-hover: oklch(0.45 0.14 130);
--running-indicator: oklch(0.5 0.12 50);
--running-indicator-text: oklch(0.45 0.14 50);
--status-success: oklch(0.5 0.12 130);
--status-success-bg: oklch(0.5 0.12 130 / 0.15);
--status-warning: oklch(0.58 0.12 70);
--status-warning-bg: oklch(0.58 0.12 70 / 0.15);
--status-error: oklch(0.55 0.18 25);
--status-error-bg: oklch(0.55 0.18 25 / 0.15);
--status-info: oklch(0.5 0.1 230);
--status-info-bg: oklch(0.5 0.1 230 / 0.15);
--status-backlog: oklch(0.58 0.03 50);
--status-in-progress: oklch(0.58 0.12 70);
--status-waiting: oklch(0.55 0.1 55);
}
.sepia .content-bg {
background: linear-gradient(
135deg,
oklch(0.95 0.025 70),
oklch(0.94 0.028 70),
oklch(0.95 0.025 70)
);
}
.sepia .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #92400e 0%, #a16207 50%, #92400e 100%);
}
.sepia .animated-outline-inner {
background: oklch(0.97 0.02 70) !important;
color: #92400e !important;
}

View File

@@ -0,0 +1,92 @@
/* Sky Theme - Light sky blue */
.sky {
--background: oklch(0.98 0.015 220);
--background-50: oklch(0.98 0.015 220 / 0.5);
--background-80: oklch(0.98 0.015 220 / 0.8);
--foreground: oklch(0.2 0.03 220);
--foreground-secondary: oklch(0.4 0.03 220);
--foreground-muted: oklch(0.55 0.02 220);
--card: oklch(0.99 0.01 220);
--card-foreground: oklch(0.2 0.03 220);
--popover: oklch(0.99 0.01 220);
--popover-foreground: oklch(0.2 0.03 220);
--primary: oklch(0.55 0.15 225);
--primary-foreground: oklch(0.99 0.01 220);
--brand-400: oklch(0.6 0.13 225);
--brand-500: oklch(0.55 0.15 225);
--brand-600: oklch(0.5 0.17 225);
--secondary: oklch(0.95 0.018 220);
--secondary-foreground: oklch(0.2 0.03 220);
--muted: oklch(0.94 0.02 220);
--muted-foreground: oklch(0.5 0.03 220);
--accent: oklch(0.92 0.025 220);
--accent-foreground: oklch(0.2 0.03 220);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.88 0.02 220);
--border-glass: oklch(0.55 0.15 225 / 0.15);
--input: oklch(0.98 0.012 220);
--ring: oklch(0.55 0.15 225);
--chart-1: oklch(0.55 0.15 225);
--chart-2: oklch(0.6 0.12 200);
--chart-3: oklch(0.55 0.15 250);
--chart-4: oklch(0.6 0.12 180);
--chart-5: oklch(0.55 0.1 270);
--sidebar: oklch(0.97 0.015 220);
--sidebar-foreground: oklch(0.2 0.03 220);
--sidebar-primary: oklch(0.55 0.15 225);
--sidebar-primary-foreground: oklch(0.99 0.01 220);
--sidebar-accent: oklch(0.94 0.02 220);
--sidebar-accent-foreground: oklch(0.2 0.03 220);
--sidebar-border: oklch(0.88 0.02 220);
--sidebar-ring: oklch(0.55 0.15 225);
--action-view: oklch(0.55 0.15 225);
--action-view-hover: oklch(0.5 0.17 225);
--action-followup: oklch(0.55 0.12 200);
--action-followup-hover: oklch(0.5 0.14 200);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.55 0.15 225);
--running-indicator-text: oklch(0.5 0.17 225);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.15);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.15);
--status-info: oklch(0.55 0.15 225);
--status-info-bg: oklch(0.55 0.15 225 / 0.15);
--status-backlog: oklch(0.6 0.02 220);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.sky .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.015 220),
oklch(0.97 0.018 220),
oklch(0.98 0.015 220)
);
}
.sky .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #0ea5e9 0%, #38bdf8 50%, #0ea5e9 100%);
}
.sky .animated-outline-inner {
background: oklch(0.99 0.01 220) !important;
color: #0ea5e9 !important;
}

View File

@@ -0,0 +1,92 @@
/* Snow Theme - Clean white with cool blue tints */
.snow {
--background: oklch(0.99 0.005 240);
--background-50: oklch(0.99 0.005 240 / 0.5);
--background-80: oklch(0.99 0.005 240 / 0.8);
--foreground: oklch(0.2 0.02 240);
--foreground-secondary: oklch(0.4 0.02 240);
--foreground-muted: oklch(0.55 0.015 240);
--card: oklch(1 0 0);
--card-foreground: oklch(0.2 0.02 240);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.2 0.02 240);
--primary: oklch(0.5 0.15 240);
--primary-foreground: oklch(1 0 0);
--brand-400: oklch(0.55 0.13 240);
--brand-500: oklch(0.5 0.15 240);
--brand-600: oklch(0.45 0.17 240);
--secondary: oklch(0.97 0.008 240);
--secondary-foreground: oklch(0.2 0.02 240);
--muted: oklch(0.96 0.01 240);
--muted-foreground: oklch(0.5 0.015 240);
--accent: oklch(0.95 0.012 240);
--accent-foreground: oklch(0.2 0.02 240);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.92 0.008 240);
--border-glass: oklch(0.5 0.15 240 / 0.1);
--input: oklch(0.98 0.005 240);
--ring: oklch(0.5 0.15 240);
--chart-1: oklch(0.5 0.15 240);
--chart-2: oklch(0.55 0.12 200);
--chart-3: oklch(0.5 0.15 280);
--chart-4: oklch(0.55 0.12 180);
--chart-5: oklch(0.5 0.1 260);
--sidebar: oklch(0.98 0.006 240);
--sidebar-foreground: oklch(0.2 0.02 240);
--sidebar-primary: oklch(0.5 0.15 240);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.96 0.01 240);
--sidebar-accent-foreground: oklch(0.2 0.02 240);
--sidebar-border: oklch(0.92 0.008 240);
--sidebar-ring: oklch(0.5 0.15 240);
--action-view: oklch(0.5 0.15 240);
--action-view-hover: oklch(0.45 0.17 240);
--action-followup: oklch(0.5 0.12 200);
--action-followup-hover: oklch(0.45 0.14 200);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.5 0.15 240);
--running-indicator-text: oklch(0.45 0.17 240);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.12);
--status-warning: oklch(0.65 0.15 70);
--status-warning-bg: oklch(0.65 0.15 70 / 0.12);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.12);
--status-info: oklch(0.5 0.15 240);
--status-info-bg: oklch(0.5 0.15 240 / 0.12);
--status-backlog: oklch(0.6 0.015 240);
--status-in-progress: oklch(0.65 0.15 70);
--status-waiting: oklch(0.6 0.12 50);
}
.snow .content-bg {
background: linear-gradient(
135deg,
oklch(0.99 0.005 240),
oklch(0.98 0.008 240),
oklch(0.99 0.005 240)
);
}
.snow .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #6366f1 0%, #8b5cf6 50%, #6366f1 100%);
}
.snow .animated-outline-inner {
background: oklch(1 0 0) !important;
color: #6366f1 !important;
}

View File

@@ -0,0 +1,92 @@
/* Solarized Light Theme */
.solarizedlight {
--background: oklch(0.98 0.01 90);
--background-50: oklch(0.98 0.01 90 / 0.5);
--background-80: oklch(0.98 0.01 90 / 0.8);
--foreground: oklch(0.35 0.05 200);
--foreground-secondary: oklch(0.5 0.05 200);
--foreground-muted: oklch(0.6 0.04 200);
--card: oklch(0.95 0.01 90);
--card-foreground: oklch(0.35 0.05 200);
--popover: oklch(0.96 0.01 90);
--popover-foreground: oklch(0.35 0.05 200);
--primary: oklch(0.55 0.15 230);
--primary-foreground: oklch(0.98 0.01 90);
--brand-400: oklch(0.6 0.13 230);
--brand-500: oklch(0.55 0.15 230);
--brand-600: oklch(0.5 0.17 230);
--secondary: oklch(0.92 0.01 90);
--secondary-foreground: oklch(0.35 0.05 200);
--muted: oklch(0.93 0.01 90);
--muted-foreground: oklch(0.5 0.04 200);
--accent: oklch(0.9 0.02 90);
--accent-foreground: oklch(0.35 0.05 200);
--destructive: oklch(0.55 0.2 25);
--border: oklch(0.88 0.015 90);
--border-glass: oklch(0.35 0.05 200 / 0.1);
--input: oklch(0.97 0.008 90);
--ring: oklch(0.55 0.15 230);
--chart-1: oklch(0.55 0.15 230);
--chart-2: oklch(0.6 0.18 25);
--chart-3: oklch(0.55 0.15 300);
--chart-4: oklch(0.6 0.15 180);
--chart-5: oklch(0.65 0.12 80);
--sidebar: oklch(0.96 0.01 90);
--sidebar-foreground: oklch(0.35 0.05 200);
--sidebar-primary: oklch(0.55 0.15 230);
--sidebar-primary-foreground: oklch(0.98 0.01 90);
--sidebar-accent: oklch(0.92 0.01 90);
--sidebar-accent-foreground: oklch(0.35 0.05 200);
--sidebar-border: oklch(0.88 0.015 90);
--sidebar-ring: oklch(0.55 0.15 230);
--action-view: oklch(0.55 0.15 230);
--action-view-hover: oklch(0.5 0.17 230);
--action-followup: oklch(0.6 0.18 25);
--action-followup-hover: oklch(0.55 0.2 25);
--action-commit: oklch(0.55 0.15 145);
--action-commit-hover: oklch(0.5 0.17 145);
--action-verify: oklch(0.55 0.15 145);
--action-verify-hover: oklch(0.5 0.17 145);
--running-indicator: oklch(0.55 0.15 230);
--running-indicator-text: oklch(0.5 0.17 230);
--status-success: oklch(0.55 0.15 145);
--status-success-bg: oklch(0.55 0.15 145 / 0.15);
--status-warning: oklch(0.65 0.15 80);
--status-warning-bg: oklch(0.65 0.15 80 / 0.15);
--status-error: oklch(0.55 0.2 25);
--status-error-bg: oklch(0.55 0.2 25 / 0.15);
--status-info: oklch(0.55 0.15 230);
--status-info-bg: oklch(0.55 0.15 230 / 0.15);
--status-backlog: oklch(0.6 0.04 200);
--status-in-progress: oklch(0.65 0.15 80);
--status-waiting: oklch(0.6 0.12 50);
}
.solarizedlight .content-bg {
background: linear-gradient(
135deg,
oklch(0.98 0.01 90),
oklch(0.96 0.012 90),
oklch(0.98 0.01 90)
);
}
.solarizedlight .animated-outline-gradient {
background: conic-gradient(from 90deg at 50% 50%, #268bd2 0%, #2aa198 50%, #268bd2 100%);
}
.solarizedlight .animated-outline-inner {
background: oklch(0.98 0.01 90) !important;
color: #268bd2 !important;
}