docs GitHub

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).

SurfaceImplementing fileStatus
Deckdeck/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
Appapps/app/src/session/Rows.tsx AskCard, apps/app/src/vault/views.tsx TrustCard (work/mobile)partial
Lumenlocal/capsule/native/Sources/UI/AgentDeskView.swift HeldCardView, UI/PresenceView.swift (work/capsule-pro)partial

Anatomy

  1. Body. Fill --panel, 1 px --rule border, 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 --rule top border, never with gaps or inner boxes.
  2. 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.
  3. Footer (optional). Padding 12 16, gap 8, 1 px --rule top 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").
  4. 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 --focus border plus a 1 px --focus ring. 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:
    1. 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.
    2. 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.
    3. Footer, --rule top 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 --label on 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 --focus outline.
  • 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-2 and 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 --hover bars 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-tool each define their own radius (8, 10, --r-3) and padding; make one .card with --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.card and 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.