Design systemDraft
Card
A card is --panel plus a hairline. It holds a held draft, an ask, a plan, a group of rows on the
phone, a settings group, a network summary. Nothing inside a card gets its own box, except code.
Drawn on nearly every board; the reference cards are the draft in "Needs you, phone and desktop",
the decided card in "States, every list, every size", the Network card in "Devices, network
and VyreDrive", and the Connections card on the Connections board (below).
| Surface | Implementing file | Status |
|---|---|---|
| Deck | deck/css/views/now.css .np-card (work/pwa), deck/css/views/planner.css .pl-card (main), deck/chat/chat.css .gate-card (work/chat) | partial |
| App | apps/app/src/session/Rows.tsx AskCard, apps/app/src/vault/views.tsx TrustCard (work/mobile) | partial |
| Lumen | local/capsule/native/Sources/UI/AgentDeskView.swift HeldCardView, UI/PresenceView.swift (work/capsule-pro) | partial |
Anatomy
- Body. Fill
--panel, 1 px--ruleborder, radius--radius-card(12 desktop) or--radius-card-phone(10 phone),overflow: hidden. Content padding 0 16 (desktop), 0 14 (phone); rows inside separate with a 1 px--ruletop border, never with gaps or inner boxes. - Header (optional). Height 44, padding 0 16, gap 8, flex row: an optional status mark or 16
icon, the label (12/16, 600,
--label; for a held item the beacon dot and the label in--beacon-ink, "Draft to send"), and meta right-aligned (12/16--label, "Gate · outbound email"). No bottom border; the first content row carries the rule. - Footer (optional). Padding 12 16, gap 8, 1 px
--ruletop border. Holds the buttons: one primary first (left), then secondary or outline, a presence or hint line in meta--label, and ghost actions pushed right (margin-left: auto, "Discard D"). - Code inside a card is the only inner box:
--code-bg, radius 8, padding 8 12, JetBrains Mono 13/18, margin 0 12 12.
Variants
- Content card. Header, fields or rows, footer (the draft, the ask, merge failed).
- Row card (phone). No header or footer; a stack of rows (needs-row, list-row, settings-row) with a section label above it outside the card.
- Choice tile. Same body at radius 10, padding 12, transparent fill; selected adds
--focusborder plus a 1 px--focusring. Used for install paths and attention colour. - Connections card (Settings, Vault, Connections). The account-row (account-row.md) grown into
a card when the row needs to show what it's granted, not just be picked. No header rule; three
parts:
- A row at the top, padding 14 16: the provider tile (account-row.md's, 32 here), the account and its meta line (label · provider), then trailing the row's normal state (Default, Last used, or the fix button when it needs one) right-aligned.
- Granted to, padding 0 16 12, wrapped: the label
--label, then one filter chip (chip.md) per surface that can use this connection (Lumen, Chat, Agents, Phone: the vault's real surfaces, never a made-up list), each with the surface's 12 icon leading. Revoking (On to Off) is one tap, always, for every surface. Granting (Off to On) is one tap with the undo toast for Lumen, Chat and Phone; the Agents chip asks Touch ID or a passkey first (chip.md States, Asking), since that hands a credential to an autonomous session, the same no-nag line as pairing and send/post/pay. A row that needs a fix (see account-row.md States) skips this part and the footer: just the top row and its Sign in. - Footer,
--ruletop border, padding 12 16: "Wrong account?" (steplink, opens the credential sheet to pick a different one for this need) on the left, "Connected 3 Jan" in--labelon the right. Never a Revoke or Disconnect here: that lives on the individual grant chip turned off, or the row's More menu.
Colour is never the card's: no violet, bone or wash on the body or border. A card that needs you shows it only through the dot and label in its header. On the Connections card the only colour is the grant chips' own bone "on" state (chip.md); the card itself stays neutral even when nothing is granted.
Sizes
Width fills its column (detail capped at 820, settings detail at 720). Min height is content. Phone cards run edge to edge within the 16 gutter.
States
- Default. As above.
- Hover. None on the card; rows inside have their own hover.
- Focus within. No card ring; the focused control inside shows its own
--focusoutline. - Busy. The primary in the footer keeps its width with a spinner and a verb ("Sending").
- Decided. The header swaps the beacon dot and label for a neutral 16 glyph in
--text-2and the decision in 13/600--text("Allowed once by you · 14:22"); the footer drops to the follow-ups (Open session, Always in Harlow Legal). - Loading. A skeleton card: header height kept, two to four
--hoverbars 10 tall, radius 4. - Error. Plain words in the body, the detail in mono, a way out (Retry, Open doctor).
Keyboard and touch
The card is not focusable. Key hints for its actions sit inside their buttons (key-hint chip). On the phone the footer's buttons are 44 (54 for the one primary in a sheet).
Motion
None on the card. Content changes in place; a card that leaves collapses its height over
--motion-tap.
Copy
Header labels are sentence case, 12/600, never mono or caps: "Draft to send", "Permission", "Network", "Tests failed after the merge".
Accessibility
A card with a header is a section labelled by its header text (aria-labelledby). The beacon
dot has the label beside it, so needs-you is never colour alone.
Gaps
Deck
- No shared card class:
.np-card,.pl-card,.gate-card,.cv-tooleach define their own radius (8, 10,--r-3) and padding; make one.cardwith--radius-card. - Held cards on main draw body rules in
--beacon-rule: violet as a border, remove.
App (work/mobile)
- AskCard and TrustCard are inline styles; extract one Card with header and footer slots.
Lumen (work/capsule-pro)
- HeldCardView uses hand-typed sizes and a caps mono label; use
Tokens.Radius.cardand the 12/600 sentence-case label.
native-core
- Settings, Vault, Connections has no card yet. The Connections board (above) is drawn but not built; account-row.md's own Gaps names the same page.