Skip to content

Colour and tokens

Every value in the system, generated from tokens.json. Components read these as CSS variables (var(--surface-100)) and never use a literal. Swatches show each theme side by side; the page theme does not change them.

Token Light Dark High contrast Usage
surface-000 #f2f0ea #141a17 #ffffff Page ground. Bone in light, Ink in dark. Everything else sits on this.
surface-100 #ffffff #1c2320 #ffffff Raised: cards, inputs, modals, menus, table rows.
surface-200 #eceae3 #0f1412 #ededed Sunken: sidebar, code blocks, skeleton base, table header.
surface-hover #e6e4dc #26302a #e2e2e2 Hover on rows, nav items, subtle buttons.
surface-selected #e4f1ea #1c3328 #d6efe2 Selected nav item, selected row, active chip. Pair with emerald-deep text.
surface-inverse #141a17 #f2f0ea #000000 Tooltips and the inverted hero band. Text on it is ink-inverse.
ink #141a17 #f2f0ea #000000 Headings, labels, primary text on every surface. 15:1 on surface-000 in both themes.
ink-secondary #2b332e #d4d8d2 #000000 Running prose and chat replies on surface-000 and surface-100.
ink-muted #4f5752 #a3aca6 #2f3532 Descriptions, metadata, placeholders, timestamps on surface-000, surface-100, surface-200. 6.5:1 light, 7.6:1 dark.
ink-disabled #8e968f #5e6762 #545a57 Disabled control text and icons only. Exempt from contrast rules; never use for live content.
ink-inverse #f2f0ea #141a17 #ffffff Text and icons on surface-inverse.
ink-on-brand #f2f0ea #141a17 #ffffff Text and icons on emerald-deep fills (primary buttons, progress fill). 5.7:1 light, 6.5:1 dark.
emerald #1f8a5b #2f9a68 #0d593a The brand green: caret mark, the up in the wordmark, status icons, large text 24px+. 3.9:1 on surface-000 light, so never for body-size text; use emerald-deep.
emerald-deep #176b47 #4fae7f #0a4a30 Interactive green: primary button fill, links, selected text, focus ring, progress. 5.7:1 on surface-000 and 6.5:1 on surface-100 in light; 6.5:1 on surface-000 dark.
emerald-hover #125a3b #7cc29c #083d27 Hover fill of primary buttons and hovered links.
emerald-active #0d452d #a8d5bc #062d1d Pressed fill of primary buttons.
emerald-soft #e4f1ea #1c3328 #d6efe2 Light button fill, success alert ground, done badge ground. Text on it is emerald-deep.
mist #d4d8d2 #3a423d #5e6662 Inactive progress track, skeleton shimmer high.
caret-idle #7c847e #6f7873 #5e6662 Undrawn caret stroke: both strokes of Queued, the right stroke of Preparing and Planning. 3.4:1 on surface-000 light, 3.9:1 dark, so the caret keeps its shape. In high contrast it stays apart from ink.
border #dddbd3 #2a322e #6e6e6e Decorative hairlines: card edges, dividers, table rules. Carries no meaning, so may sit under 3:1.
border-strong #7c847e #6f7873 #000000 Control borders: inputs, checkboxes, radios, outline buttons. 3.4:1 on surface-000 light, 3.9:1 dark, as WCAG asks of a control edge.
focus #176b47 #4fae7f #000000 The one focus ring: 2px solid, 2px offset, on every focusable element. 5.7:1 on surface-000 light, 6.5:1 dark.
success = emerald-deep #176b47 #4fae7f #0a4a30 Success text and icon, always next to a word or the done caret, never colour alone.
success-soft = emerald-soft #e4f1ea #1c3328 #d6efe2 Success alert and badge ground.
warning #8a5a14 #e8b45a #5c3a00 Needs-approval and waiting states: text and icon on warning-soft (5.0:1 light, 7.5:1 dark) and on surface-000.
warning-soft #f7ebd3 #413d2a #fff0d1 Warning alert, badge and banner ground.
danger #9a3a2a #f09080 #7d1d0e Failed states, destructive buttons, field errors: text and icon on danger-soft (5.6:1 light, 6.4:1 dark) and on surface-000. Always paired with an X icon or the word.
danger-soft #f6e3de #423731 #fde3dd Error alert, badge and field-error ground.
info #2f5f8f #7fb3e6 #173f6e Informational notices: text and icon on info-soft (5.5:1 light, 6.8:1 dark). Blue, so it is never confused with success.
info-soft #e1eaf4 #2e3d44 #dbe8f7 Info alert and badge ground.
overlay #141a177a #000000a6 #000000cc Scrim behind modals and drawers.
chart-1 #1f8a5b #2f9a68 #0a4a30 Categorical series 1 (emerald). Fixed order, never cycled. Validated: adjacent CVD ΔE ≥ 10 both themes, ≥ 3:1 on surface-100.
chart-2 #2e6fd8 #5b93ea #1a4fa8 Categorical series 2 (blue).
chart-3 #b8780f #bf7f18 #7a4d00 Categorical series 3 (amber). Last slot safe for scatter and maps; beyond three series fold to Other or facet.
chart-4 #d3588e #d2659c #a52a6b Categorical series 4 (magenta). Bars, lines and stacks only.
chart-5 #7a5bd6 #8676de #4b2fa6 Categorical series 5 (violet).
chart-6 #c8562e #d06a48 #8f3414 Categorical series 6 (clay). Also the warm pole of the diverging scale. Never for danger; that is danger.
chart-ord-1 #6ab98f #a8d5bc #6ab98f Ordinal and sequential ramp, lightest step (near zero). Validated: monotone, ΔL ≥ 0.06, ≥ 2:1 on the surface.
chart-ord-2 #2f9a68 #7cc29c #2f9a68 Ramp step 2.
chart-ord-3 #176b47 #4fae7f #176b47 Ramp step 3.
chart-ord-4 #0d452d #2f9a68 #0d452d Ramp step 4, darkest in light, mid in dark; dark adds chart-ord-5.
chart-ord-5 #0d452d #176b47 #0d452d Ramp step 5 (dark theme only; equals step 4 in light).
chart-mid = mist #d4d8d2 #3a423d #5e6662 Neutral midpoint of the diverging scale (emerald ↔ clay) and the empty track of charts.
emerald-0 #e8f3ed #e8f3ed #e8f3ed Mantine colors.emerald[0]. Softest tint.
emerald-1 #cde6d8 #cde6d8 #cde6d8 Mantine colors.emerald[1].
emerald-2 #a8d5bc #a8d5bc #a8d5bc Mantine colors.emerald[2]. Dark theme pressed fill.
emerald-3 #7cc29c #7cc29c #7cc29c Mantine colors.emerald[3]. Dark theme hover fill.
emerald-4 #4fae7f #4fae7f #4fae7f Mantine colors.emerald[4]. Dark theme primary shade.
emerald-5 #2f9a68 #2f9a68 #2f9a68 Mantine colors.emerald[5]. Dark theme brand green.
emerald-6 #1f8a5b #1f8a5b #1f8a5b Mantine colors.emerald[6]. The brand green.
emerald-7 #176b47 #176b47 #176b47 Mantine colors.emerald[7]. Light theme primary shade.
emerald-8 #125a3b #125a3b #125a3b Mantine colors.emerald[8]. Light theme hover.
emerald-9 #0d452d #0d452d #0d452d Mantine colors.emerald[9]. Light theme pressed.

