---
version: alpha
name: Forge-design-analysis
description: "A dark-first developer workbench for AI agents. Forge anchors on a near-black canvas (#0B0B0E) layered with four ascending surface tiers, a single chromatic accent (Indigo #6366F1) reserved for primary actions and focus, and a warm Coral (#E85A4F) used for destructive / error / brand-warmth moments. The voice is engineering-precise like Linear with editorial warmth borrowed from Claude: a serif display family handles all H1/H2 moments while a humanist sans carries every UI surface. Type is dense (13–14px UI baseline), borders are hairline (1px), radii are restrained (8–12px), and surfaces never use decorative gradients except in two sanctioned places: the auth ambient backdrop and the brand mark. The result is a quietly luxurious agent workbench — dense without feeling cramped, warm without losing focus."

colors:
  # Brand
  primary: "#6366F1"
  primary-hover: "#818CF8"
  primary-active: "#4F46E5"
  primary-subtle: "rgba(99, 102, 241, 0.12)"
  on-primary: "#FFFFFF"

  # Canvas & surfaces (dark — default)
  canvas: "#0B0B0E"
  surface-1: "#16161A"
  surface-2: "#1A1A1E"
  surface-3: "#222226"
  surface-4: "#2A2A2E"

  # Hairlines
  hairline: "#2A2A2E"
  hairline-strong: "#3A3A40"
  hairline-focus: "#6366F1"

  # Ink (text)
  ink: "#FAFAF9"
  ink-muted: "#8E8E93"
  ink-subtle: "#6B6B70"
  ink-tertiary: "#4A4A50"

  # Semantic accents
  accent-coral: "#E85A4F"
  accent-green: "#32D583"
  accent-amber: "#FFB547"

  # Status
  success: "#32D583"
  warning: "#FFB547"
  error: "#E85A4F"
  info: "#6366F1"

  # Inverse (light theme)
  canvas-light: "#FFFFFF"
  surface-1-light: "#F5F5F4"
  surface-2-light: "#FAFAF9"
  surface-3-light: "#F0F0EE"
  surface-4-light: "#E8E8E6"
  hairline-light: "#E8E8E6"
  hairline-strong-light: "#D0D0CE"
  ink-light: "#1A1A1E"
  ink-muted-light: "#6B6B70"
  ink-subtle-light: "#8E8E93"
  ink-tertiary-light: "#B0B0B4"

  # Code/terminal
  code-bg: "#1A1A1E"
  code-ink: "#FAFAF9"
  code-comment: "#6B6B70"
  code-keyword: "#818CF8"
  code-string: "#32D583"
  code-number: "#FFB547"

typography:
  # Display — serif, editorial moments (auth, hero, empty states)
  display-xl:
    fontFamily: "Tiempos Headline, Iowan Old Style, 'Georgia', serif"
    fontSize: 56px
    fontWeight: 400
    lineHeight: 1.08
    letterSpacing: -1.5px
  display-lg:
    fontFamily: "Tiempos Headline, Iowan Old Style, 'Georgia', serif"
    fontSize: 40px
    fontWeight: 400
    lineHeight: 1.12
    letterSpacing: -0.8px
  display-md:
    fontFamily: "Tiempos Headline, Iowan Old Style, 'Georgia', serif"
    fontSize: 28px
    fontWeight: 400
    lineHeight: 1.2
    letterSpacing: -0.4px

  # Headings — sans, for in-app panels & section titles
  heading-lg:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 18px
    fontWeight: 600
    lineHeight: 1.35
    letterSpacing: -0.1px
  heading-md:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 15px
    fontWeight: 600
    lineHeight: 1.4
    letterSpacing: 0
  heading-sm:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 600
    lineHeight: 1.4
    letterSpacing: 0

  # Body — the UI baseline (forge defaults to 13–14px)
  body-md:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
    letterSpacing: 0
  body-sm:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 400
    lineHeight: 1.5
    letterSpacing: 0
  body-xs:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.45
    letterSpacing: 0

  # Caption / eyebrow / meta
  caption:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 11px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0.4px
    textTransform: uppercase
  meta:
    fontFamily: "Inter, 'Geist Sans', system-ui, sans-serif"
    fontSize: 11px
    fontWeight: 400
    lineHeight: 1.4
    letterSpacing: 0

  # Monospace — terminal, code blocks, command palette
  mono-md:
    fontFamily: "'Geist Mono', 'JetBrains Mono', 'Fira Code', ui-monospace, monospace"
    fontSize: 13px
    fontWeight: 400
    lineHeight: 1.55
  mono-sm:
    fontFamily: "'Geist Mono', 'JetBrains Mono', 'Fira Code', ui-monospace, monospace"
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.5

