shadcn/ui theme · dark original

Emerald SaaS

Deep forest-black surfaces under a bright emerald primary — the confident, modern look of open-source dashboards and data tools.

darkgreensaas

Install

npx shadcn@latest add https://csscreme.com/r/emerald-saas.json

Requires a project with shadcn/ui set up. Prefer to paste? The CSS variables are below.

Partial install

Live preview

Revenue

Last 30 days across all workspaces.

Total

$48,210+12.4%

Active

1,204+3.1%

Churn

0.8%-0.2%

Tokens

:root {
  --background: oklch(99.0% 0.002 145.6);
  --foreground: oklch(27.6% 0.020 163.1);
  --card: oklch(97.4% 0.002 165.1);
  --card-foreground: oklch(27.6% 0.020 163.1);
  --popover: oklch(97.4% 0.002 165.1);
  --popover-foreground: oklch(27.6% 0.020 163.1);
  --primary: oklch(69.6% 0.149 162.5);
  --primary-foreground: oklch(15.2% 0.009 285.3);
  --secondary: oklch(98.0% 0.002 165.1);
  --secondary-foreground: oklch(27.6% 0.020 163.1);
  --muted: oklch(98.0% 0.002 165.1);
  --muted-foreground: oklch(55.0% 0.017 164.3);
  --accent: oklch(77.3% 0.153 163.2);
  --accent-foreground: oklch(15.2% 0.009 285.3);
  --destructive: oklch(62.6% 0.193 23.0);
  --destructive-foreground: oklch(15.2% 0.009 285.3);
  --border: oklch(84.4% 0.007 160.0);
  --input: oklch(84.4% 0.007 160.0);
  --ring: oklch(69.6% 0.149 162.5);
  --chart-1: oklch(69.6% 0.149 162.5);
  --chart-2: oklch(77.3% 0.153 163.2);
  --chart-3: oklch(57.1% 0.125 239.3);
  --chart-4: oklch(68.2% 0.227 142.6);
  --chart-5: oklch(73.4% 0.152 163.0);
  --sidebar: oklch(98.3% 0.002 165.1);
  --sidebar-foreground: oklch(27.6% 0.020 163.1);
  --sidebar-primary: oklch(69.6% 0.149 162.5);
  --sidebar-primary-foreground: oklch(15.2% 0.009 285.3);
  --sidebar-accent: oklch(98.0% 0.002 165.1);
  --sidebar-accent-foreground: oklch(27.6% 0.020 163.1);
  --sidebar-border: oklch(84.4% 0.007 160.0);
  --sidebar-ring: oklch(69.6% 0.149 162.5);
  --radius: 10px;
  --shadow-2xs: 0 1px 2px 0px rgb(31 43 37 / 0.05);
  --shadow-xs: 0 1px 3px 0px rgb(31 43 37 / 0.06);
  --shadow-sm: 0 1px 3px 0px rgb(31 43 37 / 0.08), 0 1px 2px -1px rgb(31 43 37 / 0.08);
  --shadow-md: 0 4px 6px -1px rgb(31 43 37 / 0.09), 0 2px 4px -2px rgb(31 43 37 / 0.09);
  --shadow-lg: 0 10px 15px -3px rgb(31 43 37 / 0.1), 0 4px 6px -4px rgb(31 43 37 / 0.1);
  --shadow-xl: 0 20px 25px -5px rgb(31 43 37 / 0.12), 0 8px 10px -6px rgb(31 43 37 / 0.12);
  --shadow-2xl: 0 25px 50px -12px rgb(31 43 37 / 0.22);
  --spacing: 4px;
}

