Skip to content

Theming

Components are styled with CSS variables that follow the shadcn/ui naming, so they adopt your project's theme as-is.

The palette is warm stone neutrals with one terracotta accent. The accent is exposed as --primary and --ring, because shadcn reserves --accent for subtle hover fills; terracotta text uses --link, which stays readable in dark mode. Override any variable in your own CSS and every component follows.

Colors

  • --backgroundPage background
  • --foregroundPrimary text
  • --surfaceSite chrome, preview frames
  • --surface-2Subtle fills, hovers
  • --cardCard surface
  • --popoverMenus, dialogs, tooltips
  • --primaryAccent: the one filled action per view, current state
  • --primary-foregroundText on accent
  • --primary-hoverAccent on hover
  • --linkTerracotta text and links
  • --secondarySecondary fills
  • --mutedMuted fills
  • --muted-foregroundSecondary text
  • --text-secondaryBody text a step quieter
  • --accentHover and active rows
  • --highlightNew badge fill
  • --highlight-foregroundText on the New badge
  • --highlight-textAmber text
  • --selectedSelected rows and items
  • --destructiveDanger
  • --destructive-textDanger text
  • --successSuccess
  • --success-foregroundText on success fills
  • --warningWarning
  • --chart-1Chart series 1
  • --chart-2Chart series 2
  • --chart-3Chart series 3
  • --chart-4Chart series 4
  • --chart-5Chart series 5
  • --chart-6Chart series 6 (usage categories)
  • --borderHairline borders
  • --inputInput borders
  • --ringFocus ring
  • --dotDot grid on preview stages
  • --codeCode blocks

Dark mode

Every color has a dark value, shown on the right of each swatch pair. They apply under data-theme="dark", on <html> for the page or on any element for a dark island inside a light page (and data-theme="light" the other way round). This site sets it in an inline script before the first paint, from your choice in the header or your system setting, so a page never flashes the wrong theme.

Components only read the variables. In a shadcn project they follow your .dark class as they are, and canvases repaint with the new colors when the theme switches.

Radius

A single --radius of 8px drives the scale: 4, 8, 12 and 16px, plus full for pills.

  • rounded-sm4px
  • rounded-md8px
  • rounded-lg12px
  • rounded-xl16px
  • rounded-full9999px

Shadows

Shadows are soft and layered: a tight contact shadow plus a wide, faint ambient one.

  • shadow-xs
  • shadow-sm
  • shadow-md
  • shadow-lg
  • shadow-xl

CSS variables

The full set, light and dark, as defined in this site's globals.css. Each one is mapped to a Tailwind color in @theme inline, e.g. --color-primary: var(--primary).

app/globals.css
:root,
[data-theme="light"] {
  --radius: 8px;

  --background: #fafaf9;
  --foreground: #1c1917;
  --surface: #f5f5f4;
  --surface-2: #e7e5e4;

  --card: #fafaf9;
  --card-foreground: #1c1917;
  --popover: #fafaf9;
  --popover-foreground: #1c1917;

  --primary: #c2410c;
  --primary-foreground: #fafaf9;
  --primary-hover: #9a3412;
  --link: #c2410c;
  --secondary: #f5f5f4;
  --secondary-foreground: #1c1917;
  --muted: #f5f5f4;
  --muted-foreground: #6b635d;
  --text-secondary: #57534e;
  --accent: #e7e5e4;
  --accent-foreground: #1c1917;

  /* Amber marks New only (badge, latest changelog entry), always with its label. */
  --highlight: #f59e0b;
  --highlight-foreground: #1c1917;
  --highlight-text: #b45309;
  --selected: #fbefe9;

  --destructive: #dc2626;
  --destructive-text: #b91c1c;
  --success: #15803d;
  --success-foreground: #ffffff;
  --warning: #b45309;

  /* Chart series, in this fixed order. Validated (OKLab, Machado 2009 protan/deutan) on #fafaf9:
     worst adjacent CVD ΔE 12.7, normal-vision 15.6, every slot at least 3:1 against the page. */
  --chart-1: #c1400a;
  --chart-2: #0784a4;
  --chart-3: #b95712;
  --chart-4: #9d0f38;
  --chart-5: #699a36;
  --chart-6: #865803;

  /* --border is decorative (dividers, card edges); controls use --input, which clears 3:1. */
  --border: #d6d3d1;
  --input: #8a827c;
  --ring: #c2410c;

  --dot: #d6d3d1;
  --code: #efedeb;

  --duration-press: 120ms;
  --duration-popover: 180ms;
  --duration-modal: 240ms;

  color-scheme: light;
}

:root[data-theme="dark"],
[data-theme="dark"] {
  --background: #161412;
  --foreground: #f5f5f4;
  --surface: #1e1b18;
  --surface-2: #2a2623;

  --card: #1e1b18;
  --card-foreground: #f5f5f4;
  --popover: #1e1b18;
  --popover-foreground: #f5f5f4;

  --primary: #c2410c;
  --primary-foreground: #fafaf9;
  --primary-hover: #b83c0a;
  --link: #fb923c;
  --secondary: #2a2623;
  --secondary-foreground: #f5f5f4;
  --muted: #1e1b18;
  --muted-foreground: #9a928b;
  --text-secondary: #a8a29e;
  --accent: #2a2623;
  --accent-foreground: #f5f5f4;

  --highlight: #fbbf24;
  --highlight-foreground: #1c1917;
  --highlight-text: #fbbf24;
  --selected: #2b1c15;

  --destructive: #dc2626;
  --destructive-text: #f87171;
  --success: #4ade80;
  --success-foreground: #052e16;
  --warning: #fbbf24;

  /* Validated on #161412: worst adjacent CVD ΔE 12.2, normal-vision 15.6, all at least 3:1. */
  --chart-1: #c1400a;
  --chart-2: #0784a4;
  --chart-3: #d16d30;
  --chart-4: #b62e4b;
  --chart-5: #6a9e34;
  --chart-6: #8a5b09;

  --border: #3a3532;
  --input: #7a726c;
  --ring: #f97316;

  --dot: #3a3532;
  --code: #1e1b18;

  color-scheme: dark;
}