Skip to contentVibraUI
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-phosphor

Needs the @vibra registry in your components.json — set it up once.

The stylesheet

app/vibra-phosphor.css
/* 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%);
}