.dark {
  --background: oklch(16.7% 0.016 165.4);
  --foreground: oklch(95.7% 0.018 166.4);
  --card: oklch(22.2% 0.027 161.4);
  --card-foreground: oklch(95.7% 0.018 166.4);
  --popover: oklch(22.2% 0.027 161.4);
  --popover-foreground: oklch(95.7% 0.018 166.4);
  --primary: oklch(69.6% 0.149 162.5);
  --primary-foreground: oklch(15.2% 0.009 285.3);
  --secondary: oklch(20.3% 0.022 163.7);
  --secondary-foreground: oklch(95.7% 0.018 166.4);
  --muted: oklch(20.3% 0.022 163.7);
  --muted-foreground: oklch(68.9% 0.049 164.4);
  --accent: oklch(77.3% 0.153 163.2);
  --accent-foreground: oklch(15.2% 0.009 285.3);
  --destructive: oklch(62.6% 0.193 23.0);
  --destructive-foreground: oklch(15.2% 0.009 285.3);
  --border: oklch(33.1% 0.025 167.5);
  --input: oklch(33.1% 0.025 167.5);
  --ring: oklch(69.6% 0.149 162.5);
  --chart-1: oklch(69.6% 0.149 162.5);
  --chart-2: oklch(77.3% 0.153 163.2);
  --chart-3: oklch(57.1% 0.125 239.3);
  --chart-4: oklch(68.2% 0.227 142.6);
  --chart-5: oklch(73.4% 0.152 163.0);
  --sidebar: oklch(19.5% 0.021 161.9);
  --sidebar-foreground: oklch(95.7% 0.018 166.4);
  --sidebar-primary: oklch(69.6% 0.149 162.5);
  --sidebar-primary-foreground: oklch(15.2% 0.009 285.3);
  --sidebar-accent: oklch(20.3% 0.022 163.7);
  --sidebar-accent-foreground: oklch(95.7% 0.018 166.4);
  --sidebar-border: oklch(33.1% 0.025 167.5);
  --sidebar-ring: oklch(69.6% 0.149 162.5);
  --shadow-2xs: 0 1px 2px 0px rgb(230 245 238 / 0.16);
  --shadow-xs: 0 1px 3px 0px rgb(230 245 238 / 0.18);
  --shadow-sm: 0 1px 3px 0px rgb(230 245 238 / 0.22), 0 1px 2px -1px rgb(230 245 238 / 0.22);
  --shadow-md: 0 4px 6px -1px rgb(230 245 238 / 0.26), 0 2px 4px -2px rgb(230 245 238 / 0.26);
  --shadow-lg: 0 10px 15px -3px rgb(230 245 238 / 0.3), 0 4px 6px -4px rgb(230 245 238 / 0.3);
  --shadow-xl: 0 20px 25px -5px rgb(230 245 238 / 0.34), 0 8px 10px -6px rgb(230 245 238 / 0.34);
  --shadow-2xl: 0 25px 50px -12px rgb(230 245 238 / 0.45);
}

Tailwind v4

@theme inline {
  --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-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);
  --radius: var(--radius);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --shadow-2xs: var(--shadow-2xs);
  --shadow-xs: var(--shadow-xs);
  --shadow-sm: var(--shadow-sm);
  --shadow-md: var(--shadow-md);
  --shadow-lg: var(--shadow-lg);
  --shadow-xl: var(--shadow-xl);
  --shadow-2xl: var(--shadow-2xl);
  --spacing: var(--spacing);
}

Colors are OKLCH. Contrast is checked in both modes: foreground on background, on cards, and button labels on the primary fill.

DESIGN.md for AI agents

Design context for Cursor, Claude Code, Codex, v0 or Lovable. Paste it in before you ask for UI, or commit it at your repo root as DESIGN.md. Every colour, ratio and rule below is computed from this theme, not written by hand, so the agent can be held to it.

curl -o DESIGN.md https://csscreme.com/d/emerald-saas.md
The file
# DESIGN.md — Emerald SaaS

> Design context for AI coding agents. Paste this file into Cursor, Claude Code, Codex, v0 or Lovable
> before asking for UI, or commit it at your repo root as `DESIGN.md`.

