332 lines
16 KiB
CSS
Executable File
332 lines
16 KiB
CSS
Executable File
/* ============================================================================
|
|
Frosty design tokens (canonical) - revision ds-r2
|
|
----------------------------------------------------------------------------
|
|
Product: Frosty Control Plane, the control plane for a Deno-native LLM
|
|
gateway. Dark is the default theme: applications mount with class="dark" on
|
|
the root element. Light theme is the :root base per shadcn/ui v4 convention.
|
|
"Auto" behavior: toggle the .dark class from prefers-color-scheme in app JS.
|
|
|
|
ds-r2 SUPERSEDES ds-r1 (glacier-blue). The register is a dense, near-neutral
|
|
monochrome developer console (shadcn "new-york"/neutral). Neutrals carry a
|
|
whisper of cool (hue 265, chroma <= 0.006), never pure gray. Primary is the
|
|
shadcn-neutral inversion: near-white in dark (ink label), near-black in light
|
|
(paper label). A single restrained cool-blue accent (hue ~252 to 255) is used
|
|
ONLY for the focus ring, links, and the active-nav indicator, never as a fill.
|
|
Semantic status colors (success/warning/destructive/info) stay a functional
|
|
vocabulary. A --chart-1..5 family is added for the analytics dashboard.
|
|
|
|
Format: shadcn/ui v4 compatible CSS custom properties in OKLCH, plus an
|
|
@theme inline mapping block for Tailwind CSS v4. Hex fallbacks are noted in
|
|
comments; every text/surface pair is contrast-verified in both themes (see
|
|
docs/design/DESIGN.md, Accessibility section: 0 failures, computed WCAG 2.x).
|
|
|
|
Source of truth: docs/design/DESIGN.md. Do not hand-edit component CSS to
|
|
diverge from these values; change the token here and let it propagate. Token
|
|
NAMES are stable across ds-r1 and ds-r2 so the app re-themes by swapping
|
|
values, not names.
|
|
========================================================================== */
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Light theme (base) + theme-independent tokens */
|
|
/* ------------------------------------------------------------------------ */
|
|
:root {
|
|
color-scheme: light;
|
|
|
|
/* --- color: surfaces ------------------------------------------------- */
|
|
--background: oklch(0.99 0.002 265); /* #fbfcfd canvas */
|
|
--foreground: oklch(0.2 0.006 265); /* #151619 body text */
|
|
--card: oklch(1 0 0); /* #ffffff raised surface */
|
|
--card-foreground: oklch(0.2 0.006 265); /* #151619 */
|
|
--popover: oklch(1 0 0); /* #ffffff dialogs, menus */
|
|
--popover-foreground: oklch(0.2 0.006 265); /* #151619 */
|
|
|
|
/* --- color: primary (shadcn-neutral inversion: near-black fill) ------- */
|
|
--primary: oklch(0.24 0.006 265); /* #1e1f22 ink */
|
|
--primary-foreground: oklch(0.985 0.001 265); /* #fafafb paper label */
|
|
|
|
/* --- color: supporting surfaces --------------------------------------- */
|
|
--secondary: oklch(0.965 0.003 265); /* #f2f3f5 */
|
|
--secondary-foreground: oklch(0.24 0.006 265); /* #1e1f22 */
|
|
--muted: oklch(0.965 0.003 265); /* #f2f3f5 */
|
|
--muted-foreground: oklch(0.475 0.008 265); /* #5a5c61 */
|
|
--accent: oklch(0.965 0.004 265); /* #f2f3f6 hover wash */
|
|
--accent-foreground: oklch(0.24 0.006 265); /* #1e1f22 */
|
|
|
|
/* --- color: semantic status ------------------------------------------- */
|
|
--destructive: oklch(0.52 0.2 25); /* #c21725 */
|
|
--destructive-foreground: oklch(0.985 0.005 25); /* #fdf9f8 */
|
|
--success: oklch(0.48 0.13 155); /* #00723b */
|
|
--success-foreground: oklch(0.985 0.005 155); /* #f8fbf9 */
|
|
--warning: oklch(0.52 0.11 70); /* #8f5d14 */
|
|
--warning-foreground: oklch(0.985 0.005 80); /* #fcfaf6 */
|
|
--info: oklch(0.5 0.15 255); /* #1762b6 */
|
|
--info-foreground: oklch(0.985 0.005 250); /* #f8fafd */
|
|
|
|
/* --- color: lines and focus ------------------------------------------- */
|
|
--border: oklch(0.92 0.004 265); /* #e3e4e7 hairline */
|
|
--input: oklch(0.89 0.004 265); /* #d9dbdd field border */
|
|
--ring: oklch(0.55 0.15 255); /* #2971c6 accent blue */
|
|
|
|
/* --- color: chart family (data marks; AA >= 3:1 non-text on card) ------ */
|
|
--chart-1: oklch(0.52 0.15 255); /* #1f68bc blue */
|
|
--chart-2: oklch(0.52 0.14 155); /* #007f43 green */
|
|
--chart-3: oklch(0.6 0.12 70); /* #ad721c amber */
|
|
--chart-4: oklch(0.52 0.2 25); /* #c21725 red */
|
|
--chart-5: oklch(0.5 0.18 300); /* #7541b8 violet */
|
|
|
|
/* --- color: sidebar family -------------------------------------------- */
|
|
--sidebar: oklch(0.975 0.003 265); /* #f6f7f9 */
|
|
--sidebar-foreground: oklch(0.24 0.006 265); /* #1e1f22 */
|
|
--sidebar-primary: oklch(0.52 0.15 255); /* #1f68bc accent blue */
|
|
--sidebar-primary-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
--sidebar-accent: oklch(0.955 0.005 265); /* #eef0f4 active item */
|
|
--sidebar-accent-foreground: oklch(0.24 0.006 265); /* #1e1f22 */
|
|
--sidebar-border: oklch(0.91 0.004 265); /* #e0e1e4 */
|
|
--sidebar-ring: oklch(0.55 0.15 255); /* #2971c6 */
|
|
|
|
/* --- shadow ramp (near-neutral, never glacier) ------------------------- */
|
|
--shadow-sm: 0 1px 2px 0 oklch(0.2 0.01 265 / 0.06);
|
|
--shadow-md: 0 2px 8px -1px oklch(0.2 0.01 265 / 0.1),
|
|
0 1px 2px 0 oklch(0.2 0.01 265 / 0.06);
|
|
--shadow-lg: 0 8px 24px -4px oklch(0.2 0.01 265 / 0.16),
|
|
0 2px 6px 0 oklch(0.2 0.01 265 / 0.08);
|
|
|
|
/* --- typography -------------------------------------------------------- */
|
|
/* JetBrains Mono (OFL-1.1, free) is an optional progressive enhancement:
|
|
it renders only where locally installed. No font files are shipped. */
|
|
--font-family-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
|
Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
|
--font-family-mono: "JetBrains Mono", ui-monospace, "Cascadia Code",
|
|
"SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
|
|
/* compact scale, px-snapped; 13.5px body for high dashboard density */
|
|
--font-size-2xs: 0.6875rem; --line-height-2xs: 1rem; /* 11/16 micro */
|
|
--font-size-xs: 0.75rem; --line-height-xs: 1rem; /* 12/16 caption */
|
|
--font-size-sm: 0.8125rem; --line-height-sm: 1.125rem; /* 13/18 secondary */
|
|
--font-size-base: 0.84375rem; --line-height-base: 1.25rem; /* 13.5/20 body */
|
|
--font-size-lg: 1rem; --line-height-lg: 1.375rem; /* 16/22 emphasis */
|
|
--font-size-xl: 1.125rem; --line-height-xl: 1.5rem; /* 18/24 section */
|
|
--font-size-2xl: 1.3125rem; --line-height-2xl: 1.625rem; /* 21/26 page title */
|
|
--font-size-3xl: 1.6875rem; --line-height-3xl: 2rem; /* 27/32 display, stat */
|
|
|
|
--font-weight-regular: 400;
|
|
--font-weight-medium: 500;
|
|
--font-weight-semibold: 600;
|
|
|
|
--tracking-tight: -0.01em; /* titles 2xl and up */
|
|
--tracking-wide: 0.02em; /* tiny mono labels */
|
|
|
|
/* --- spacing (base unit 4px) ------------------------------------------- */
|
|
--space-1: 0.25rem; /* 4px */
|
|
--space-2: 0.5rem; /* 8px */
|
|
--space-3: 0.75rem; /* 12px */
|
|
--space-4: 1rem; /* 16px */
|
|
--space-5: 1.25rem; /* 20px */
|
|
--space-6: 1.5rem; /* 24px */
|
|
--space-8: 2rem; /* 32px */
|
|
--space-10: 2.5rem; /* 40px */
|
|
--space-12: 3rem; /* 48px */
|
|
--space-16: 4rem; /* 64px */
|
|
|
|
/* --- radius (one family, derived from a single 6px base) --------------- */
|
|
--radius: 0.375rem; /* 6px base */
|
|
--radius-sm: calc(var(--radius) - 2px); /* 4px badges, small controls */
|
|
--radius-md: var(--radius); /* 6px buttons, inputs */
|
|
--radius-lg: calc(var(--radius) + 2px); /* 8px cards, panels */
|
|
--radius-xl: calc(var(--radius) + 6px); /* 12px dialogs, sheets */
|
|
--radius-full: 9999px; /* pills, switch */
|
|
|
|
/* --- layout and control metrics (denser than ds-r1) -------------------- */
|
|
--border-w: 1px;
|
|
--ring-w: 2px;
|
|
--ring-offset: 2px;
|
|
--control-h-sm: 1.875rem; /* 30px dense-row controls */
|
|
--control-h: 2.125rem; /* 34px default control height */
|
|
--control-h-lg: 2.625rem; /* 42px prominent controls */
|
|
--tap-target: 2.75rem; /* 44px minimum hit area (extended if visual < 44) */
|
|
--sidebar-width: 15rem;
|
|
--sidebar-width-icon: 3rem;
|
|
/* Outer content cap. Was 78rem (1248px), which left ~1250px of a 2560px
|
|
monitor unused while tables scrolled horizontally inside it. 110rem
|
|
(1760px) is wide enough for dense telemetry tables and the two-pane
|
|
layouts without letting a page become a single ungrouped expanse. */
|
|
--container-max: 110rem;
|
|
/* Inner cap for prose and single-column forms. A control row stretched to
|
|
1760px puts its label a screen away from its input; text past ~75ch stops
|
|
being scannable. Views opt into this for text-heavy panels while their
|
|
tables use the full --container-max. */
|
|
--measure-max: 60rem;
|
|
/* Page gutter, tightening on small screens so a tablet does not spend a
|
|
quarter of its width on padding. */
|
|
--gutter: 1.5rem;
|
|
--opacity-disabled: 0.5;
|
|
|
|
/* --- motion ------------------------------------------------------------- */
|
|
--motion-fast: 100ms; /* hover, focus, pressed feedback */
|
|
--motion-default: 150ms; /* menus, popovers, toggles, tabs */
|
|
--motion-slow: 220ms; /* dialogs, sheets, page-level */
|
|
--motion-spin: 800ms; /* continuous loading spinner */
|
|
--motion-ease-out: cubic-bezier(0.2, 0, 0, 1);
|
|
--motion-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
--motion-rise: -2px; /* hover lift distance */
|
|
--motion-enter: 8px; /* enter-toward travel distance */
|
|
|
|
/* --- z-index ------------------------------------------------------------ */
|
|
--z-sticky: 20;
|
|
--z-overlay: 40;
|
|
--z-modal: 50;
|
|
--z-toast: 60;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Dark theme (Frosty default: mount with class="dark") */
|
|
/* ------------------------------------------------------------------------ */
|
|
.dark {
|
|
color-scheme: dark;
|
|
|
|
--background: oklch(0.15 0.004 265); /* #0a0b0d canvas */
|
|
--foreground: oklch(0.985 0.001 265); /* #fafafb body text */
|
|
--card: oklch(0.185 0.004 265); /* #121314 raised surface */
|
|
--card-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
--popover: oklch(0.205 0.004 265); /* #161719 dialogs, menus */
|
|
--popover-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
|
|
--primary: oklch(0.92 0.004 265); /* #e3e4e7 near-white */
|
|
--primary-foreground: oklch(0.205 0.006 265); /* #16171a ink label */
|
|
|
|
--secondary: oklch(0.255 0.004 265); /* #222325 */
|
|
--secondary-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
--muted: oklch(0.235 0.004 265); /* #1d1e20 */
|
|
--muted-foreground: oklch(0.712 0.008 265); /* #a0a2a7 */
|
|
--accent: oklch(0.255 0.006 265); /* #212326 hover wash */
|
|
--accent-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
|
|
--destructive: oklch(0.665 0.19 25); /* #f25855 */
|
|
--destructive-foreground: oklch(0.205 0.04 25); /* #280e0c ink label */
|
|
--success: oklch(0.72 0.15 155); /* #43c07a */
|
|
--success-foreground: oklch(0.18 0.04 155); /* #021709 */
|
|
--warning: oklch(0.8 0.13 82); /* #e7b551 */
|
|
--warning-foreground: oklch(0.24 0.04 82); /* #291d07 */
|
|
--info: oklch(0.68 0.13 250); /* #549de5 */
|
|
--info-foreground: oklch(0.17 0.04 250); /* #021020 */
|
|
|
|
--border: oklch(0.27 0.006 265); /* #252629 */
|
|
--input: oklch(0.3 0.006 265); /* #2c2e31 */
|
|
--ring: oklch(0.62 0.13 252); /* #4589d2 accent blue */
|
|
|
|
--chart-1: oklch(0.66 0.14 252); /* #4b95e5 blue */
|
|
--chart-2: oklch(0.72 0.15 155); /* #43c07a green */
|
|
--chart-3: oklch(0.8 0.13 82); /* #e7b551 amber */
|
|
--chart-4: oklch(0.665 0.19 25); /* #f25855 red */
|
|
--chart-5: oklch(0.62 0.16 300); /* #966cd7 violet */
|
|
|
|
--sidebar: oklch(0.13 0.004 265); /* #070709 */
|
|
--sidebar-foreground: oklch(0.8 0.006 265); /* #bcbec2 */
|
|
--sidebar-primary: oklch(0.62 0.13 252); /* #4589d2 accent blue */
|
|
--sidebar-primary-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
--sidebar-accent: oklch(0.235 0.006 265); /* #1d1e21 active item */
|
|
--sidebar-accent-foreground: oklch(0.985 0.001 265); /* #fafafb */
|
|
--sidebar-border: oklch(0.24 0.006 265); /* #1e1f22 */
|
|
--sidebar-ring: oklch(0.62 0.13 252); /* #4589d2 */
|
|
|
|
--shadow-sm: 0 1px 2px 0 oklch(0.03 0.006 265 / 0.5);
|
|
--shadow-md: 0 2px 8px -1px oklch(0.03 0.006 265 / 0.6),
|
|
0 1px 2px 0 oklch(0.03 0.006 265 / 0.5);
|
|
--shadow-lg: 0 10px 30px -5px oklch(0.03 0.006 265 / 0.7),
|
|
0 4px 8px -2px oklch(0.03 0.006 265 / 0.5);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Reduced motion: durations collapse, travel distances zero out */
|
|
/* ------------------------------------------------------------------------ */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
:root {
|
|
--motion-fast: 0ms;
|
|
--motion-default: 0ms;
|
|
--motion-slow: 0ms;
|
|
--motion-rise: 0px;
|
|
--motion-enter: 0px;
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Tailwind CSS v4 mapping (shadcn/ui v4 convention) */
|
|
/* Import this file in the app stylesheet after `@import "tailwindcss";`. */
|
|
/* ------------------------------------------------------------------------ */
|
|
@theme inline {
|
|
/* colors */
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--color-card: var(--card);
|
|
--color-card-foreground: var(--card-foreground);
|
|
--color-popover: var(--popover);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
--color-secondary: var(--secondary);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
--color-muted: var(--muted);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
--color-accent: var(--accent);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
--color-destructive: var(--destructive);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
--color-success: var(--success);
|
|
--color-success-foreground: var(--success-foreground);
|
|
--color-warning: var(--warning);
|
|
--color-warning-foreground: var(--warning-foreground);
|
|
--color-info: var(--info);
|
|
--color-info-foreground: var(--info-foreground);
|
|
--color-border: var(--border);
|
|
--color-input: var(--input);
|
|
--color-ring: var(--ring);
|
|
--color-chart-1: var(--chart-1);
|
|
--color-chart-2: var(--chart-2);
|
|
--color-chart-3: var(--chart-3);
|
|
--color-chart-4: var(--chart-4);
|
|
--color-chart-5: var(--chart-5);
|
|
--color-sidebar: var(--sidebar);
|
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
--color-sidebar-primary: var(--sidebar-primary);
|
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
--color-sidebar-accent: var(--sidebar-accent);
|
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
--color-sidebar-border: var(--sidebar-border);
|
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
|
|
/* typography */
|
|
--font-sans: var(--font-family-sans);
|
|
--font-mono: var(--font-family-mono);
|
|
--text-2xs: var(--font-size-2xs);
|
|
--text-2xs--line-height: var(--line-height-2xs);
|
|
--text-xs: var(--font-size-xs);
|
|
--text-xs--line-height: var(--line-height-xs);
|
|
--text-sm: var(--font-size-sm);
|
|
--text-sm--line-height: var(--line-height-sm);
|
|
--text-base: var(--font-size-base);
|
|
--text-base--line-height: var(--line-height-base);
|
|
--text-lg: var(--font-size-lg);
|
|
--text-lg--line-height: var(--line-height-lg);
|
|
--text-xl: var(--font-size-xl);
|
|
--text-xl--line-height: var(--line-height-xl);
|
|
--text-2xl: var(--font-size-2xl);
|
|
--text-2xl--line-height: var(--line-height-2xl);
|
|
--text-3xl: var(--font-size-3xl);
|
|
--text-3xl--line-height: var(--line-height-3xl);
|
|
|
|
/* radius */
|
|
--radius-sm: calc(var(--radius) - 2px);
|
|
--radius-md: var(--radius);
|
|
--radius-lg: calc(var(--radius) + 2px);
|
|
--radius-xl: calc(var(--radius) + 6px);
|
|
|
|
/* shadows */
|
|
--shadow-sm: var(--shadow-sm);
|
|
--shadow-md: var(--shadow-md);
|
|
--shadow-lg: var(--shadow-lg);
|
|
|
|
/* easing */
|
|
--ease-out: var(--motion-ease-out);
|
|
--ease-in-out: var(--motion-ease-in-out);
|
|
}
|