# Solid Design System

A compact guide to the visual language of Solid, a minimal workspace where users direct an autonomous agent through conversation. Use this as the starting point for any new surface, pattern, or component.

This document captures the *character* of Solid, not every pixel. It is meant to give any designer enough foundation to produce work that feels at home in the product, without prescribing a particular implementation. If something here produces a worse result than an alternative, flag it and suggest a change. The system should evolve.

For product behavior and flows, see `product-spec/`. For working reference implementations, see `reference/`.

---

## Design Character

Solid draws from editorial terminals: clean type, generous whitespace, flat surfaces, restrained interaction. The product's point of view is that chat is the control layer, so the interface stays simpler than the system beneath it.

**Principles**

- **Structure over decoration.** Typography, spacing, and alignment carry hierarchy. Color and ornament are last resorts.
- **Earn trust through restraint.** Every element justifies its presence. Competence speaks quietly.
- **Defer to content.** The interface recedes so the user's work and the agent's output take center stage.
- **Honest by default.** No marketing-speak, no gamification, no manipulative patterns.
- **Encourage agency.** Reward exploration. Never punish curiosity.

**Visual attributes**

- Monochrome-first. Black, white, and gray. Non-gray color only when functionally necessary.
- Generous whitespace. Thin dividers. Flat surfaces.
- No gradients, glow, glossy effects, or heavy shadows.
- No neon or "AI-aesthetic" treatments.

**Logo**

A solid black hexagon (flat-topped) with slightly rounded corners. Always rendered in the primary text color. No outlines, gradients, or color variants.

---

## Color

A monochrome foundation plus a small set of utility colors for state and feedback. Use non-gray color only when it does real work: primary actions, destructive states, status signals, or unread cues.

| Role | Value | Use |
|---|---|---|
| Background | `#ffffff` | Page, card, modal, input fills |
| Sidebar background | `#fafafa` | Sidebar only |
| Text primary | `#0a0a0a` | Headings, body, primary button fills |
| Text secondary | `#666666` | Descriptions, supporting copy |
| Text tertiary | `#999999` | Metadata, hints, timestamps, placeholders |
| Border | `#e5e5e5` | Dividers, card and input borders |
| Hover | `#f5f5f5` | Hover background on interactive surfaces |
| Active | `#e8e8e8` | Background for selected sidebar items |
| Message bubble | `#f0f0f0` | User message background only |
| Unread | `#3d8ec4` | Unread dot indicator only |
| Destructive | `#d4382c` | Delete, remove, critical actions, error text |
| Status amber | `#D97706` | Waiting / pending status dot |
| Status green | `#16a34a` | Active / ready status dot |

Dedicated success and warning colors aren't part of the palette. Structure and copy usually carry those states without dedicated color. Add them only when the monochrome system genuinely falls short.

---

## Typography

Two families, no others.

- **Geist Sans** — conversation, UI chrome, inputs, data, labels. The default for everything.
- **Geist Mono** — reserved for structured, machine-like text: access codes, phone numbers, verification codes, inline code fragments. Don't use it for decoration or personality.

**Hierarchy**

| Role | Size | Weight | Notes |
|---|---|---|---|
| Chat message body | 16px | 400 | Generous line-height (~1.65) |
| Composer input | 16px | 400 | Matches the message body |
| Page title | 20px | 600 | Tight tracking (~-0.02em) |
| Workspace name | 16px | 600 | Slight tracking inward |
| Section heading | 15px | 500 | Card titles, section headers |
| UI body | 14px | 400 | Nav, descriptions, sidebar items |
| Section label / badge | 11px | 500 | Uppercase, wide tracking (~0.05em) |
| Metadata, timestamps | 12–13px | 400 | Tertiary color |
| Numeric data (credits, counts) | 13–14px | 400–500 | — |

The hierarchy relies on a few well-chosen sizes rather than many. If you need a size outside this range, first ask whether the existing scale already covers it.

---

## Space and Rhythm

Solid reads calm because the spacing gives it room. When in doubt, add space rather than remove it.

- **Content columns** are centered with a max-width. Chat conversations sit at ~720px. Standalone pages (onboarding, subscription, profile) use 480–800px depending on content.
- **Section spacing** between major blocks is 32–48px.
- **Conversational rhythm.** User messages get less breathing room below (~32px) than agent turns (~44px), producing a two-beat cadence between exchanges.
- **Dividers** are a single thin line. Avoid panels, boxed sections, or tinted containers unless they're doing structural work.

**Border radius scale**

Small for controls, larger for surfaces. Stay within this range:

| Element | Radius |
|---|---|
| Buttons, small controls | 6–8px |
| Input fields, sidebar items | 8px |
| Dropdowns, popovers | 10px |
| Cards, modals | 10–14px |
| Composer box | 16px |

**Responsive breakpoints**

| Name | Width | Character |
|---|---|---|
| Compact | <768px | Phones, touch-primary. Sidebar collapses behind a toggle. |
| Regular | 768–1023px | Tablets and small laptops. Both touch and pointer expected. |
| Wide | ≥1024px | Desktop, pointer-primary. Resizable sidebar. |

Touch targets are 44px minimum on compact and regular. Wide viewports can go denser (24px minimum).

---

## Components

Each component is described by character and role. For exact sizing, padding, and transitions, see `reference/`.

### Buttons