- **Source:** [Emerald SaaS on CSS Crème](https://csscreme.com/themes/emerald-saas)
- **Default mode:** dark
- **Tags:** dark, green, saas
- **Install as a real shadcn/ui theme:** `npx shadcn@latest add https://csscreme.com/r/emerald-saas.json`
- **Fingerprint:** `fnv1a-6782e32a` — a hash of the token set below. It changes only when a token changes.
- **Verify this copy:** call the MCP tool `verify_design_md` with `{ "id": "emerald-saas", "fingerprint": "fnv1a-6782e32a" }`
  at `https://csscreme.com/mcp`, or refetch https://csscreme.com/d/emerald-saas.md. A stale copy is worse than none: an agent will follow it faithfully.
- **Also available as:** [DTCG tokens](https://csscreme.com/d/emerald-saas.tokens.json) for Tokens Studio / Figma Variables · [agent rules block](https://csscreme.com/d/emerald-saas.rules.md) for CLAUDE.md, AGENTS.md or .cursor/rules

Deep forest-black surfaces under a bright emerald primary — the confident, modern look of open-source dashboards and data tools.

---

## Semantic color roles

Six roles carry the identity. Everything else in this file is derived from them.

| Role | Hex | OKLCH | Use it for |
| --- | --- | --- | --- |
| `bg` | `#08110D` | `oklch(16.7% 0.016 165.4)` | page background |
| `surface` | `#0F1F17` | `oklch(22.2% 0.027 161.4)` | cards, panels, popovers |
| `primary` | `#10B981` | `oklch(69.6% 0.149 162.5)` | brand actions: primary buttons, links, focus rings |
| `accent` | `#34D399` | `oklch(77.3% 0.153 163.2)` | secondary emphasis only, never a second primary |
| `text` | `#E6F5EE` | `oklch(95.7% 0.018 166.4)` | body and heading text |
| `muted` | `#7FA593` | `oklch(68.9% 0.049 164.4)` | secondary text, borders, disabled states |

## Full token set (shadcn/ui, both modes)

Colors are OKLCH (Tailwind v4 / shadcn native). Brand colors are identical in both modes by design:
only the neutrals move, and they keep their hue, so light and dark read as the same design system.

| Token | Light | Dark |
| --- | --- | --- |
| `--background` | `oklch(99.0% 0.002 145.6)` | `oklch(16.7% 0.016 165.4)` |
| `--foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--card` | `oklch(97.4% 0.002 165.1)` | `oklch(22.2% 0.027 161.4)` |
| `--card-foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--popover` | `oklch(97.4% 0.002 165.1)` | `oklch(22.2% 0.027 161.4)` |
| `--popover-foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--primary` | `oklch(69.6% 0.149 162.5)` | `oklch(69.6% 0.149 162.5)` |
| `--primary-foreground` | `oklch(15.2% 0.009 285.3)` | `oklch(15.2% 0.009 285.3)` |
| `--secondary` | `oklch(98.0% 0.002 165.1)` | `oklch(20.3% 0.022 163.7)` |
| `--secondary-foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--muted` | `oklch(98.0% 0.002 165.1)` | `oklch(20.3% 0.022 163.7)` |
| `--muted-foreground` | `oklch(55.0% 0.017 164.3)` | `oklch(68.9% 0.049 164.4)` |
| `--accent` | `oklch(77.3% 0.153 163.2)` | `oklch(77.3% 0.153 163.2)` |
| `--accent-foreground` | `oklch(15.2% 0.009 285.3)` | `oklch(15.2% 0.009 285.3)` |
| `--destructive` | `oklch(62.6% 0.193 23.0)` | `oklch(62.6% 0.193 23.0)` |
| `--destructive-foreground` | `oklch(15.2% 0.009 285.3)` | `oklch(15.2% 0.009 285.3)` |
| `--border` | `oklch(84.4% 0.007 160.0)` | `oklch(33.1% 0.025 167.5)` |
| `--input` | `oklch(84.4% 0.007 160.0)` | `oklch(33.1% 0.025 167.5)` |
| `--ring` | `oklch(69.6% 0.149 162.5)` | `oklch(69.6% 0.149 162.5)` |
| `--chart-1` | `oklch(69.6% 0.149 162.5)` | `oklch(69.6% 0.149 162.5)` |
| `--chart-2` | `oklch(77.3% 0.153 163.2)` | `oklch(77.3% 0.153 163.2)` |
| `--chart-3` | `oklch(57.1% 0.125 239.3)` | `oklch(57.1% 0.125 239.3)` |
| `--chart-4` | `oklch(68.2% 0.227 142.6)` | `oklch(68.2% 0.227 142.6)` |
| `--chart-5` | `oklch(73.4% 0.152 163.0)` | `oklch(73.4% 0.152 163.0)` |
| `--sidebar` | `oklch(98.3% 0.002 165.1)` | `oklch(19.5% 0.021 161.9)` |
| `--sidebar-foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--sidebar-primary` | `oklch(69.6% 0.149 162.5)` | `oklch(69.6% 0.149 162.5)` |
| `--sidebar-primary-foreground` | `oklch(15.2% 0.009 285.3)` | `oklch(15.2% 0.009 285.3)` |
| `--sidebar-accent` | `oklch(98.0% 0.002 165.1)` | `oklch(20.3% 0.022 163.7)` |
| `--sidebar-accent-foreground` | `oklch(27.6% 0.020 163.1)` | `oklch(95.7% 0.018 166.4)` |
| `--sidebar-border` | `oklch(84.4% 0.007 160.0)` | `oklch(33.1% 0.025 167.5)` |
| `--sidebar-ring` | `oklch(69.6% 0.149 162.5)` | `oklch(69.6% 0.149 162.5)` |

**What is measured and what is derived.** The six roles are the source. `chart-*` and `sidebar-*` follow
fixed rules over them (chart-1 = primary, chart-2 = accent, chart-3/4 = primary rotated ±40°, chart-5 = the
primary–accent midpoint; sidebar maps onto surface, border and primary). `shadow-*` is the foreground
colour at a fixed opacity per step. None of those is a measurement, and an agent should treat them as
defaults it may override, unlike the six roles, which it may not.

## Typography

- **Headings:** Inter
- **Body:** Inter

## Shape and rhythm

- **Radius:** `10px` (the `--radius` token; derive smaller/larger from it, do not invent new values)
- **Spacing scale:** 4px base · 4 / 8 / 12 / 16 / 24 / 32

## Contrast, measured

Computed from the tokens above in dark mode, not asserted. Ratios are WCAG 2.1 relative luminance.

| Pair | Foreground | Background | Ratio | Verdict |
| --- | --- | --- | --- | --- |
| Body text on page background | `#E6F5EE` | `#08110D` | 17.02:1 | AAA |
| Body text on card | `#E6F5EE` | `#0F1F17` | 15.19:1 | AAA |
| Muted text on page background | `#7FA593` | `#08110D` | 7.03:1 | AAA |
| Button label on primary | `#0b0b0f` | `#10B981` | 7.74:1 | AAA |
| Button label on accent | `#0b0b0f` | `#34D399` | 10.22:1 | AAA |

## Rules for the agent

These are constraints, not suggestions. Each one is checkable against the tables above.

1. **Use only the tokens listed here.** Do not introduce a hex value that is not in the token table. If
   you need an in-between shade, mix two existing tokens rather than inventing a new hue.
2. **`#10B981` (primary) is the only call-to-action color.** One primary action per view. `accent`
   is for secondary emphasis and must never be styled as a second primary button.
3. **Never restyle brand colors between light and dark.** Only neutrals change mode. A theme whose
   primary shifts between modes is a different theme.
4. **Respect the radius token.** Every corner derives from `10px`. Mixed radii across a view is
   the most common tell of generated UI.
5. **Stay on the spacing scale.** 4px base · 4 / 8 / 12 / 16 / 24 / 32. No arbitrary pixel values.
6. **Do not drop below the contrast ratios above.** If a combination you need is not in the contrast
   table, compute it before shipping it. Text under 4.5:1 fails AA.
7. **Headings in Inter, body in Inter.** Do not add a third family.
8. **Use the semantic role, not the raw color.** Write `var(--primary)`, never `#10B981`, so the
   theme stays swappable.

## CSS variables

Paste into `globals.css`:

```css
:root {
  --background: oklch(99.0% 0.002 145.6);
  --foreground: oklch(27.6% 0.020 163.1);
  --card: oklch(97.4% 0.002 165.1);
  --card-foreground: oklch(27.6% 0.020 163.1);
  --popover: oklch(97.4% 0.002 165.1);
  --popover-foreground: oklch(27.6% 0.020 163.1);
  --primary: oklch(69.6% 0.149 162.5);
  --primary-foreground: oklch(15.2% 0.009 285.3);
  --secondary: oklch(98.0% 0.002 165.1);
  --secondary-foreground: oklch(27.6% 0.020 163.1);
  --muted: oklch(98.0% 0.002 165.1);
  --muted-foreground: oklch(55.0% 0.017 164.3);
  --accent: oklch(77.3% 0.153 163.2);
  --accent-foreground: oklch(15.2% 0.009 285.3);
  --destructive: oklch(62.6% 0.193 23.0);
  --destructive-foreground: oklch(15.2% 0.009 285.3);
  --border: oklch(84.4% 0.007 160.0);
  --input: oklch(84.4% 0.007 160.0);
  --ring: oklch(69.6% 0.149 162.5);
  --chart-1: oklch(69.6% 0.149 162.5);
  --chart-2: oklch(77.3% 0.153 163.2);
  --chart-3: oklch(57.1% 0.125 239.3);
  --chart-4: oklch(68.2% 0.227 142.6);
  --chart-5: oklch(73.4% 0.152 163.0);
  --sidebar: oklch(98.3% 0.002 165.1);
  --sidebar-foreground: oklch(27.6% 0.020 163.1);
  --sidebar-primary: oklch(69.6% 0.149 162.5);
  --sidebar-primary-foreground: oklch(15.2% 0.009 285.3);
  --sidebar-accent: oklch(98.0% 0.002 165.1);
  --sidebar-accent-foreground: oklch(27.6% 0.020 163.1);
  --sidebar-border: oklch(84.4% 0.007 160.0);
  --sidebar-ring: oklch(69.6% 0.149 162.5);
  --radius: 10px;
  --shadow-2xs: 0 1px 2px 0px rgb(31 43 37 / 0.05);
  --shadow-xs: 0 1px 3px 0px rgb(31 43 37 / 0.06);
  --shadow-sm: 0 1px 3px 0px rgb(31 43 37 / 0.08), 0 1px 2px -1px rgb(31 43 37 / 0.08);
  --shadow-md: 0 4px 6px -1px rgb(31 43 37 / 0.09), 0 2px 4px -2px rgb(31 43 37 / 0.09);
  --shadow-lg: 0 10px 15px -3px rgb(31 43 37 / 0.1), 0 4px 6px -4px rgb(31 43 37 / 0.1);
  --shadow-xl: 0 20px 25px -5px rgb(31 43 37 / 0.12), 0 8px 10px -6px rgb(31 43 37 / 0.12);
  --shadow-2xl: 0 25px 50px -12px rgb(31 43 37 / 0.22);
  --spacing: 4px;
}

.dark {
  --background: oklch(16.7% 0.016 165.4);
  --foreground: oklch(95.7% 0.018 166.4);
  --card: oklch(22.2% 0.027 161.4);
  --card-foreground: oklch(95.7% 0.018 166.4);
  --popover: oklch(22.2% 0.027 161.4);
  --popover-foreground: oklch(95.7% 0.018 166.4);
  --primary: oklch(69.6% 0.149 162.5);
  --primary-foreground: oklch(15.2% 0.009 285.3);
  --secondary: oklch(20.3% 0.022 163.7);
  --secondary-foreground: oklch(95.7% 0.018 166.4);
  --muted: oklch(20.3% 0.022 163.7);
  --muted-foreground: oklch(68.9% 0.049 164.4);
  --accent: oklch(77.3% 0.153 163.2);
  --accent-foreground: oklch(15.2% 0.009 285.3);
  --destructive: oklch(62.6% 0.193 23.0);
  --destructive-foreground: oklch(15.2% 0.009 285.3);
  --border: oklch(33.1% 0.025 167.5);
  --input: oklch(33.1% 0.025 167.5);
  --ring: oklch(69.6% 0.149 162.5);
  --chart-1: oklch(69.6% 0.149 162.5);
  --chart-2: oklch(77.3% 0.153 163.2);
  --chart-3: oklch(57.1% 0.125 239.3);
  --chart-4: oklch(68.2% 0.227 142.6);
  --chart-5: oklch(73.4% 0.152 163.0);
  --sidebar: oklch(19.5% 0.021 161.9);
  --sidebar-foreground: oklch(95.7% 0.018 166.4);
  --sidebar-primary: oklch(69.6% 0.149 162.5);
  --sidebar-primary-foreground: oklch(15.2% 0.009 285.3);
  --sidebar-accent: oklch(20.3% 0.022 163.7);
  --sidebar-accent-foreground: oklch(95.7% 0.018 166.4);
  --sidebar-border: oklch(33.1% 0.025 167.5);
  --sidebar-ring: oklch(69.6% 0.149 162.5);
  --shadow-2xs: 0 1px 2px 0px rgb(230 245 238 / 0.16);
  --shadow-xs: 0 1px 3px 0px rgb(230 245 238 / 0.18);
  --shadow-sm: 0 1px 3px 0px rgb(230 245 238 / 0.22), 0 1px 2px -1px rgb(230 245 238 / 0.22);
  --shadow-md: 0 4px 6px -1px rgb(230 245 238 / 0.26), 0 2px 4px -2px rgb(230 245 238 / 0.26);
  --shadow-lg: 0 10px 15px -3px rgb(230 245 238 / 0.3), 0 4px 6px -4px rgb(230 245 238 / 0.3);
  --shadow-xl: 0 20px 25px -5px rgb(230 245 238 / 0.34), 0 8px 10px -6px rgb(230 245 238 / 0.34);
  --shadow-2xl: 0 25px 50px -12px rgb(230 245 238 / 0.45);
}
```

Tailwind v4 maps them into utilities:

```css
@theme inline {
  --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-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);
  --radius: var(--radius);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --shadow-2xs: var(--shadow-2xs);
  --shadow-xs: var(--shadow-xs);
  --shadow-sm: var(--shadow-sm);
  --shadow-md: var(--shadow-md);
  --shadow-lg: var(--shadow-lg);
  --shadow-xl: var(--shadow-xl);
  --shadow-2xl: var(--shadow-2xl);
  --spacing: var(--spacing);
}
```

---

Generated by [CSS Crème](https://csscreme.com) — curated web design, decoded so you can build it.
Every value above is computed from the palette, not written by hand.

Or link an agent straight at /d/emerald-saas.md — it is served as text/markdown with CORS open, so a tool can fetch it directly.

Fingerprint fnv1a-6782e32a Hash of the token set. Changes only when a token changes. An agent holding this file can ask the MCP verify_design_md whether its copy is still current.
DTCG tokens /d/emerald-saas.tokens.json W3C Design Tokens format. Import into Tokens Studio or Figma Variables without retyping a hex.
Agent rules /d/emerald-saas.rules.md A block for CLAUDE.md, AGENTS.md or .cursor/rules that makes every session read DESIGN.md before touching UI.

Every pair, measured dark mode

The DESIGN.md prints the five pairs an agent will actually produce. This is the whole grid: each token as text on each token as background, WCAG 2.1 ratio and verdict. No summary score, because a single number would hide the one pair that fails.

backgroundcardsecondaryprimaryaccentdestructiveforegroundmuted-foreground
background 1.12fail 1.07fail 7.55AAA 9.96AAA 4.89AA 17.02AAA 7.03AAA
card 1.12fail 1.05fail 6.74AA 8.89AAA 4.37AA large 15.19AAA 6.27AA
secondary 1.07fail 1.05fail 7.05AAA 9.3AAA 4.57AA 15.88AAA 6.56AA
primary 7.55AAA 6.74AA 7.05AAA 1.32fail 1.54fail 2.25fail 1.07fail
accent 9.96AAA 8.89AAA 9.3AAA 1.32fail 2.04fail 1.71fail 1.42fail
destructive 4.89AA 4.37AA large 4.57AA 1.54fail 2.04fail 3.48AA large 1.44fail
foreground 17.02AAA 15.19AAA 15.88AAA 2.25fail 1.71fail 3.48AA large 2.42fail
muted-foreground 7.03AAA 6.27AA 6.56AA 1.07fail 1.42fail 1.44fail 2.42fail

Rows are the text colour, columns the background. AAA is 7:1 or better, AA 4.5:1, AA large 3:1.

Where this came from

Themes here aren't randomised swatches — they start life as a palette in our design layer, studied against real interfaces. See the Emerald SaaS palette for the full role breakdown, font pairing and spacing scale, or browse the showcase and breakdowns the palettes are drawn from.

Font pairing Inter headings · Inter body  ·  Radius 10px

Related themes