Borders carry structure; shadows only lift floating layers. Never shadow a card at rest.

Token Light Dark High contrast Usage
shadow-sm Dropdown menus, popovers, tooltips.
shadow-md Notifications, the composer when focused, dragged items.
shadow-lg Modals and drawers over overlay.
Style Sample Size / line Weight Usage
hero Always up. 56px / 60px 700 Marketing hero only. Familjen Grotesk never appears inside the app UI; the wordmark ships as SVG.
hero-sm Your data. Your control. 40px / 44px 700 Marketing section titles and the hero at phone width.
h1 Tasks 28px / 36px 700 Page title. One per page.
h2 Four phases. One caret. 24px / 32px 600 Section title, modal title.
h3 Connect a provider 20px / 28px 600 Card title, stepper step title.
h4 Daily finance digest 17px / 24px 600 List item title, task card title.
body-lg Always-on AI agents, on infrastructure you own. 17px / 26px 400 Lead paragraphs, onboarding copy.
body Long-running tasks that plan, execute, and review their own work. 15px / 22px 400 Default text: chat, descriptions, table cells, inputs.
body-sm Worked for 4.2 s 13px / 18px 400 Metadata, helper text, timestamps, nav items.
label Provider 13px / 16px 600 Form labels, button text at size sm, badge text.
caption Enter to send · Shift+Enter for a new line 12px / 16px 500 Hints under composers, footnotes. Never below 12px.
overline TODAY 11px / 16px 600 Uppercase group headers in lists and sidebars.
code docker compose up -d 13px / 20px 400 Code blocks, tool call arguments, version strings.
code-sm 0.1.0-alpha.122 12px / 18px 400 Inline code inside body-sm, keyboard shortcuts.

