Visual system for Cairn. A ring of worn index cards in a dim workshop: cold slate light, one oxidized brass tag catching a glint. The mood lives in the accent and the typography, not in loud surfaces.
Dark, single theme. The surface is a cool near-black slate. It is a workshop bench, not a screen glowing at you. One restrained accent (oxidized teal) carries primary actions, current selection, and the "funded" cue. Role is carried by a small family of muted tag colors, each always paired with its name in text.
Surfaces
--bg: oklch(0.17 0.016 235) cool dark slate, the bench--surface: oklch(0.215 0.016 235) a raised card--surface-2: oklch(0.255 0.016 235) hover and inset--line: oklch(0.32 0.014 235) hairline borders
Text (all verified >= 4.5:1 on --bg)
--ink: oklch(0.96 0.006 235) primary text--muted: oklch(0.74 0.012 235) secondary text--faint: oklch(0.62 0.012 235) hints only, never body
Accent (oxidized teal, brightened to glow on dark)
--accent: oklch(0.72 0.11 182)--accent-dim: oklch(0.52 0.09 182) borders and pressed--accent-ink: oklch(0.22 0.06 182) text on an accent fill
Role tags (one family, similar L and C so they read as a set, never a rainbow). Chip = role color text on a 12 percent tint of the same hue.
- Deployer: oklch(0.76 0.10 75) brass
- Agent: oklch(0.70 0.11 300) violet
- Merchant: oklch(0.73 0.11 150) green
- Personal: oklch(0.72 0.10 250) blue
- Cold: oklch(0.74 0.07 210) pale cyan
- Hot: oklch(0.70 0.12 30) coral
- Test: oklch(0.70 0.02 235) grey
- Other: oklch(0.68 0.06 320) mauve
Semantic
- funded uses
--accent; empty uses--faint. Never a red for empty; empty is not an error.
Two families on a contrast axis, functional not decorative.
- UI sans: Inter (weights 400, 500, 600). Headings, labels, buttons, body.
- Data mono: JetBrains Mono (weights 400, 500). Every address, balance, tag, and hash. Anything a machine produced.
Fixed rem scale, product not fluid. Steps: 12, 13, 14, 16, 20, 28 px. Ratio near 1.2. Wordmark is the one larger moment.
The marker card is the signature object. A tactile index card / luggage tag:
- Rounded rect,
--surface, hairline--line. A single small punched-hole notch centered at the top edge (a 10px circle cut) reads as a tag on a ring. This is the one distinctive motif, used once per card, never repeated as ornament. - Label in sans 16 500. Address below in mono 13,
--muted, click to copy. - Role chip top-right: tinted pill, role color text, role name always shown.
- Tags as small mono chips in
--surface-2. - Balance bottom-right, mono, large-ish, with a small dot cue:
--accentwhen funded,--faintwhen empty. - Edit and remove are quiet icon buttons, visible on hover and focus, always reachable by keyboard.
Set on a ring: the dashboard is a responsive grid, repeat(auto-fit, minmax(280px, 1fr)), that fills one viewport for a normal set. A thin vertical rail on the left edge of the grid hints at the ring spine without boxing every card.
Standard states on every interactive element: default, hover, focus-visible (2px --accent ring), active, disabled, loading (skeleton cards, not spinners). Empty state teaches: connect, then add your first marker.
Fixed slim header (wordmark, connected address, network pill, "add wallet"), then the grid. Single column on narrow screens, the header collapses the address into an avatar. No page-length scroll for a normal set.
150 to 250 ms, state only. Card enter: opacity plus a 4px rise, staggered lightly across a freshly loaded set. Balance change: a brief tick of the dot, no number spinning. Copy: a quick check swap. All wrapped in prefers-reduced-motion, which collapses to instant or crossfade.