SurfSense Color System
Use PALETTE.css as the canonical palette contract. Preserve its
token names and values unless the user explicitly requests a palette change.
Principles
- Use semantic tokens such as
background, foreground, primary,
muted, accent, destructive, border, and their foreground pairs.
Do not use raw hex values in components.
- Use the matching foreground token for text and icons placed on a semantic
surface:
primary-foreground on primary, card-foreground on card,
and so on.
- Use
chart-1 through chart-5 for data series. Do not repurpose chart
colors as component state colors.
- Use
ring for focus indicators and border or input for boundaries.
Never remove a visible keyboard focus indicator.
- Use
muted-foreground only for secondary text. Do not use it for small or
essential text unless its contrast passes WCAG.
- Use
destructive only for destructive actions, errors, or dangerous
states. Do not use chart colors to communicate errors.
- Support both
:root and .dark; never add a light-only semantic token.
- Prefer existing semantic tokens over creating new aliases. Add a token only
when it represents a reusable semantic role that the palette does not cover.
Workflow
- Locate the active global CSS file from the target app's
components.json;
this repository contains more than one frontend.
- Compare the active theme with PALETTE.css. Do not overwrite
unrelated CSS, animation, layout, or framework directives.
- Apply palette values at the global token layer, not inside individual
components.
- In components, use the project's semantic utility classes or CSS variables,
for example
bg-background text-foreground, bg-card text-card-foreground, and border-border.
- Check affected foreground/background pairs in both themes. WCAG targets:
4.5:1 for normal text, 3:1 for large text and meaningful UI boundaries.
- Verify focus, hover, active, selected, disabled, destructive, chart, and
sidebar states when affected.
Guardrails
- Do not invent intermediate shades to make one component look better.
- Do not use opacity to compensate for an incorrect semantic token when it
reduces text contrast.
- Do not replace the palette wholesale when the requested change concerns one
component.
- Report a contrast failure instead of silently changing canonical values.
- Treat the palette's
@theme inline block as Tailwind v4 configuration.
Before applying it, verify the target app uses Tailwind v4 and preserve any
required non-color namespaces already present in its global stylesheet.
Known Accessibility Constraint
The canonical dark muted-foreground (#7a706a) does not reach 4.5:1 for
normal text on dark background (4.11:1), card (3.90:1), or muted
(3.64:1). Preserve the palette, but do not use this token for essential or
small normal-weight dark-mode text. Report the conflict and request a palette
decision when no existing foreground token fits.
Coordination
- For shadcn/ui composition and styling, also use
../shadcn/SKILL.md.
- For React or Next.js implementation, also use
../vercel-react-best-practices/SKILL.md.
- For interface polish, color transitions, or reduced-motion behavior, use
../make-interfaces-feel-better/SKILL.md after implementation.
Output
For implementation tasks, report:
- which app and global stylesheet received the palette;
- whether both themes were updated;
- contrast or state risks that remain;
- validation performed.
For audits, cite each issue by token pair and usage location, then recommend a
semantic-token correction before proposing a new color.
1---2name: color-system3description: Applies and reviews SurfSense's canonical light and dark color palette, semantic design tokens, typography, charts, borders, shadows, and theme mappings. Use when creating or changing frontend colors, themes, component styling, data visualizations, or design tokens.4---56# SurfSense Color System78Use [PALETTE.css](PALETTE.css) as the canonical palette contract. Preserve its9token names and values unless the user explicitly requests a palette change.1011## Principles12131. Use semantic tokens such as `background`, `foreground`, `primary`,14 `muted`, `accent`, `destructive`, `border`, and their foreground pairs.15 Do not use raw hex values in components.162. Use the matching foreground token for text and icons placed on a semantic17 surface: `primary-foreground` on `primary`, `card-foreground` on `card`,18 and so on.193. Use `chart-1` through `chart-5` for data series. Do not repurpose chart20 colors as component state colors.214. Use `ring` for focus indicators and `border` or `input` for boundaries.22 Never remove a visible keyboard focus indicator.235. Use `muted-foreground` only for secondary text. Do not use it for small or24 essential text unless its contrast passes WCAG.256. Use `destructive` only for destructive actions, errors, or dangerous26 states. Do not use chart colors to communicate errors.277. Support both `:root` and `.dark`; never add a light-only semantic token.288. Prefer existing semantic tokens over creating new aliases. Add a token only29 when it represents a reusable semantic role that the palette does not cover.3031## Workflow32331. Locate the active global CSS file from the target app's `components.json`;34 this repository contains more than one frontend.352. Compare the active theme with [PALETTE.css](PALETTE.css). Do not overwrite36 unrelated CSS, animation, layout, or framework directives.373. Apply palette values at the global token layer, not inside individual38 components.394. In components, use the project's semantic utility classes or CSS variables,40 for example `bg-background text-foreground`, `bg-card41 text-card-foreground`, and `border-border`.425. Check affected foreground/background pairs in both themes. WCAG targets:43 4.5:1 for normal text, 3:1 for large text and meaningful UI boundaries.446. Verify focus, hover, active, selected, disabled, destructive, chart, and45 sidebar states when affected.4647## Guardrails4849- Do not invent intermediate shades to make one component look better.50- Do not use opacity to compensate for an incorrect semantic token when it51 reduces text contrast.52- Do not replace the palette wholesale when the requested change concerns one53 component.54- Report a contrast failure instead of silently changing canonical values.55- Treat the palette's `@theme inline` block as Tailwind v4 configuration.56 Before applying it, verify the target app uses Tailwind v4 and preserve any57 required non-color namespaces already present in its global stylesheet.5859## Known Accessibility Constraint6061The canonical dark `muted-foreground` (`#7a706a`) does not reach 4.5:1 for62normal text on dark `background` (4.11:1), `card` (3.90:1), or `muted`63(3.64:1). Preserve the palette, but do not use this token for essential or64small normal-weight dark-mode text. Report the conflict and request a palette65decision when no existing foreground token fits.6667## Coordination6869- For shadcn/ui composition and styling, also use `../shadcn/SKILL.md`.70- For React or Next.js implementation, also use71 `../vercel-react-best-practices/SKILL.md`.72- For interface polish, color transitions, or reduced-motion behavior, use73 `../make-interfaces-feel-better/SKILL.md` after implementation.7475## Output7677For implementation tasks, report:7879- which app and global stylesheet received the palette;80- whether both themes were updated;81- contrast or state risks that remain;82- validation performed.8384For audits, cite each issue by token pair and usage location, then recommend a85semantic-token correction before proposing a new color.