relay design system · v3.5-a neutral-first · canon

Component Canon

Every block on this page renders with the shipped CSS — @relay/ui (copied verbatim into ui/) plus the app-level extract in app.css. If it looks wrong here, it looks wrong in the app. Spec of record: relay-app DESIGN.md; when this page and tokens.css disagree, tokens win.

Tokens — surfaces · accent roles
--bg
--surface
--panel
--deep
--accent-ui
Aa--accent-fill + --on-accent
--accent-tint
--accent-motion · motion only
--indigo · org only
--success
--warning
--error

The accent split. One Context Teal identity, dual-value (#0d9488 light / #2dd4bf dark), consumed by role: --accent-ui for icons/rings/marks · --accent-text for links and Codes (AA) · --accent-fill+--on-accent for buttons — dark mode flips to #0d1514 ink, never white-on-teal. Surfaces are achromatic; teal ≤10% of any surface and only on interactive/active. #00D9C8 is motion-only (animated strokes + the logomark).

Type — three registers, no overlap
Cormorant Garamond — one display heading per view
Outfit — all running copy, labels, buttons, nav. This is the UI register.
JETBRAINS MONO — CODES · TIMESTAMPS · COUNTS · BADGES

Single Display Rule — exactly one Cormorant display per view. Mono-for-Data Rule — mono is structured data only, never prose.

Buttons

Ink-Flip Rule. Dark-mode teal fills carry --on-accent: #0d1514 ink. White-on-teal (1.9:1) is forbidden in dark; black-on-teal (the v3.4 signature) is retired everywhere.

Badges · chips · status dots
Active Received Expiring Expired Draft chip chip-teal chip-indigo · org chip-green chip-warn chip-red
active / pending claimed / received / completed expiring expired / deleted / error inactive / draft / private

Status-dot colors have one source of truth: concepts/src/ui/status-dot.ts (RCTX-440). Direction vocabulary is Outgoing / Incoming; the received status is "Received", never "Sent/Received".

The Code — signature artifact
QNHC2C

Codes are text — they take --accent-text (AA), always mono, always with a copy affordance. Hover the hero: characters scramble then cascade home — the shipped scramble egg (reduced-motion honors a plain copy).

Cards — flat by default
Card Title
Uppercase section heading, sub in muted 13px. Depth is border-color, never shadow.
Body content. Hover a list card and the border brightens (--border-hi) — the Flat-By-Default Rule keeps shadows for modals and dropdowns only.
Relays sent
128
Received
54
Open sessions
7
workspace · 34 relays

Transfers

Eyebrow (mono, hairline) → display (Cormorant italic) → subtitle (Outfit light). Emitted by ui/primitives.ts screenHead().

Tool help card — .fi-panel (feature-intro.ts)
New here
Meet Stream

Streams are named focus areas that gather related relays and sessions in one place — like a project thread your agents keep adding to.

  1. 1Create a streamName it after a project or topic — takes a few seconds.
  2. 2Add a relay to itDrop a relay in and it starts accumulating context you can hand off later.
  3. 3Come back to itRelays, sessions and peeks for that focus area stay together and stay current.

The training pattern (#604). One per primitive page outside Overview: Transfers · Series · Stream · Sessions · Search · Catalog · Requests · Trash (Send/Connect when their tracks land). Fires once, first visit; seen-state persists server-side; an account already holding objects of the primitive absorbs it silently (the has-content guard, #455). Sanctioned teal-tint surface; step numbers carry --on-accent ink.

Timeline — honest time
2m ago · 14:32:08
Relay QNHC2C claimed
by build-agent · session pc_42e3
1h ago
Added to stream relay-platform
by erik
Jul 17
Relay sent
outgoing · org christensen-digital

Relative time ticks honestly and shows the exact stamp on hover. Timestamps are mono. Counts describe what's drawn, never imply the corpus.

Empty state
Nothing in flight
Relays you send or receive will land here.

Fail-closed visibility: absence renders as an honest empty state — never a ghosted list. Locked objects render dashed; a bad deep link gets an anchor-404.

Quiet easter eggs
Eggs stay quiet: discoverable, never in the way, all behind prefers-reduced-motion guards, and toggleable in-app (the eggs toggle). Canon eggs on this page and in the app:
  • Code scramble — hover the hero Code above; characters scramble then cascade home left→right.
  • Signal ripple — triple-click the page background: a single teal ring broadcasts out (#signal-fx, shipped in relay-app.css).
  • Console greeting — open devtools. The brand mark logs in, in character.
  • Logomark heartbeat — the broadcast mark's core beats at 3.4s (corebeat) — the one sanctioned --accent-motion surface.
canon source: relay-app packages/ui/*.css (verbatim copy in ui/) + app.css extract of concepts/public/relay-app.css · synced 2026-07-18
related: app shell · screen reality matrix · global cards / notices · transfers list-shell