Palette
Phosphor theme
Near-black with a phosphor-green accent, an amber warning and hairlines drawn in the accent instead of white.
background
card
primary
chart-2
success
warning
Install
The file lands as app/vibra-phosphor.css. Import it after your globals and set data-preset="phosphor" on <html>, or on any wrapper.
$
npx shadcn@latest add @vibra/theme-phosphorNeeds the @vibra registry in your components.json — set it up once.
The stylesheet
/* Phosphor — near-black with a phosphor-green accent, amber warning and
* hairlines drawn in the accent rather than in white.
*
* Dark-first: the dark mode is the instrument panel this preset is for; the
* light mode keeps the same deep green ink on near-white so a page printed or
* read in daylight still belongs to it. Both scopes carry every token
* vibra.css defines, so `data-preset="phosphor"` repaints a page completely —
* on <html> or on any wrapper, which is what the second scope's three
* selectors are for.
*
* The green is a field colour, never small text on the page background: at the
* lightness that reads as phosphor it carries dark text, and the light mode
* darkens it to L 0.44 before it is allowed to carry white. The accent-tinted
* hairlines are opaque now, so the field boundary clears 3:1 in both modes.
*/
[data-preset="phosphor"] {
--radius: 0.375rem;
--background: oklch(0.985 0.006 150);
--surface: oklch(0.96 0.01 150);
--card: oklch(1 0 0);
--popover: oklch(1 0 0);
--muted: oklch(0.955 0.01 150);
--secondary: oklch(0.945 0.012 150);
--accent: oklch(0.925 0.03 150);
--foreground: oklch(0.2 0.022 155);
--card-foreground: oklch(0.2 0.022 155);
--popover-foreground: oklch(0.2 0.022 155);
--muted-foreground: oklch(0.48 0.025 152);
--faint-foreground: oklch(0.5 0.022 152);
--secondary-foreground: oklch(0.27 0.03 152);
--accent-foreground: oklch(0.27 0.035 152);
--brand: oklch(0.44 0.13 148);
--brand-foreground: oklch(0.99 0.01 150);
--brand-muted: oklch(0.925 0.05 148);
--primary: var(--brand);
--primary-foreground: var(--brand-foreground);
--ring: var(--brand);
--border: oklch(0.87 0.03 150);
--rule: oklch(0.77 0.045 150);
--input: oklch(0.63 0.05 150);
--chart-grid: oklch(0.9 0.025 150);
--success: oklch(0.45 0.13 148);
--success-foreground: oklch(0.99 0.01 150);
--success-muted: oklch(0.93 0.05 148);
--warning: oklch(0.5 0.11 70);
--warning-foreground: oklch(0.99 0.01 85);
--warning-muted: oklch(0.94 0.06 82);
--danger: oklch(0.51 0.21 27);
--danger-foreground: oklch(0.99 0.01 27);
--danger-muted: oklch(0.93 0.04 27);
--info: oklch(0.47 0.11 200);
--info-foreground: oklch(0.99 0.01 200);
--info-muted: oklch(0.93 0.04 200);
--destructive: var(--danger);
--chart-1: var(--brand);
--chart-2: oklch(0.52 0.1 195);
--chart-3: oklch(0.58 0.12 105);
--chart-4: oklch(0.55 0.14 30);
--chart-5: oklch(0.5 0.11 250);
--chart-6: oklch(0.62 0.13 128);
--chart-7: oklch(0.6 0.12 65);
--chart-8: oklch(0.44 0.04 155);
--chart-positive: var(--success);
--chart-negative: var(--danger);
--chart-neutral: var(--muted-foreground);
--chart-axis: var(--muted-foreground);
--sidebar: oklch(0.955 0.012 150);
--sidebar-foreground: oklch(0.2 0.022 155);
--sidebar-primary: var(--brand);
--sidebar-primary-foreground: var(--brand-foreground);
--sidebar-accent: oklch(0.915 0.03 150);
--sidebar-accent-foreground: oklch(0.27 0.035 152);
--sidebar-border: oklch(0.44 0.13 148 / 22%);
--sidebar-ring: var(--brand);
--shadow-sheet: 0 1px 2px oklch(0.2 0.03 155 / 6%), 0 2px 6px -2px oklch(0.2 0.03 155 / 5%);
--shadow-float: 0 8px 24px -8px oklch(0.2 0.03 155 / 22%), 0 1px 2px oklch(0.2 0.03 155 / 8%);
--shadow-modal: 0 24px 48px -16px oklch(0.2 0.03 155 / 30%);
--overlay: oklch(0.2 0.03 155 / 24%);
}
.dark [data-preset="phosphor"],
[data-preset="phosphor"].dark,
[data-preset="phosphor"] .dark {
--background: oklch(0.145 0.014 155);
--surface: oklch(0.175 0.016 155);
--card: oklch(0.185 0.017 155);
--popover: oklch(0.225 0.018 155);
--muted: oklch(0.24 0.02 155);
--secondary: oklch(0.24 0.02 155);
--accent: oklch(0.28 0.035 150);
--foreground: oklch(0.93 0.03 150);
--card-foreground: oklch(0.93 0.03 150);
--popover-foreground: oklch(0.93 0.03 150);
--muted-foreground: oklch(0.74 0.04 150);
--faint-foreground: oklch(0.7 0.035 150);
--secondary-foreground: oklch(0.93 0.03 150);
--accent-foreground: oklch(0.93 0.045 148);
--brand: oklch(0.86 0.19 145);
--brand-foreground: oklch(0.17 0.05 150);
--brand-muted: oklch(0.28 0.055 148);
--primary: var(--brand);
--primary-foreground: var(--brand-foreground);
--ring: var(--brand);
--border: oklch(0.3 0.035 150);
--rule: oklch(0.4 0.045 150);
--input: oklch(0.55 0.05 150);
--chart-grid: oklch(0.32 0.03 152);
--success: oklch(0.86 0.19 145);
--success-foreground: oklch(0.17 0.05 150);
--success-muted: oklch(0.3 0.05 148);
--warning: oklch(0.85 0.16 80);
--warning-foreground: oklch(0.2 0.05 80);
--warning-muted: oklch(0.31 0.04 80);
--danger: oklch(0.71 0.19 27);
--danger-foreground: oklch(0.17 0.04 27);
--danger-muted: oklch(0.31 0.035 27);
--info: oklch(0.8 0.12 195);
--info-foreground: oklch(0.17 0.04 195);
--info-muted: oklch(0.3 0.04 195);
--destructive: var(--danger);
--chart-1: var(--brand);
--chart-2: oklch(0.76 0.12 195);
--chart-3: oklch(0.83 0.15 105);
--chart-4: oklch(0.7 0.16 30);
--chart-5: oklch(0.72 0.1 250);
--chart-6: oklch(0.72 0.15 128);
--chart-7: oklch(0.8 0.14 65);
--chart-8: oklch(0.62 0.05 155);
--chart-positive: var(--success);
--chart-negative: var(--danger);
--chart-neutral: var(--muted-foreground);
--chart-axis: var(--muted-foreground);
--sidebar: oklch(0.125 0.014 155);
--sidebar-foreground: oklch(0.93 0.03 150);
--sidebar-primary: var(--brand);
--sidebar-primary-foreground: var(--brand-foreground);
--sidebar-accent: oklch(0.21 0.02 155);
--sidebar-accent-foreground: oklch(0.93 0.03 150);
--sidebar-border: oklch(0.86 0.19 145 / 16%);
--sidebar-ring: var(--brand);
--shadow-sheet: inset 0 1px 0 oklch(1 0 0 / 5%);
--shadow-float: 0 12px 32px -8px oklch(0 0 0 / 60%), inset 0 1px 0 oklch(1 0 0 / 6%);
--shadow-modal: 0 24px 64px -12px oklch(0 0 0 / 70%);
--overlay: oklch(0 0 0 / 60%);
}