spacing:
  unit: 4px
  scale: [0, 2, 4, 6, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80]

radii:
  none: 0
  sm: 4px       # tags, small chips
  md: 8px       # inputs, small cards
  lg: 12px      # cards, panels, dialogs
  xl: 16px      # hero cards, login card
  pill: 9999px  # toggle, badge

shadows:
  none: none
  sm: "0 1px 2px rgba(0,0,0,0.25)"
  md: "0 4px 12px -2px rgba(0,0,0,0.35)"
  lg: "0 8px 32px -8px rgba(0,0,0,0.45)"
  xl: "0 16px 48px -16px rgba(0,0,0,0.55)"
  focus-ring: "0 0 0 3px rgba(99,102,241,0.35)"
---

# Forge — Design System

> A dark-first agent workbench. **Linear**'s engineering precision crossed with **Claude**'s editorial warmth.

---

## 1. Visual Theme & Atmosphere

**Mood**: Quietly luxurious. Dense without feeling cramped. Engineering-grade without being cold.

**Density**: UI baseline is **13–14px**. Every panel earns its space — there is no decorative padding. Sidebar items are 32px tall, cards have 20px internal padding, sections breathe with 24px gaps.

**Atmosphere**: Near-black canvas (`#0B0B0E`) with four ascending surface tiers. Light reads from above — elevated surfaces are slightly lighter, not darker. Hairline 1px borders carry the grid. A single chromatic accent (Indigo) carries every focus / active / primary state. Decorative gradients are forbidden except in the auth ambient backdrop and the brand mark.

**Philosophy**: *Tools, not posters.* Every pixel serves the workflow. Editorial moments (serif headings, warm coral) appear only at human entry points — login, empty states, brand surfaces — to remind the user that a person built this for them.

---

## 2. Color Palette & Roles

### Brand
| Token | Hex | Role |
|---|---|---|
| `primary` | `#6366F1` | Primary CTAs, active tab, focus ring, selected list item |
| `primary-hover` | `#818CF8` | Hover state on primary |
| `primary-active` | `#4F46E5` | Pressed state |
| `primary-subtle` | `rgba(99,102,241,0.12)` | Selected row background, active chip background |

### Canvas & Surfaces (dark default)
| Token | Hex | When to use |
|---|---|---|
| `canvas` | `#0B0B0E` | Page background, outside all panels |
| `surface-1` | `#16161A` | Sidebar, top bar, primary panels |
| `surface-2` | `#1A1A1E` | Cards inside surface-1, inputs |
| `surface-3` | `#222226` | Hover on surface-2, secondary buttons hovered |
| `surface-4` | `#2A2A2E` | Pressed/active inside surface-3 |

### Hairlines
| Token | Hex | When |
|---|---|---|
| `hairline` | `#2A2A2E` | Default 1px panel & input border |
| `hairline-strong` | `#3A3A40` | Hover border, divider in dense lists |
| `hairline-focus` | `#6366F1` | Focused input, selected tab underline |

### Ink (text)
| Token | Hex | When |
|---|---|---|
| `ink` | `#FAFAF9` | Primary text, headings |
| `ink-muted` | `#8E8E93` | Secondary text, descriptions |
| `ink-subtle` | `#6B6B70` | Helper text, timestamps |
| `ink-tertiary` | `#4A4A50` | Disabled, placeholder, decorative caption |

### Semantic
| Token | Hex | Reserved for |
|---|---|---|
| `accent-coral` `#E85A4F` | Destructive (delete), errors, brand-warmth (logo gradient stop) |
| `accent-green` `#32D583` | Success, "connected", running task |
| `accent-amber` `#FFB547` | Warning, "pending", needs-attention |

### Anti-patterns
- ❌ Never use raw white `#FFFFFF` for text on canvas — use `ink` (`#FAFAF9`)
- ❌ Never use multiple accent colors in one screen (only `indigo` + at most one semantic color)
- ❌ Never put decorative gradients on cards, buttons, or backgrounds outside auth + brand mark

---

## 3. Typography Rules

