VERA Design Tokens
This file is the source of truth for VERA's visual language. Edit the values in the tables below; run node scripts/build-tokens.js to regenerate public/tokens.css; both the web console and getvera.site consume that file, so a change here propagates to both.
- You can edit any value by hand — change a hex, a size, a radius — then regenerate.
- Claude keeps this file and
public/tokens.css in lockstep when we change styling together. - Token names map to CSS custom properties as
--vera-<group>-<name> (e.g. color.brand → --vera-color-brand).
The brand palette is built on the Cobalt (#0b3e9d) from the Figma Brand Colors collection; the vivid accent-* colors below are reserved for highlights (badges, CTAs, charts), not core UI chrome. Nothing here is sacred — adjust freely.
Color
Colors are emitted as HSLA. Values below are authored as hex (so the swatches stay accurate), but build-tokens.js converts each color.* to HSL and emits two custom properties: --vera-color-<name>-hsl (the H, S%, L% channels) and --vera-color-<name> (= hsla(var(--vera-color-<name>-hsl), 1), the opaque color). Use the plain variable for normal fills (color: var(--vera-color-brand)); to dial back opacity, compose with the channel var and an alpha float — e.g. background: hsla(var(--vera-color-brand-hsl), .5).
Brand
| Swatch | Token | Value | Usage |
|---|
 | color.brand | #0b3e9d | Primary actions, links, active nav, focus |
 | color.brand-hover | #082f78 | Hover/pressed state of brand elements |
 | color.brand-soft | #e6ebf5 | Soft brand background (active rows, tints, badges) |
 | color.on-brand | #ffffff | Text/icons on a brand-filled surface |
Neutral
| Swatch | Token | Value | Usage |
|---|
 | color.bg | #f7f8fa | App/page background |
 | color.surface | #ffffff | Cards, tables, modals, header |
 | color.surface-alt | #f0f0f0 | Table headers, subtle fills |
 | color.surface-warm | #E7E4D6 | Warm surface tint (console content background) |
 | color.border | #e0e0e0 | Card/table/input borders, dividers |
 | color.border-soft | #f0f0f0 | Hairline row separators |
 | color.text | #1a1a1a | Primary body text |
 | color.text-2 | #555555 | Secondary text, labels, nav |
 | color.text-muted | #888888 | Muted/help text, placeholders |
Semantic
| Swatch | Token | Value | Usage |
|---|
 | color.success | #22c55e | Positive accent (bars, dots) |
 | color.success-soft | #dcfce7 | Success banner/badge background |
 | color.success-text | #166534 | Success text / positive profit |
 | color.warning | #f59e0b | Caution accent |
 | color.warning-soft | #fff3cd | Warning banner/badge background |
 | color.warning-text | #92400e | Warning text |
 | color.danger | #c0392b | Destructive actions, negative accent |
 | color.danger-hover | #a93226 | Hover of destructive buttons |
 | color.danger-soft | #fee2e2 | Error banner/badge background |
 | color.danger-text | #b91c1c | Error text / negative profit |
 | color.info-soft | #d1ecf1 | Info/neutral badge background |
 | color.info-text | #0c5460 | Info/neutral badge text |
Scales
Tailwind-style 50→950 scales for the five core families. Existing semantic tokens (color.brand, color.success, color.warning, color.danger, color.text, color.text-2, color.bg) stay as-is and remain valid aliases — their values already equal the matching scale step.
brand
| Swatch | Token | Value |
|---|
 | color.brand-50 | #ecf0fa |
 | color.brand-100 | #d3ddf2 |
 | color.brand-200 | #aabfe6 |
 | color.brand-300 | #7898d6 |
 | color.brand-400 | #426fc1 |
 | color.brand-500 | #1c50ac |
 | color.brand-600 | #0b3e9d |
 | color.brand-700 | #082f78 |
 | color.brand-800 | #0a2a63 |
 | color.brand-900 | #0c264f |
 | color.brand-950 | #07162f |
neutral
| Swatch | Token | Value |
|---|
 | color.neutral-50 | #f7f8fa |
 | color.neutral-100 | #eef0f3 |
 | color.neutral-200 | #e1e4e9 |
 | color.neutral-300 | #cdd2da |
 | color.neutral-400 | #9aa1ad |
 | color.neutral-500 | #707784 |
 | color.neutral-600 | #555555 |
 | color.neutral-700 | #3e434c |
 | color.neutral-800 | #292d34 |
 | color.neutral-900 | #1a1a1a |
 | color.neutral-950 | #0d0f12 |
success
| Swatch | Token | Value |
|---|
 | color.success-50 | #f0fdf4 |
 | color.success-100 | #dcfce7 |
 | color.success-200 | #bbf7d0 |
 | color.success-300 | #86efac |
 | color.success-400 | #4ade80 |
 | color.success-500 | #22c55e |
 | color.success-600 | #16a34a |
 | color.success-700 | #15803d |
 | color.success-800 | #166534 |
 | color.success-900 | #14532d |
 | color.success-950 | #052e16 |
warning
| Swatch | Token | Value |
|---|
 | color.warning-50 | #fffbeb |
 | color.warning-100 | #fef3c7 |
 | color.warning-200 | #fde68a |
 | color.warning-300 | #fbcf4d |
 | color.warning-400 | #f9b424 |
 | color.warning-500 | #f59e0b |
 | color.warning-600 | #b9770e |
 | color.warning-700 | #a4640f |
 | color.warning-800 | #92400e |
 | color.warning-900 | #78350f |
 | color.warning-950 | #451f06 |
danger
| Swatch | Token | Value |
|---|
 | color.danger-50 | #fef2f2 |
 | color.danger-100 | #fee2e2 |
 | color.danger-200 | #fecaca |
 | color.danger-300 | #fca5a5 |
 | color.danger-400 | #f87171 |
 | color.danger-500 | #ef4444 |
 | color.danger-600 | #c0392b |
 | color.danger-700 | #b91c1c |
 | color.danger-800 | #991b1b |
 | color.danger-900 | #7f1d1d |
 | color.danger-950 | #450a0a |
Accent
Vivid campaign palette sourced from the bramd-colors LinkedIn-image swatches; bound to the Brand Colors variable collection in Figma. For social/marketing surfaces, not the console UI chrome.
| Swatch | Token | Value | Usage |
|---|
 | color.accent-green | #51ff2f | Electric green — high-energy CTA background |
 | color.accent-lime | #ecf251 | Lime — CTA background |
 | color.accent-yellow | #f5ff00 | Yellow — CTA background / accent text |
 | color.accent-butter | #fdfd96 | Butter (pale yellow) — soft CTA background / on-dark text |
 | color.accent-orange | #ff9500 | Orange — CTA background |
 | color.accent-azure | #047aff | Azure — CTA background |
 | color.accent-cobalt | #0b3e9d | Cobalt (deep blue) — CTA background |
 | color.accent-charcoal | #2b2c29 | Charcoal (near-black) — CTA background / accent text |
Typography
| Token | Value | Usage |
|---|
font.sans | 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif | All UI text |
font.mono | 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace | Code, IDs, monospace tables |
font.headline | 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace | Headings — getvera.site (console uses font.sans) |
font.button | 'Roboto Condensed', 'Arial Narrow', sans-serif | Buttons — always uppercase, regular weight, ~5% tracking |
font.size-xs | 0.8rem | Captions, footnotes |
font.size-sm | 0.85rem | Secondary text, table cells, buttons |
font.size-base | 0.9rem | Body default |
font.size-md | 1rem | Card titles, emphasis |
font.size-lg | 1.1rem | Page/brand heading |
font.size-xl | 1.25rem | Section heading |
font.size-2xl | 1.5rem | Hero / large numbers |
font.weight-normal | 400 | Body |
font.weight-medium | 500 | Labels, emphasis |
font.weight-semibold | 600 | Headings, brand, totals |
Spacing
4px base scale.
| Token | Value |
|---|
space.xs | 4px |
space.sm | 8px |
space.md | 12px |
space.lg | 16px |
space.xl | 24px |
space.2xl | 32px |
Radius
| Token | Value | Usage |
|---|
radius.sm | 4px | Inputs, buttons |
radius.md | 6px | Cards, tables |
radius.lg | 8px | Modals, boxes |
radius.pill | 12px | Badges, segmented toggles |
radius.full | 999px | Fully-rounded (pill) buttons |
Shadow
| Token | Value | Usage |
|---|
shadow.card | 0 1px 3px rgba(0,0,0,0.06) | Cards, tables |
shadow.modal | 0 8px 32px rgba(0,0,0,0.2) | Modals, popovers |
shadow.toast | 0 2px 12px rgba(0,0,0,0.15) | Floating toasts |
Z-index
| Token | Value | Usage |
|---|
z.nav | 1050 | Mobile nav overlay |
z.toast | 1000 | Banner toasts |
z.modal | 1200 | Modal overlays |
LER context pills
LER (revenue ÷ cost) values render as coloured "context pills" in tables (Project Managers, Reports). The bands reuse the existing scale tokens — no new tokens — ramping from danger (losing money) up the success scale. Implemented by _lerPill in lib/console/render.js; shown live on /design-system.
Bands (background / text), all existing scale tokens:
- < 1.0 (losing money) — bg danger-100, text danger-800
- 1.0 – 1.5 — bg success-50, text success-800
- 1.6 – 1.9 — bg success-100, text success-800
- 2.0 – 2.5 — bg success-200, text success-900
- 2.6 – 2.9 — bg success-300, text success-900
- 3.0 + — bg success-400, text success-900
(Listed, not tabled, on purpose: build-tokens.js parses two-backtick table rows as tokens, so this mapping is kept as prose to avoid emitting bogus custom properties.)