Skip to content

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

SwatchTokenValueUsage
#0b3e9dcolor.brand#0b3e9dPrimary actions, links, active nav, focus
#082f78color.brand-hover#082f78Hover/pressed state of brand elements
#e6ebf5color.brand-soft#e6ebf5Soft brand background (active rows, tints, badges)
#ffffffcolor.on-brand#ffffffText/icons on a brand-filled surface

Neutral

SwatchTokenValueUsage
#f7f8facolor.bg#f7f8faApp/page background
#ffffffcolor.surface#ffffffCards, tables, modals, header
#f0f0f0color.surface-alt#f0f0f0Table headers, subtle fills
#e7e4d6color.surface-warm#E7E4D6Warm surface tint (console content background)
#e0e0e0color.border#e0e0e0Card/table/input borders, dividers
#f0f0f0color.border-soft#f0f0f0Hairline row separators
#1a1a1acolor.text#1a1a1aPrimary body text
#555555color.text-2#555555Secondary text, labels, nav
#888888color.text-muted#888888Muted/help text, placeholders

Semantic

SwatchTokenValueUsage
#22c55ecolor.success#22c55ePositive accent (bars, dots)
#dcfce7color.success-soft#dcfce7Success banner/badge background
#166534color.success-text#166534Success text / positive profit
#f59e0bcolor.warning#f59e0bCaution accent
#fff3cdcolor.warning-soft#fff3cdWarning banner/badge background
#92400ecolor.warning-text#92400eWarning text
#c0392bcolor.danger#c0392bDestructive actions, negative accent
#a93226color.danger-hover#a93226Hover of destructive buttons
#fee2e2color.danger-soft#fee2e2Error banner/badge background
#b91c1ccolor.danger-text#b91c1cError text / negative profit
#d1ecf1color.info-soft#d1ecf1Info/neutral badge background
#0c5460color.info-text#0c5460Info/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

SwatchTokenValue
#ecf0facolor.brand-50#ecf0fa
#d3ddf2color.brand-100#d3ddf2
#aabfe6color.brand-200#aabfe6
#7898d6color.brand-300#7898d6
#426fc1color.brand-400#426fc1
#1c50accolor.brand-500#1c50ac
#0b3e9dcolor.brand-600#0b3e9d
#082f78color.brand-700#082f78
#0a2a63color.brand-800#0a2a63
#0c264fcolor.brand-900#0c264f
#07162fcolor.brand-950#07162f

neutral

SwatchTokenValue
#f7f8facolor.neutral-50#f7f8fa
#eef0f3color.neutral-100#eef0f3
#e1e4e9color.neutral-200#e1e4e9
#cdd2dacolor.neutral-300#cdd2da
#9aa1adcolor.neutral-400#9aa1ad
#707784color.neutral-500#707784
#555555color.neutral-600#555555
#3e434ccolor.neutral-700#3e434c
#292d34color.neutral-800#292d34
#1a1a1acolor.neutral-900#1a1a1a
#0d0f12color.neutral-950#0d0f12

success

SwatchTokenValue
#f0fdf4color.success-50#f0fdf4
#dcfce7color.success-100#dcfce7
#bbf7d0color.success-200#bbf7d0
#86efaccolor.success-300#86efac
#4ade80color.success-400#4ade80
#22c55ecolor.success-500#22c55e
#16a34acolor.success-600#16a34a
#15803dcolor.success-700#15803d
#166534color.success-800#166534
#14532dcolor.success-900#14532d
#052e16color.success-950#052e16

warning

SwatchTokenValue
#fffbebcolor.warning-50#fffbeb
#fef3c7color.warning-100#fef3c7
#fde68acolor.warning-200#fde68a
#fbcf4dcolor.warning-300#fbcf4d
#f9b424color.warning-400#f9b424
#f59e0bcolor.warning-500#f59e0b
#b9770ecolor.warning-600#b9770e
#a4640fcolor.warning-700#a4640f
#92400ecolor.warning-800#92400e
#78350fcolor.warning-900#78350f
#451f06color.warning-950#451f06

danger

SwatchTokenValue
#fef2f2color.danger-50#fef2f2
#fee2e2color.danger-100#fee2e2
#fecacacolor.danger-200#fecaca
#fca5a5color.danger-300#fca5a5
#f87171color.danger-400#f87171
#ef4444color.danger-500#ef4444
#c0392bcolor.danger-600#c0392b
#b91c1ccolor.danger-700#b91c1c
#991b1bcolor.danger-800#991b1b
#7f1d1dcolor.danger-900#7f1d1d
#450a0acolor.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.

SwatchTokenValueUsage
#51ff2fcolor.accent-green#51ff2fElectric green — high-energy CTA background
#ecf251color.accent-lime#ecf251Lime — CTA background
#f5ff00color.accent-yellow#f5ff00Yellow — CTA background / accent text
#fdfd96color.accent-butter#fdfd96Butter (pale yellow) — soft CTA background / on-dark text
#ff9500color.accent-orange#ff9500Orange — CTA background
#047affcolor.accent-azure#047affAzure — CTA background
#0b3e9dcolor.accent-cobalt#0b3e9dCobalt (deep blue) — CTA background
#2b2c29color.accent-charcoal#2b2c29Charcoal (near-black) — CTA background / accent text

Typography

TokenValueUsage
font.sans'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serifAll UI text
font.mono'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospaceCode, IDs, monospace tables
font.headline'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospaceHeadings — getvera.site (console uses font.sans)
font.button'Roboto Condensed', 'Arial Narrow', sans-serifButtons — always uppercase, regular weight, ~5% tracking
font.size-xs0.8remCaptions, footnotes
font.size-sm0.85remSecondary text, table cells, buttons
font.size-base0.9remBody default
font.size-md1remCard titles, emphasis
font.size-lg1.1remPage/brand heading
font.size-xl1.25remSection heading
font.size-2xl1.5remHero / large numbers
font.weight-normal400Body
font.weight-medium500Labels, emphasis
font.weight-semibold600Headings, brand, totals

Spacing

4px base scale.

TokenValue
space.xs4px
space.sm8px
space.md12px
space.lg16px
space.xl24px
space.2xl32px

Radius

TokenValueUsage
radius.sm4pxInputs, buttons
radius.md6pxCards, tables
radius.lg8pxModals, boxes
radius.pill12pxBadges, segmented toggles
radius.full999pxFully-rounded (pill) buttons

Shadow

TokenValueUsage
shadow.card0 1px 3px rgba(0,0,0,0.06)Cards, tables
shadow.modal0 8px 32px rgba(0,0,0,0.2)Modals, popovers
shadow.toast0 2px 12px rgba(0,0,0,0.15)Floating toasts

Z-index

TokenValueUsage
z.nav1050Mobile nav overlay
z.toast1000Banner toasts
z.modal1200Modal 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.)