### Two-family system
| Family | Use | Stack |
|---|---|---|
| **Serif** (editorial) | `display-*` only — auth, empty states, hero | `Tiempos Headline → Iowan Old Style → Georgia → serif` |
| **Sans** (UI baseline) | Everything else — buttons, body, navigation, labels | `Inter → Geist Sans → system-ui → sans-serif` |
| **Mono** | Terminal, code blocks, command palette, IDs, paths | `Geist Mono → JetBrains Mono → Fira Code → ui-monospace` |

### Hierarchy
| Token | Size / Weight | Where |
|---|---|---|
| `display-xl` | 56 / 400 serif | Auth page H1, marketing hero |
| `display-lg` | 40 / 400 serif | Empty state title |
| `display-md` | 28 / 400 serif | Login card title (already in use) |
| `heading-lg` | 18 / 600 sans | Section title inside a view |
| `heading-md` | 15 / 600 sans | Card title |
| `heading-sm` | 13 / 600 sans | Group label inside a card |
| `body-md` | 14 / 400 sans | Default copy |
| `body-sm` | 13 / 400 sans | Sidebar items, table rows, dense lists |
| `body-xs` | 12 / 400 sans | Tooltips, helper text |
| `caption` | 11 / 500 / +0.4 / UPPER | Eyebrow, divider label ("OR WITH EMAIL"), section kicker |
| `mono-md` | 13 / 400 | Code, IDs, paths |

### Rules
- One serif per page — never mix two display sizes
- Headings never have `text-transform`; that's reserved for `caption`
- Numbers in tables and timestamps use `font-variant-numeric: tabular-nums`
- Don't bold inside `body-*`; use `heading-sm` instead

---

## 4. Component Stylings

### Button

| Variant | Height | Bg | Border | Ink | Radius |
|---|---|---|---|---|---|
| `primary` | 40 / 36 / 32 | `primary` | none | `on-primary` | `md` (8px) |
| `secondary` | 40 / 36 / 32 | `surface-2` | `1px hairline` | `ink` | `md` |
| `ghost` | 32 | transparent | none | `ink-muted` | `md` |
| `danger` | 36 | transparent | `1px accent-coral` | `accent-coral` | `md` |

**States**
- `hover`: lift one surface tier (`surface-2 → surface-3`) for secondary; `primary → primary-hover` for primary
- `active`: pressed surface (`primary-active`) + scale 0.98
- `focus`: 3px `primary` ring with 35% opacity (`shadow.focus-ring`)
- `disabled`: 50% opacity, no hover

**Anti-patterns**: no shadow on buttons (only the auth submit may have `shadow.sm`); no gradients; no border on primary

### Input

- Height **40px** (form), **36px** (settings), **32px** (inline edit)
- `bg: surface-2`, `border: 1px hairline`, `radius: md` (8px), `padding: 0 12px`
- Placeholder: `ink-tertiary`
- Focus: `border-color: primary`, **no** outer ring on inputs (ring is reserved for buttons / interactive surfaces)
- Read-only: `bg: canvas`, ink dimmed to `ink-muted`
- **Autofill kill switch**: every form sets `autoComplete="off"` + uses `readOnly` + `onFocus` unlock pattern. See `src/app/login/login-form.tsx` reference implementation.

### Card / Panel

- `bg: surface-1`, `border: 1px hairline`, `radius: lg` (12px), `padding: 20px`
- Internal section spacing: 16px
- Card title is `heading-md` (15/600)
- Nested cards go to `surface-2`

### Sidebar Item

- Height **32px**, padding `0 12px`, radius `md` (8px)
- Resting: transparent
- Hover: `bg surface-2`
- Active: `bg primary-subtle`, ink `primary`, left 2px `primary` accent rail
- Icon size 16, gap 8

### Switch (toggle)

- Track 40×22 pill, knob 18 circle, padding 2
- Off: track `surface-4`, knob `ink`
- On: track `accent-green` (for "enabled/connected") or `primary` (for "selected mode")
- Transition: 200ms ease

### Select (`CustomSelect`)

- Same shell as Input
- Menu: `bg surface-2`, `border hairline`, `radius lg`, `shadow lg`
- Item height 32, hover `surface-3`, selected `primary-subtle`

### Tabs

- Bottom-border tabs only
- Resting label: `ink-muted` 13/500
- Hover: `ink`
- Active: `ink` + 2px `primary` underline
- No pills, no chips, no decorative bg