- **Primary** — dark fill, light text. One per view, for the single most important action. Subtle darken on hover.
- **Secondary** — white fill, dark text, thin border. For supporting actions. Border quietens or darkens slightly on hover.
- **Disabled / current state** — muted text and border, no hover effect. Communicates a current selection, not a broken control.
- **Text button** — no background, no border. For tertiary actions (cancel, log out, manage). Secondary or tertiary color at rest; primary on hover.
- **Back button** — icon-only chevron-left. Subtle hover background. Used in artifact headers and overlays. No text label.
- **Inline action** — "Open →" style, sits inside a card or row. No background. Slight opacity shift on hover.

### Inputs

- **Composer box** — rounded bordered container holding an auto-growing textarea and a small bottom toolbar (attach on the left, send or stop on the right). The border stays quiet and doesn't change on focus. Files appear as compact chips above the textarea.
- **Bordered input** — standard form field for promo codes, inline rename, etc. Thin border, subtle focus state using tertiary color. Never blue.
- **Input row** — a capsule that wraps a borderless field and an action button as a single unit. Used for access codes, phone numbers, verification codes. Structured data fields override to mono for easier scanning.

### Cards

- **Result card** — inline summary of a completed agent output. Thin border, no fill at rest, soft background on hover. The whole card is clickable, opening the artifact.
- **Metric card** — minimal stat display. Small-caps label, emphasized value, muted change indicator.
- **Tier card** — used on the subscription flow. Badge, plan name, price, savings line, contextual action. When a discount is active, shows the struck-through original price next to the discounted price. Never uses "sale" badges or urgency language.

### Modals

Centered overlay with a soft backdrop. Flat surface, generous padding. Title, body, right-aligned actions. Fade in with a subtle scale. No drawers or side panels unless they serve a clear functional purpose.

### Dropdowns and popovers

White fill, thin border, soft shadow. Items use tight padding and a small radius. Items highlight with the hover background on interaction.

### Sidebar items

A single row with a type icon on the left and the item name. Agents use a filled robot icon in secondary color, which gives them more visual weight than artifacts. Artifacts use a stroked type icon in tertiary color (app, doc, link). Agent items with active work show a right-aligned spinner; completed-but-unseen work shows an unread dot instead.

### Section labels

Small, uppercase, wide tracking, tertiary color. Used across sidebar, profile, and standalone pages. Quiet by design. They orient without competing.

### Thinking block

Defined in `product-spec/thinking-block.md`. Keep that as the single source of truth.

---

## Interaction Patterns

### Hover-revealed actions

Cards and rows should look complete at rest. Most of the time, the user is not hovering, so the resting state is the primary design target.

**Rule:** hover-revealed actions must not reserve layout space at rest. No invisible buttons pushing content around, no phantom gaps.

Three approved patterns:

1. **Absolute positioning.** The action sits in a corner of its container, out of flow.
2. **Content swap.** A label replaces another in place on hover (e.g., "Selected" → "Remove").
3. **Row expand.** The action collapses to zero width at rest and expands on row hover with a short delay, so casual mouse movement doesn't trigger it.

If the action is a text button ("Remove", "Change"), underline it so it reads as clickable at a glance.

### Transitions

Short, subtle, functional. No springs or bounces.

| Property | Duration |
|---|---|
| Hover states (background, color, border) | ~0.12s |
| Show / hide, fade, scale | ~0.15s |

No motion lasts longer than ~0.2s. Respect `prefers-reduced-motion`. Disable animation entirely when it's set.

### Status indicators

- **Spinner** — a thin 270° arc, rotating smoothly. For in-progress work (e.g., a running agent in the sidebar). Uses primary text color so it stands out from static icons.
- **Unread dot** — a small filled circle in the unread color. For completed-but-unseen states. The dot is the whole signal. Don't also bold the name.
- **Pulsing dot** — slow opacity pulse on a status color. For ambient active states (e.g., "Solid is at capacity").

### Scrollbar

Thin and quiet. A light gray thumb on a transparent track, darkening slightly on hover. No accents, no wide tracks.

---

## Writing

Copy is part of the design. It should sound like a person wrote it.

- No em dashes in product, marketing, onboarding, or UI copy. Use periods, commas, or colons.
- No marketing-speak. No gamification. No urgency pressure.
- Prefer "when" over "if" for any state the user will reach.
- Errors are direct and offer a path forward. No alarm, no blame.

---

## Conventions

Current defaults. They exist to keep things consistent, not to prevent better ideas.

### Prefer

- Tokens over hardcoded values
- Whitespace and structure for hierarchy, over color or weight
- Monochrome hover states
- Tertiary color for anything that should recede
- Semantic HTML (`<nav>`, `<dialog>`, `<button>`, `<main>`)
- The type and radius scales defined above

### Avoid

- Gradients, glow, glossy effects, or heavy shadows
- Decorative color (tinted backgrounds, colored borders, brand accents)
- Geist Mono outside of structured or machine-like text
- Panels or drawers without a clear functional purpose
- Redundant information already visible elsewhere
- Animations longer than ~0.2s, or spring / bounce easing
- Blue focus rings (use a tertiary border instead)
- Em dashes in user-facing copy

### When a convention doesn't fit

Flag it. Explain why. Suggest what this document should say instead. `design.md` is meant to evolve with the product, not hold it in place.
