Orchard Design System
On this page
Overview
This page is the canonical design-system contract for the canopy worker
portal (services/canopy-web) and its Orchard theme. It is what plugin
authors and jurisdiction maintainers should treat as canon: every color
token, type-scale entry, spacing step, radius, motion rule, voice
guideline, and reusable component named here is part of the contract, not
a suggestion.
It is translated faithfully from the design team’s design/canopy-web/
(§3, "Design system (the contract)"), supplemented by the final Palette-Revision values (folded into this page).
The visual reference is Design System.html in the design project.
rulesets/georgia/notices/components/orchard.typ (notice
rendering), services/canopy-web/src/theme.rs (the ColorPalette struct and
css_variables() emitter), and services/canopy-web/static/css/canopy-web.css
(the --orchard-* CSS variables and utility classes). When those files and this
page disagree on a literal value, the code is what ships; this page records the
design the code is meant to realize.
3. Design system (the contract)
All colors are exposed as --orchard-{name} CSS variables. Theme switching
is [data-theme="dark"] on <body>; the light palette is the default
(:root / [data-theme="light"]), and a @media (prefers-color-scheme: dark)
block applies the dark palette when [data-theme="system"] is set.
3.1 Color tokens
Brand
| Token | Light | Dark | Purpose |
|---|---|---|---|
|
|
|
Headers, primary actions, brand identity |
|
|
|
Hover state |
|
|
|
Decorative only — rules, overlines, leaves |
#ecbf44, Orchard Gold) has strict scope. It is
for brand and decoration only: the center leaf of the canopy mark, section
rule accents (the 14–40px gold lines), selected-row indicators (left rail + soft
tint), and overline labels (sparingly). Gold is never used for functional
warning UI (use warning amber #e08a2b), status pills, or body text (it fails
contrast on white at any size). A second gold (#D0AE56, "DHS Logo Gold")
exists only for rendering the Georgia DHS agency seal in co-branded materials
and is out of scope for general UI.
Surface
| Token | Light | Dark |
|---|---|---|
|
|
|
|
|
|
|
|
|
Text
| Token | Light | Dark |
|---|---|---|
|
|
|
|
|
|
|
|
|
Semantic (foreground + soft bg)
Each semantic family has a base foreground token plus a -bg (soft
background) and a -text (readable-on-bg foreground) variant. The info
family was the addition introduced by the Palette Revision (previously
missing).
| Token | Light | Dark |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The semantic tints also drive several functional UI recipes whose values are intentionally pinned (so the recipe stays consistent across jurisdictions even when a jurisdiction overrides the primary palette):
-
Status pills (
.u-status-*) — light: approved#d8f0e1on#1c6b3e, pending#fbe6c8on#8e510f, denied#f5d6cfon#8a2916, info#d6ebecon#275f63, neutral on--orchard-surface-sunken/--orchard-text; dark: approved#1f4231on#a3e3b9, pending#3e2a0eon#f0c587, denied#3e1812on#e4a094, info#163336on#8fc8cc. -
Expedited / time-sensitive banner — uses
--orchard-warning(amber), not the gold accent. Gold is brand-only. -
Service error panel — light:
#fbe6c8bg,#f0c587border,#8e510ftext; dark:#3e2a0ebg,#6b4810border,#f0c587text. -
Discrepancy row — a tint of the new error: light
#fbeae6bg with a--orchard-errorleft edge; dark#3e1812bg.
--orchard-primary, --orchard-primary-hover,
--orchard-accent) and the leaf-mark SVG colors are intentionally fixed; the
Palette Revision moved only the semantic, surface, text, and dark-mode layers.
3.2 Type
-
Display + body: Montserrat 400 / 500 / 600 / 700.
-
Mono: JetBrains Mono 400 / 500 / 600 for IDs, hex, timestamps, config.
Scale:
| Use | Size | Weight | Letter-spacing |
|---|---|---|---|
Hero display |
42px |
700 |
-1px |
Page title |
28px |
700 |
-0.4px |
Section title |
22px |
700 |
-0.3px |
Card title |
17px |
700 |
-0.2px |
Body large |
14px |
500 |
normal |
Body |
12px |
500 |
normal |
Caption |
10.5px |
500 |
normal |
Overline |
9.5px |
700 |
2px (uppercase) |
Numbers in mono always use tabular figures:
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum";
3.3 Spacing
4px base. Most things land on 8, 12, 16, 20.
| Token | Value | Use |
|---|---|---|
|
4px |
Hairline |
|
6px |
Tight inline rhythm, pill padding |
|
8px |
Default gap |
|
12px |
Compact card padding |
|
16px |
Default card padding |
|
20px |
Section gap |
|
24px |
Page padding |
|
32px |
Hero padding |
3.5 Motion
Only two animations exist in the system:
-
cy-pulse— skeleton loaders. 1.6s ease-in-out. Opacity 1 ↔ 0.55. -
cy-caret-blink— input carets. 1.05s steps(2). Never on UI elements.
Honor prefers-reduced-motion: reduce by disabling both.
3.6 Voice
The system speaks like a thoughtful caseworker, not a SaaS app.
-
Editorial · not chirpy. "Nothing in your queue." not "Oops! Looks empty 😊"
-
Name the service, not the user. "canopy-ievs service unreachable" not "Something went wrong."
-
Numbers in mono. Case IDs, hex, timestamps in JetBrains Mono with tabular-nums. Counts in body sans.
-
Time relative, then exact. "14m ago", "Yesterday 16:48", "May 11". Detail rails always include the ISO timestamp.
3.7 Components
Reusable primitives (see Design System.html for live examples):
| Component | Description |
|---|---|
|
The unit of composition. Card with overline + gold rule header. |
|
Small-caps brand label. |
|
2px gold horizontal accent. |
|
Tabular-num display number (sm/md/lg/xl/xxl sizes). |
|
Directional micro-stat with semantic color. |
|
approved / pending / denied / info / neutral / discrepancy. |
|
Eyebrow-style status (replaces pills in editorial layouts). |
|
3px colored left edge identifying program. |
|
Solid colored chip with white text per program. |
|
Horizontal bar for inline stats. |
|
Decorative single-leaf brand mark. |
|
Tiny inline trend. |
|
Dark-green band with greeting + big stat + leaf watermark. |
3.8 Accessibility commitments
-
Contrast ≥ AA (4.5:1 body, 3:1 large/UI) in both modes. Audited per release.
-
Full keyboard path for every interaction. ⌘K opens the palette. Tab order = visual order.
-
Focus rings always visible (2px gold accent on
:focus-visible). Never removed for aesthetics. -
Semantic landmarks (
<main>,<nav>,<header>,<aside>),role="tablist",aria-current="page",aria-selected. -
Status pills never rely on color alone — always accompanied by a label.
-
prefers-reduced-motiondisablescy-pulseandcy-caret-blink.