### Dialog / Modal

- Centered, max-width 480 (form) / 720 (content)
- `bg surface-1`, `border 1px hairline`, `radius xl` (16px), `shadow xl`
- Header `heading-lg`, body `body-md`, footer right-aligned 8px gap
- Backdrop: `rgba(0,0,0,0.6)` + 6px blur

### Badge / Pill

- Height 20, padding `0 8`, radius `pill`, `body-xs / 500`
- `neutral`: `surface-3` bg + `ink-muted` ink
- `info`: `primary-subtle` bg + `primary` ink
- `success` / `warning` / `error`: 12% bg of accent + accent ink

### Code block

- `bg surface-2`, `border 1px hairline`, `radius md`, `padding 12 16`
- `font: mono-md`
- Inline code: `bg surface-3`, `padding 2 6`, `radius sm`

### Command Palette / Mention

- Floating panel, `bg surface-2`, `border hairline`, `radius lg`, `shadow xl`
- Search input is borderless, separated by 1px hairline
- Result row 36 high, selected `primary-subtle`

---

## 5. Layout Principles

### App skeleton
```
╭───────────┬──────────────────────────────────────╮
│  Sidebar  │  Main view                            │
│  240–280  │  fluid                                │
│  surface-1│  canvas                               │
├───────────┴──────────────────────────────────────┤
│  Status bar (optional, 28px, surface-1)           │
╰──────────────────────────────────────────────────╯
```

### Spacing scale
**Always use 4px base**: 4 · 8 · 12 · 16 · 20 · 24 · 32 · 48 · 64
- Inside a card: 16 between sections, 8 between label+control
- Between cards: 16
- Between page sections: 32
- Page top padding: 24, bottom 48

### Grid
- 12-column inside content area
- Gutter 16
- Max content width 1280 for marketing/landing, **no max** for app views (workbench is fluid)

### Whitespace philosophy
- *Density first*: prefer 12–16px gaps over 24+
- *Hairlines, not padding*: divide with 1px border, not 32px white space
- *Vertical rhythm*: keep label-control-help triplets at 6-8-4 internal spacing

---

## 6. Depth & Elevation

### Surface hierarchy
```
canvas (0B0B0E) ─ outside everything
  └ surface-1 (16161A) ─ sidebar, top bar, primary cards
      └ surface-2 (1A1A1E) ─ nested cards, inputs
          └ surface-3 (222226) ─ hover state
              └ surface-4 (2A2A2E) ─ active/pressed
```

### Shadow ladder (use sparingly)
| Token | When |
|---|---|
| `shadow.sm` | Auth submit button only |
| `shadow.md` | Floating select/menu |
| `shadow.lg` | Command palette, popovers |
| `shadow.xl` | Modal, login card |
| `shadow.focus-ring` | Focused button |

**Rule**: Cards, panels, and inputs use **hairline borders, not shadows**. Shadows are reserved for *floating* surfaces.

---

## 7. Do's & Don'ts

### ✅ Do
- Use a single accent (Indigo) per screen
- Layer surfaces with the `surface-1 → 4` ladder, not arbitrary hexes
- Keep body copy at 13–14px
- Use serif **only** for `display-*` (≤ 3 occurrences per page)
- Use hairline 1px borders to divide regions
- Tabular-nums for numbers in tables
- Pin destructive actions to `accent-coral` and keep them isolated from primary

### ❌ Don't
- Don't use decorative gradients on cards or buttons
- Don't bold inside `body-*` — promote to `heading-sm`
- Don't use shadow + border together on the same element
- Don't mix indigo + coral + amber on the same surface
- Don't use raw white `#FFFFFF` for text
- Don't use radius larger than `xl` (16px) anywhere in app chrome
- Don't autofill credential fields outside login (see auth section)

---

## 8. Responsive Behavior

### Breakpoints
| Name | Min | Behavior |
|---|---|---|
| `sm` | 640 | Sidebar collapses to icons (56px) |
| `md` | 768 | Sidebar 220px, single content column |
| `lg` | 1024 | Sidebar 240, side panels appear |
| `xl` | 1280 | Full 3-pane (sidebar + main + right inspector) |
| `2xl` | 1536 | Max gutter widens; nothing else |

### Touch targets
- Minimum 32×32 hit area; for `sm` viewport, promote to 40×40
- Switches and toggles enlarge knob to 22 on touch