4px base. Use steps, never odd values. Component padding is on the step; layout gaps use the larger steps.

Token Value Usage
space-1 4px Icon to text inside a badge; gap between stacked helper lines.
space-2 8px Icon to label in buttons; gap between chips; inside padding of small controls.
space-3 12px Horizontal padding of inputs and medium buttons; gap between form fields in a row.
space-4 16px Card padding at phone width; gap between fields; the minimum side gutter.
space-5 20px Card padding on desktop; gap between cards.
space-6 24px Modal padding; gap between form sections; page side padding on tablet.
space-8 32px Page side padding on desktop; gap between page sections.
space-10 40px Gap between major page regions; stepper content top margin.
space-12 48px Top bar height; empty state padding.
space-16 64px Marketing section padding.

Soft, 8px base. Radius signals an object: controls md, containers lg, overlays xl, pills full.

Token Value Usage
radius-xs 4px Checkbox box, kbd, inline code, skeleton lines.
radius-sm 6px Small buttons, chips at size sm, menu items.
radius-md 8px Buttons, inputs, selects, tabs, table container, tooltips.
radius-lg 12px Cards, tiles, alerts, chat bubbles, popovers.
radius-xl 16px Modals, drawers, the composer.
radius-full 9999px Badges, pills, avatars, switch, progress bar.

Control heights and icon sizes. Touch targets are 40px minimum on pointer-coarse devices, 32px minimum with a mouse.

Token Value Usage
control-sm 32px Small buttons, inline inputs in tables, action icons.
control-md 40px Default buttons, inputs, selects, nav items. The touch minimum.
control-lg 48px Primary call to action on marketing pages and onboarding.
icon-sm 16px Icons inside badges, inputs and body-sm text.
icon-md 20px Default icon: buttons, nav, table actions.
icon-lg 24px Empty states, feature tiles, page headers.
sidebar 248px App sidebar width on desktop. Collapses to an icon rail of 56px below md, a drawer below sm.
topbar 48px App top bar height.
measure 68ch Maximum width of running prose, chat replies and documentation.

Mantine’s defaults, in em so they follow the user’s font size. Mobile first: write the phone layout, then add from sm up.

Token Value Usage
bp-xs 36em 576px. Two-column form rows start here.
bp-sm 48em 768px. Sidebar becomes an icon rail; cards go two across.
bp-md 62em 992px. Full sidebar; three-card grids.
bp-lg 75em 1200px. Chat gets the side panel; tables show every column.
bp-xl 88em 1408px. Content stops growing; margins absorb the rest.
Token Value Usage
z-sticky 100 Top bar, table header, stepper header.
z-dropdown 200 Menus, selects, popovers, tooltips.
z-overlay 300 Modal and drawer scrim.
z-modal 400 Modal and drawer panel.
z-toast 500 Notifications stack, always above modals.

Durations and easings. Hover and colour 120ms, state 200ms, overlays 240ms in and 160ms out. The caret is the only thing that animates for longer. Everything stops under prefers-reduced-motion.

Token Value Usage
duration-fast 120ms Hover, colour and border changes, press scale, tooltip fade.
duration-base 200ms State changes: checked, expanded, selected, caret stroke, progress width, chevron rotate.
duration-enter 240ms Overlays entering: modal, drawer, menu, toast, popover.
duration-leave 160ms Overlays leaving. Always shorter than entering.
duration-loader 1600ms One loop of the drawing caret loader.
duration-lift 4000ms Period of the working-task lift (2px up and back).
duration-shimmer 1800ms One pass of the skeleton shimmer.
ease-standard cubic-bezier(.4, 0, .2, 1) Everything that moves or changes state.
ease-leave cubic-bezier(.4, 0, 1, 1) Overlays leaving: starts fast, no settle.
ease-caret cubic-bezier(.2, 0, 0, 1) The caret draw: quick start, long settle so the stroke looks drawn, not slid.
press-scale 0.98 Scale of a button or tile while pressed.
tooltip-delay 400ms Hover delay before a tooltip shows; 0 when another tooltip was open in the last second.