From a4049971e5f0bbf7f8200e9fcb86cc19225caeda Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Wed, 1 Jul 2026 18:01:17 -0700 Subject: [PATCH] FN-7401: add Glass Silver dashboard theme Adds a frosted silver/gray dashboard color theme across app, desktop, and release metadata. - Register glass-silver in shared theme types, selector options, and startup validation hooks. - Add Glass Silver CSS tokens, swatch styling, and dashboard/desktop stylesheet preload coverage. - Cover theme registration, dropdown/selector rendering, theme persistence, and CSS token invariants with tests. - Document the new dashboard theme and publish a minor changeset for @runfusion/fusion. Files changed: .changeset/fn-7401-glass-silver-theme.md | 7 + docs/dashboard-guide.md | 3 +- packages/core/src/types.ts | 2 + .../app/__tests__/glass-silver-theme.test.ts | 155 ++++++++++++++++++++ .../dashboard/app/components/ThemeSelector.css | 14 ++ .../components/__tests__/ThemeDropdown.test.tsx | 13 ++ .../components/__tests__/ThemeSelector.test.tsx | 16 +++ packages/dashboard/app/components/themeOptions.ts | 1 + .../dashboard/app/hooks/__tests__/useTheme.test.ts | 15 ++ packages/dashboard/app/index.html | 2 +- packages/dashboard/app/public/theme-data.css | 156 +++++++++++++++++++++ packages/desktop/src/renderer/index.html | 1 + 12 files changed, 383 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7401 Fusion-Task-Lineage: e64f14cc-590e-458b-adf6-7c9baa488157 Co-authored-by: Fusion (runfusion.ai) --- .changeset/fn-7401-glass-silver-theme.md | 7 + docs/dashboard-guide.md | 3 +- packages/core/src/types.ts | 2 + .../app/__tests__/glass-silver-theme.test.ts | 155 +++++++++++++++++ .../app/components/ThemeSelector.css | 14 ++ .../__tests__/ThemeDropdown.test.tsx | 13 ++ .../__tests__/ThemeSelector.test.tsx | 16 ++ .../dashboard/app/components/themeOptions.ts | 1 + .../app/hooks/__tests__/useTheme.test.ts | 15 ++ packages/dashboard/app/index.html | 2 +- packages/dashboard/app/public/theme-data.css | 156 ++++++++++++++++++ packages/desktop/src/renderer/index.html | 1 + 12 files changed, 383 insertions(+), 2 deletions(-) create mode 100644 .changeset/fn-7401-glass-silver-theme.md create mode 100644 packages/dashboard/app/__tests__/glass-silver-theme.test.ts diff --git a/.changeset/fn-7401-glass-silver-theme.md b/.changeset/fn-7401-glass-silver-theme.md new file mode 100644 index 0000000000..5b5d751d5c --- /dev/null +++ b/.changeset/fn-7401-glass-silver-theme.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": minor +--- + +summary: Add a Glass Silver dashboard theme. +category: feature +dev: Registers glass-silver across core theme metadata, dashboard/desktop startup validators, CSS tokens, swatches, and tests. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 634e829f48..f131feae1d 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -1584,8 +1584,9 @@ Non-Command-Center dashboard CSS uses `--text` as the canonical primary text tok ### Theme system + -Dark/light modes via `data-theme`; 75 color themes via `data-color-theme` (lazy-loaded from `app/public/theme-data.css`), including the Shadcn zinc-neutral theme with an orange default highlight/accent, Shadcn Custom (the same base with sanitized per-token color-picker overrides), and its color family: Shadcn Blue/Green/Red/Purple/Pink/Orange/Yellow, Shadcn Mono Red/Blue/Green/Purple/Pink/Orange/Yellow (grayscale surfaces with color-specific accents; legacy `shadcn-mono` selections migrate to Shadcn Mono Red), Shadcn Black (pure black and white), Shadcn Gray (fully neutral zinc-gray accent), and Shadcn Gray Blue (blue-gray slate neutral surfaces with a muted slate-blue accent). Air is the minimal, borderless, paper-like preset with near-monochrome tokens and CSS-only chrome flattening. +Dark/light modes via `data-theme`; 76 color themes via `data-color-theme` (lazy-loaded from `app/public/theme-data.css`), including the Shadcn zinc-neutral theme with an orange default highlight/accent, Shadcn Custom (the same base with sanitized per-token color-picker overrides), and its color family: Shadcn Blue/Green/Red/Purple/Pink/Orange/Yellow, Shadcn Mono Red/Blue/Green/Purple/Pink/Orange/Yellow (grayscale surfaces with color-specific accents; legacy `shadcn-mono` selections migrate to Shadcn Mono Red), Shadcn Black (pure black and white), Shadcn Gray (fully neutral zinc-gray accent), and Shadcn Gray Blue (blue-gray slate neutral surfaces with a muted slate-blue accent). Air is the minimal, borderless, paper-like preset with near-monochrome tokens and CSS-only chrome flattening. Glass Silver preserves the Glass theme's frosted translucent surfaces and transparent modal overlay behavior while using silver and graphite accents instead of purple/pink. Choose Shadcn variants from **Settings → Appearance** or from the Command Center **Overview** theme card; both selectors use the same `themeOptions.ts` labels and color-chip swatches. The left sidebar active-item highlight and resize accent use the active theme's `--accent`, so they follow the selected Shadcn accent instead of staying fixed blue. diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index e4053203ac..dba2fa19c1 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -313,6 +313,8 @@ export const COLOR_THEMES = [ "parchment", "terminal", "glass", + // FNXC:DashboardTheming 2026-07-01-00:00: Glass Silver is the silver/gray frosted sibling of Glass; keep this id in lockstep with dashboard/desktop validators and selector metadata so persisted explicit choices survive startup. + "glass-silver", "horizon", "vitesse", "outrun", diff --git a/packages/dashboard/app/__tests__/glass-silver-theme.test.ts b/packages/dashboard/app/__tests__/glass-silver-theme.test.ts new file mode 100644 index 0000000000..1d3b735880 --- /dev/null +++ b/packages/dashboard/app/__tests__/glass-silver-theme.test.ts @@ -0,0 +1,155 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; +import { COLOR_THEMES as CORE_COLOR_THEMES } from "@fusion/core"; +import { COLOR_THEMES as DASHBOARD_COLOR_THEMES } from "../components/themeOptions"; + +const themeDataPath = path.resolve(__dirname, "../public/theme-data.css"); +const dashboardIndexPath = path.resolve(__dirname, "../index.html"); +const desktopIndexPath = path.resolve(__dirname, "../../../desktop/src/renderer/index.html"); + +/* +FNXC:DashboardTheming 2026-07-01-00:00: +Glass Silver is a first-class color theme, so this contract keeps the core union, selector metadata, dashboard/desktop pre-hydration validators, and frosted CSS blocks synchronized. +*/ +describe("Glass Silver color theme", () => { + const themeData = readFileSync(themeDataPath, "utf-8"); + const dashboardIndexHtml = readFileSync(dashboardIndexPath, "utf-8"); + const desktopIndexHtml = readFileSync(desktopIndexPath, "utf-8"); + + it("registers the theme in core, dashboard metadata, and both bootstrap validators without duplicates", () => { + expect(CORE_COLOR_THEMES).toContain("glass-silver"); + expect(DASHBOARD_COLOR_THEMES).toContainEqual({ + value: "glass-silver", + label: "Glass Silver", + className: "theme-swatch-glass-silver", + }); + expect(DASHBOARD_COLOR_THEMES.map((theme) => theme.value)).toEqual([...CORE_COLOR_THEMES]); + + const coreIds = [...CORE_COLOR_THEMES]; + expect(new Set(coreIds).size).toBe(coreIds.length); + + const dashboardValidThemes = extractValidThemes(dashboardIndexHtml); + const desktopValidThemes = extractValidThemes(desktopIndexHtml); + expect(dashboardValidThemes).toEqual(coreIds); + expect(desktopValidThemes).toEqual(coreIds); + expect(new Set(dashboardValidThemes).size).toBe(dashboardValidThemes.length); + expect(new Set(desktopValidThemes).size).toBe(desktopValidThemes.length); + expect(dashboardIndexHtml).toContain("colorTheme = 'shadcn-ember'"); + expect(desktopIndexHtml).toContain('colorTheme = "shadcn-ember"'); + }); + + it("defines dark and light frosted silver/gray token blocks", () => { + const darkBlock = extractSelectorBlock(themeData, '[data-color-theme="glass-silver"]'); + const lightBlock = extractSelectorBlock(themeData, '[data-color-theme="glass-silver"][data-theme="light"]'); + const combined = `${darkBlock}\n${lightBlock}`; + + for (const block of [darkBlock, lightBlock]) { + expect(block).toContain("--surface-hover:"); + expect(block).toContain("--surface: color-mix(in srgb,"); + expect(block).toContain("--card: color-mix(in srgb,"); + expect(block).toContain("transparent);"); + expect(block).toContain("--cta-bg:"); + expect(block).toContain("--cta-border:"); + expect(block).toContain("--cta-text:"); + expect(block).toContain("--accent:"); + expect(block).toContain("--accent-text:"); + expect(block).toContain("--color-info:"); + expect(block).toContain("--shadow-glow:"); + expect(block).toContain("--focus-ring:"); + } + + expect(darkBlock).toContain("--font-primary:"); + expect(darkBlock).toContain("--radius:"); + expect(darkBlock).toContain("--bg: #101216;"); + expect(darkBlock).toContain("--accent: #d7dde6;"); + expect(darkBlock).toContain("--accent-text: #111318;"); + expect(lightBlock).toContain("--bg: #eef0f3;"); + expect(lightBlock).toContain("--accent: #5f6875;"); + expect(lightBlock).toContain("--accent-text: #ffffff;"); + expect(combined).not.toContain("#c86bff"); + expect(combined).not.toContain("#ff7aa8"); + expect(combined).not.toContain("#9d40cf"); + expect(combined).not.toContain("#c74b7a"); + }); + + it("mirrors Glass frosted component overrides and transparent modal overlays", () => { + const cardBlock = extractGroupedRuleBlock(themeData, '[data-color-theme="glass-silver"] .card,'); + const lightCardBlock = extractGroupedRuleBlock(themeData, '[data-color-theme="glass-silver"][data-theme="light"] .card,'); + const buttonBlock = extractSelectorBlock(themeData, '[data-color-theme="glass-silver"] .btn'); + const primaryBlock = extractGroupedRuleBlock(themeData, '[data-color-theme="glass-silver"] .btn-primary,'); + const hoverBlock = extractGroupedRuleBlock(themeData, '[data-color-theme="glass-silver"] .btn-primary:hover,'); + const lightButtonBlock = extractSelectorBlock(themeData, '[data-color-theme="glass-silver"][data-theme="light"] .btn'); + const overlayBlock = extractSelectorBlock(themeData, '[data-color-theme="glass-silver"] .modal-overlay'); + + for (const block of [cardBlock, buttonBlock]) { + expect(block).toContain("backdrop-filter: blur("); + expect(block).toContain("-webkit-backdrop-filter: blur("); + expect(block).toContain("color-mix(in srgb,"); + expect(block).toContain("transparent);"); + } + expect(lightCardBlock).toContain("color-mix(in srgb,"); + expect(lightCardBlock).toContain("transparent);"); + expect(primaryBlock).toContain("linear-gradient(135deg"); + expect(primaryBlock).toContain("#d7dde6"); + expect(hoverBlock).toContain("linear-gradient(135deg"); + expect(hoverBlock).toContain("box-shadow:"); + expect(lightButtonBlock).toContain("color-mix(in srgb, #ffffff 52%, transparent)"); + expect(overlayBlock).toContain("background: transparent;"); + expect(overlayBlock).toContain("backdrop-filter: none;"); + expect(overlayBlock).toContain("-webkit-backdrop-filter: none;"); + expect(overlayBlock).not.toContain("blur("); + }); +}); + +function extractValidThemes(html: string): string[] { + const match = html.match(/var validThemes = \[([\s\S]*?)\];/); + if (!match) { + throw new Error("Could not find pre-hydration validThemes array"); + } + + return [...match[1].matchAll(/["']([^"']+)["']/g)].map((themeMatch) => themeMatch[1]); +} + +function extractSelectorBlock(css: string, selector: string): string { + const startIdx = css.indexOf(`${selector} {`); + if (startIdx === -1) { + throw new Error(`Could not find selector block: ${selector}`); + } + + const openBraceIdx = css.indexOf("{", startIdx); + let depth = 1; + let end = openBraceIdx; + for (let i = openBraceIdx + 1; i < css.length; i++) { + if (css[i] === "{") depth++; + if (css[i] === "}") depth--; + if (depth === 0) { + end = i; + break; + } + } + + return css.slice(startIdx, end + 1); +} + +function extractGroupedRuleBlock(css: string, selector: string): string { + const selectorIdx = css.indexOf(selector); + if (selectorIdx === -1) { + throw new Error(`Could not find selector in grouped block: ${selector}`); + } + + const openBraceIdx = css.indexOf("{", selectorIdx); + let depth = 1; + let end = openBraceIdx; + for (let i = openBraceIdx + 1; i < css.length; i++) { + if (css[i] === "{") depth++; + if (css[i] === "}") depth--; + if (depth === 0) { + end = i; + break; + } + } + + const priorCloseIdx = css.lastIndexOf("}", selectorIdx); + return css.slice(priorCloseIdx + 1, end + 1); +} diff --git a/packages/dashboard/app/components/ThemeSelector.css b/packages/dashboard/app/components/ThemeSelector.css index 90e5a12ff0..eee92e2b7d 100644 --- a/packages/dashboard/app/components/ThemeSelector.css +++ b/packages/dashboard/app/components/ThemeSelector.css @@ -665,6 +665,13 @@ --swatch-sample-4: #ff7aa8; } +.theme-swatch-glass-silver { + --swatch-sample-1: #101216; + --swatch-sample-2: color-mix(in srgb, #252a32 78%, transparent); + --swatch-sample-3: #d7dde6; + --swatch-sample-4: #9ca6b4; +} + .theme-swatch-horizon { --swatch-sample-1: #1c1e26; --swatch-sample-2: #16161c; @@ -1024,6 +1031,13 @@ --swatch-sample-4: #c74b7a; } +[data-theme="light"] .theme-swatch-glass-silver { + --swatch-sample-1: #eef0f3; + --swatch-sample-2: color-mix(in srgb, #ffffff 75%, transparent); + --swatch-sample-3: #5f6875; + --swatch-sample-4: #747f8c; +} + [data-theme="light"] .theme-swatch-slate { --swatch-sample-1: #f1f5f9; --swatch-sample-2: #e2e8f0; diff --git a/packages/dashboard/app/components/__tests__/ThemeDropdown.test.tsx b/packages/dashboard/app/components/__tests__/ThemeDropdown.test.tsx index a95ef71f60..69ea515655 100644 --- a/packages/dashboard/app/components/__tests__/ThemeDropdown.test.tsx +++ b/packages/dashboard/app/components/__tests__/ThemeDropdown.test.tsx @@ -41,6 +41,19 @@ describe("ThemeDropdown", () => { expect(defaultOptions[0]).toHaveTextContent("Shadcn Ember (Default)"); }); + it("renders Glass Silver as a non-empty compact dropdown option", () => { + render(); + + const trigger = screen.getByRole("button", { name: /glass silver/i }); + expect(trigger).toHaveTextContent("Glass Silver"); + expect(trigger.querySelector(".theme-swatch-glass-silver")).toBeTruthy(); + + fireEvent.click(trigger); + const glassSilverOption = screen.getByRole("option", { name: /glass silver/i }); + expect(glassSilverOption).toHaveTextContent("Glass Silver"); + expect(glassSilverOption.querySelector(".theme-swatch-glass-silver")).toBeTruthy(); + }); + it("selects themes and closes from click, escape, and outside click", () => { const onColorThemeChange = vi.fn(); render(); diff --git a/packages/dashboard/app/components/__tests__/ThemeSelector.test.tsx b/packages/dashboard/app/components/__tests__/ThemeSelector.test.tsx index 9ff4c09179..86fa9e83c6 100644 --- a/packages/dashboard/app/components/__tests__/ThemeSelector.test.tsx +++ b/packages/dashboard/app/components/__tests__/ThemeSelector.test.tsx @@ -132,6 +132,22 @@ describe("ThemeSelector", () => { expect(THEME_OPTIONS.map((theme) => theme.value)).toEqual([...COLOR_THEMES]); }); + it("renders the Glass Silver affordance with a non-empty label and swatch", () => { + render( + + ); + + const option = screen.getByLabelText("Glass Silver theme"); + expect(option).toHaveTextContent("Glass Silver"); + expect(option.querySelector(".theme-swatch-glass-silver")).toBeTruthy(); + expect(option.getAttribute("aria-pressed")).toBe("true"); + }); + it("marks current color theme as active", () => { render( { expect(document.documentElement.getAttribute("data-color-theme")).toBe("shadcn-mono-red"); }); + it("preserves explicit Glass and Glass Silver color themes from localStorage", () => { + localStorageMock[COLOR_THEME_STORAGE_KEY] = "glass-silver"; + + const { result, rerender } = renderHook(() => useTheme()); + + expect(result.current.colorTheme).toBe("glass-silver"); + expect(document.documentElement.getAttribute("data-color-theme")).toBe("glass-silver"); + + act(() => result.current.setColorTheme("glass")); + rerender(); + + expect(result.current.colorTheme).toBe("glass"); + expect(document.documentElement.getAttribute("data-color-theme")).toBe("glass"); + }); + it("ignores invalid color theme in localStorage", () => { localStorageMock[COLOR_THEME_STORAGE_KEY] = "invalid-theme"; diff --git a/packages/dashboard/app/index.html b/packages/dashboard/app/index.html index 2ce1918364..06365b177a 100644 --- a/packages/dashboard/app/index.html +++ b/packages/dashboard/app/index.html @@ -160,7 +160,7 @@ try { var mode = localStorage.getItem('kb-dashboard-theme-mode') || 'dark'; var colorTheme = localStorage.getItem('kb-dashboard-color-theme') || 'shadcn-ember'; - var validThemes = ['default', 'ocean', 'forest', 'sunset', 'zen', 'berry', 'high-contrast', 'industrial', 'monochrome', 'slate', 'ash', 'air', 'graphite', 'silver', 'solarized', 'factory', 'factory-mono', 'ayu', 'one-dark', 'nord', 'dracula', 'gruvbox', 'tokyo-night', 'catppuccin-mocha', 'github-dark', 'everforest', 'rose-pine', 'kanagawa', 'night-owl', 'palenight', 'monokai-pro', 'slime', 'brutalist', 'neon-city', 'parchment', 'terminal', 'glass', 'horizon', 'vitesse', 'outrun', 'snazzy', 'porple', 'espresso', 'mars', 'poimandres', 'ember', 'rust', 'copper', 'foundry', 'carbon', 'sandstone', 'lagoon', 'frost', 'lavender', 'neon-bloom', 'sepia', 'shadcn', 'shadcn-ember', 'shadcn-custom', 'shadcn-blue', 'shadcn-green', 'shadcn-red', 'shadcn-purple', 'shadcn-pink', 'shadcn-orange', 'shadcn-yellow', 'shadcn-mono-red', 'shadcn-mono-blue', 'shadcn-mono-green', 'shadcn-mono-purple', 'shadcn-mono-pink', 'shadcn-mono-orange', 'shadcn-mono-yellow', 'shadcn-black', 'shadcn-gray', 'shadcn-gray-blue']; + var validThemes = ['default', 'ocean', 'forest', 'sunset', 'zen', 'berry', 'high-contrast', 'industrial', 'monochrome', 'slate', 'ash', 'air', 'graphite', 'silver', 'solarized', 'factory', 'factory-mono', 'ayu', 'one-dark', 'nord', 'dracula', 'gruvbox', 'tokyo-night', 'catppuccin-mocha', 'github-dark', 'everforest', 'rose-pine', 'kanagawa', 'night-owl', 'palenight', 'monokai-pro', 'slime', 'brutalist', 'neon-city', 'parchment', 'terminal', 'glass', 'glass-silver', 'horizon', 'vitesse', 'outrun', 'snazzy', 'porple', 'espresso', 'mars', 'poimandres', 'ember', 'rust', 'copper', 'foundry', 'carbon', 'sandstone', 'lagoon', 'frost', 'lavender', 'neon-bloom', 'sepia', 'shadcn', 'shadcn-ember', 'shadcn-custom', 'shadcn-blue', 'shadcn-green', 'shadcn-red', 'shadcn-purple', 'shadcn-pink', 'shadcn-orange', 'shadcn-yellow', 'shadcn-mono-red', 'shadcn-mono-blue', 'shadcn-mono-green', 'shadcn-mono-purple', 'shadcn-mono-pink', 'shadcn-mono-orange', 'shadcn-mono-yellow', 'shadcn-black', 'shadcn-gray', 'shadcn-gray-blue']; // FNXC:DashboardTheming 2026-06-30-00:00: Unset startup theme is Shadcn Ember; explicit stored legacy ids such as "default" and "ocean" remain valid and must not be migrated. // FNXC:DashboardTheming 2026-06-20-00:00: FN-6813 remaps the legacy mono id before pre-hydration validation so persisted users keep the red mono accent. if (colorTheme === 'shadcn-mono') colorTheme = 'shadcn-mono-red'; diff --git a/packages/dashboard/app/public/theme-data.css b/packages/dashboard/app/public/theme-data.css index be7af00bcf..0d057d18d7 100644 --- a/packages/dashboard/app/public/theme-data.css +++ b/packages/dashboard/app/public/theme-data.css @@ -5795,6 +5795,162 @@ body[data-color-theme="terminal"][data-theme="light"]::before { -webkit-backdrop-filter: none; } + +/* GLASS SILVER - Frosted translucent silver/gray surfaces */ +[data-color-theme="glass-silver"] { + /* + FNXC:DashboardTheming 2026-07-01-00:00: + Glass Silver must preserve the same frosted, translucent surface contract as Glass while replacing the purple/pink accents with silver and graphite tones across dark and light modes. + */ + --bg: #101216; + --surface: color-mix(in srgb, #252a32 78%, transparent); + --card: color-mix(in srgb, #3a414c 55%, transparent); + --card-hover: color-mix(in srgb, #49515d 65%, transparent); + --surface-hover: color-mix(in srgb, var(--surface) 90%, var(--text) 10%); + --border: color-mix(in srgb, #f5f7fa 22%, transparent); + --text: #f3f4f6; + --text-muted: #c5cad3; + --text-dim: #8f97a3; + + --todo: #d7dde6; + --in-progress: #b9c2cf; + --in-progress-rgb: 185, 194, 207; + --in-review: #a7b4c2; + --triage: #c7b88f; + --done: #8f97a3; + --color-success: #a7b4c2; + --color-error: #ef8f8f; + + --font-primary: "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-mono: "SF Mono", "JetBrains Mono", "Menlo", monospace; + + --space-xs: 5px; + --space-sm: 10px; + --space-md: 14px; + --space-lg: 20px; + --space-xl: 28px; + --space-2xl: 38px; + + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 20px; + --radius-xl: 26px; + --radius-pill: 999px; + --radius: var(--radius-md); + + --btn-padding: 9px 16px; + --btn-border-width: 1px; + --card-padding: 12px 14px; + --modal-padding: var(--space-lg) var(--space-xl); + + --shadow-sm: 0 8px 16px color-mix(in srgb, #020305 24%, transparent); + --shadow-md: 0 14px 30px color-mix(in srgb, #030407 30%, transparent); + --shadow-lg: 0 22px 42px color-mix(in srgb, #04060a 35%, transparent); + --shadow-glow: 0 0 12px color-mix(in srgb, var(--todo) 22%, transparent); + --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent); + --focus-ring-strong: 0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent); + --shadow: var(--shadow-lg); + + --transition-instant: 0.08s ease; + --transition-fast: 0.14s ease; + --transition-normal: 0.22s ease; + --transition-slow: 0.34s ease; + + --cta-bg: color-mix(in srgb, var(--accent) 32%, transparent); + --cta-border: color-mix(in srgb, #f5f7fa 38%, transparent); + --cta-text: #f7f8fa; + --cta-bg-hover: color-mix(in srgb, var(--accent) 46%, transparent); + --cta-border-hover: color-mix(in srgb, #f5f7fa 50%, transparent); + --cta-glow: 0 0 12px color-mix(in srgb, var(--accent) 24%, transparent); + --logo-accent: var(--todo); + --color-info: #b9c2cf; + --accent: #d7dde6; + --accent-text: #111318; +} + +[data-color-theme="glass-silver"][data-theme="light"] { + --bg: #eef0f3; + --surface: color-mix(in srgb, #ffffff 75%, transparent); + --card: color-mix(in srgb, #ffffff 60%, transparent); + --card-hover: color-mix(in srgb, #ffffff 75%, transparent); + --surface-hover: color-mix(in srgb, var(--surface) 92%, var(--text) 8%); + --border: color-mix(in srgb, #5d6673 22%, transparent); + --text: #252a31; + --text-muted: #58616d; + --text-dim: #8a929d; + + --todo: #5f6875; + --in-progress: #747f8c; + --in-progress-rgb: 116, 127, 140; + --in-review: #667383; + --triage: #907d53; + --done: #8a929d; + --color-success: #667383; + --color-error: #b24f4f; + + --shadow-sm: 0 8px 16px color-mix(in srgb, #1f2933 8%, transparent); + --shadow-md: 0 14px 30px color-mix(in srgb, #1f2933 10%, transparent); + --shadow-lg: 0 22px 42px color-mix(in srgb, #1f2933 14%, transparent); + --shadow-glow: 0 0 10px color-mix(in srgb, var(--todo) 20%, transparent); + --focus-ring: 0 0 0 2px color-mix(in srgb, var(--accent) 15%, transparent); + --focus-ring-strong: 0 0 0 2px color-mix(in srgb, var(--accent) 24%, transparent); + + --cta-bg: color-mix(in srgb, var(--accent) 24%, transparent); + --cta-border: color-mix(in srgb, var(--accent) 38%, transparent); + --cta-text: #252a31; + --cta-bg-hover: color-mix(in srgb, var(--accent) 34%, transparent); + --cta-border-hover: color-mix(in srgb, var(--accent) 48%, transparent); + --cta-glow: 0 0 10px color-mix(in srgb, var(--accent) 22%, transparent); + --logo-accent: var(--todo); + --color-info: #747f8c; + --accent: #5f6875; + --accent-text: #ffffff; +} + +[data-color-theme="glass-silver"] .card, +[data-color-theme="glass-silver"] .column { + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + background: color-mix(in srgb, #f5f7fa 8%, transparent); + border-color: color-mix(in srgb, #f5f7fa 24%, transparent); +} + +[data-color-theme="glass-silver"][data-theme="light"] .card, +[data-color-theme="glass-silver"][data-theme="light"] .column { + background: color-mix(in srgb, #ffffff 60%, transparent); + border-color: color-mix(in srgb, #5d6673 24%, transparent); +} + +[data-color-theme="glass-silver"] .btn { + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-color: color-mix(in srgb, #f5f7fa 34%, transparent); + background: color-mix(in srgb, #f5f7fa 10%, transparent); +} + +[data-color-theme="glass-silver"] .btn-primary, +[data-color-theme="glass-silver"] .btn-task-create { + background: linear-gradient(135deg, color-mix(in srgb, #d7dde6 35%, transparent), color-mix(in srgb, #9ca6b4 30%, transparent)); + border-color: color-mix(in srgb, #f5f7fa 42%, transparent); +} + +[data-color-theme="glass-silver"] .btn-primary:hover, +[data-color-theme="glass-silver"] .btn-task-create:hover { + background: linear-gradient(135deg, color-mix(in srgb, #d7dde6 50%, transparent), color-mix(in srgb, #9ca6b4 42%, transparent)); + box-shadow: 0 12px 24px color-mix(in srgb, #030407 28%, transparent); +} + +[data-color-theme="glass-silver"][data-theme="light"] .btn { + background: color-mix(in srgb, #ffffff 52%, transparent); + border-color: color-mix(in srgb, #5d6673 28%, transparent); +} + +[data-color-theme="glass-silver"] .modal-overlay { + background: transparent; + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + /* HORIZON - Warm sunset-inspired palette */ [data-color-theme="horizon"] { --bg: #1c1e26; diff --git a/packages/desktop/src/renderer/index.html b/packages/desktop/src/renderer/index.html index 2872f5be34..855a6b5495 100644 --- a/packages/desktop/src/renderer/index.html +++ b/packages/desktop/src/renderer/index.html @@ -48,6 +48,7 @@ "parchment", "terminal", "glass", + "glass-silver", "horizon", "vitesse", "outrun",