### Collapsing rules
- Below `lg`: right panels become bottom drawer
- Below `md`: top bar action group collapses into overflow menu
- Below `sm`: sidebar becomes a sheet (modal drawer) opened by hamburger

---

## 9. Agent Prompt Guide

### Quick reference (copy this when asking an agent to build a Forge UI)

> Build the UI for **Forge** using its design system:
> - **Canvas**: `#0B0B0E`. **Cards**: `#16161A` with `1px solid #2A2A2E` border, `12px radius`, `20px padding`.
> - **Primary accent**: indigo `#6366F1` — buttons, focus, active states only. Hover `#818CF8`.
> - **Text**: 14px Inter for body, 13px for dense lists, serif (Tiempos / Iowan Old Style fallback) only for H1/H2 display moments.
> - **Buttons**: 40px tall, 8px radius, `bg #6366F1` for primary, `bg #1A1A1E + border #2A2A2E` for secondary.
> - **Inputs**: 40px tall, 8px radius, `bg #1A1A1E`, `border #2A2A2E`, focus border `#6366F1`, no outer ring.
> - **Spacing**: 4px base scale (4/8/12/16/20/24/32). Between cards 16, inside cards 16, page top 24.
> - **Density**: dev-tool tight — never larger than 14px unless it's a serif H1.
> - **No decorative gradients** except auth ambient backdrop.

### Ready-to-paste palette (Tailwind config)
```ts
colors: {
  canvas: '#0B0B0E',
  surface: { 1: '#16161A', 2: '#1A1A1E', 3: '#222226', 4: '#2A2A2E' },
  hairline: { DEFAULT: '#2A2A2E', strong: '#3A3A40' },
  ink: { DEFAULT: '#FAFAF9', muted: '#8E8E93', subtle: '#6B6B70', tertiary: '#4A4A50' },
  primary: { DEFAULT: '#6366F1', hover: '#818CF8', active: '#4F46E5' },
  coral: '#E85A4F', green: '#32D583', amber: '#FFB547',
}
```

### Voice & tone (microcopy)
- Headings are imperative or noun phrases: "Save template", "New workspace" — not "Click here to save"
- Helper text is fragment-style, lowercase first letter when continuing a label: "minimum 8 characters"
- Errors are diagnostic, not apologetic: "Email already in use" — not "Sorry, we couldn't…"
- Empty states use the serif `display-md` + a single CTA

---

## Appendix A — Mapping to existing Forge tokens

Current Forge variables already align ~90% with this spec. Migration:

| Current var (`src/app/globals.css`) | Action |
|---|---|
| `--bg-page` `#0B0B0E` | ✅ Keep — becomes `canvas` |
| `--bg-surface` `#16161A` | ✅ Keep — becomes `surface-1` |
| `--bg-elevated` `#1A1A1E` | ✅ Keep — becomes `surface-2` |
| `--bg-hover` `#222226` | ✅ Keep — becomes `surface-3` |
| `--bg-active` `#2A2A2E` | ✅ Keep — becomes `surface-4` |
| `--text-primary` `#FAFAF9` | ✅ Keep — becomes `ink` |
| `--text-secondary` `#8E8E93` | ✅ Keep — becomes `ink-muted` |
| `--border-subtle` `#2A2A2E` | ✅ Keep — becomes `hairline` |
| `--border-strong` `#3A3A40` | ✅ Keep — becomes `hairline-strong` |
| `--accent-indigo` `#6366F1` | ✅ Keep — becomes `primary` |
| *(new)* `--primary-hover` `#818CF8` | Add |
| *(new)* `--primary-subtle` `rgba(99,102,241,.12)` | Add |
| `--accent-coral` `#E85A4F` | ✅ Keep — error / destructive |
| `--accent-green` `#32D583` | ✅ Keep — success |
| `--accent-amber` `#FFB547` | ✅ Keep — warning |

**Conclusion**: This DESIGN.md is a *codification* of where Forge already is, with three deltas:
1. Introduce `primary-hover` and `primary-subtle` so hover/selected states stop using ad-hoc opacity
2. Formalize the **8-step type scale** (today the codebase has scattered `text-[XXpx]`)
3. Adopt the **8-tier component grammar** (Button / Input / Card / Switch / Select / Tab / Dialog / Badge) and stop inlining them in views

Estimated migration effort to reach 100% conformance: **5–7 engineer-days**, see breakdown in commit history & task plan.
