# Uncommon design.md

**Public agent contract for on-brand UI.** Load this file when building or redesigning pages for Uncommon Artwork.
**Canonical deep reference:** `/resources/design-system` · `docs/DESIGN-SYSTEM.md`
**In-repo rules:** `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/*.mdc`

Last updated: September 2026

---

## Scope

Use this file when generating or editing:

- Platform marketing (`.platform-landing`)
- Studio / dashboard (`.dashboard-ui`)
- Artist / gallery public sites (`.artist-site`)

Do **not** invent a fourth token world. Do **not** mix ladders across surfaces.

Out of scope: studio write APIs, OAuth app catalogs, generating “AI art,” or treating Uncommon as a generic website builder.

---

## North star — Kanketsu (簡潔)

Less, but complete. Crafted, editorial, intentional.

- Copy says what needs saying; UI shows what needs seeing; nothing competes with the work.
- Warmth comes from craft and restraint, not decoration.
- When in doubt, remove — then ask whether what remains still feels complete.

Voice: refined, understated, confident. No hype. No marketing speak.

---

## Reader and task (structure the page for the job)

Every page shares Uncommon typography/color/spacing language, but **structure follows the reader’s job** — not one template.

| Surface / page | Reader came to… | Lead with | Keep secondary |
|----------------|-----------------|-----------|----------------|
| **Artist site home** | See the work | One focal entry; work owns the stage | Nav, subscribe, theme — recede |
| **Archive / shop** | Scan and open works | Titles + images; spacing over cards | Provenance detail after the hit |
| **Studio Appearance** | Pick theme / type / layout | Three choices only | Do not expose gray ladder, accent pickers, font catalogs, nav sliders |
| **Studio settings / billing** | Complete a decision | Clear status + primary action | Supporting plan detail below |
| **Platform landing hero** | Trust the brand + take one CTA | Brand, one headline, one sentence, one CTA group, one dominant visual | No stats, badges, promo chips, or secondary marketing in the first viewport |
| **Pricing** | Decide whether to pay | Plan decision clarity | Feature theater and decoration |
| **Reports / proposals (generated)** | Decide quickly, audit if needed | Recommendation / answer first | Evidence in full-width tables; caveats honest |

Observable checks:

- The reader’s decision or next action is visible without scrolling past noise.
- Supplied facts survive; do not invent metrics, prices, or testimonials.
- Supporting detail is available without competing with the summary.

---

## Three surfaces — pick one world

| Surface | Root class | Color | Radius | Type |
|---------|------------|-------|--------|------|
| Dashboard | `.dashboard-ui` | `--ds-gray-*`, `--ds-background-*` | 6 / 12 / 16 via materials | `TYPE.*` |
| Artist site | `.artist-site` | `--gray-*`, `--background-*` from paper + ink | 0 page chrome; 6 / 12 floating menus | `SITE_TYPE.*` / `TYPE.*` |
| Platform landing | `.platform-landing` | `--landing-fg`, `--landing-muted`, `--landing-bg` | landing radius classes | Garaje display + `font-body` |

**Imports (use these names — do not reinvent):**

- `@/lib/geist-typography` → `TYPE`, `SITE_TYPE`
- `@/lib/geist-materials` → `MATERIAL`
- `@/lib/dashboard-ui.ts` → dashboard shells
- `@/lib/platform-landing-tokens.ts` → `PLATFORM_LANDING_*` classes

---

## Allowed primitives

### Color — role, then step (100–1000)

| Step | Role |
|------|------|
| 100 | Default component background |
| 200 | Hover background |
| 300 | Active background |
| 400 | Default border |
| 500 | Hover border |
| 600 | Active border |
| 700 | High-contrast background |
| 800 | Hover high-contrast background |
| 900 | Secondary text and icons |
| 1000 | Primary text and icons |

Page planes: `background-100` (canvas), `background-200` (rail / nested).

```tsx
// Dashboard
<div className="bg-(--ds-gray-100) text-(--ds-gray-1000) ring-1 ring-(--ds-gray-400)" />
<p className="text-(--ds-gray-900)" />

// Artist site
<p className="text-(--gray-900)" />

// Landing
<p className="text-(--landing-muted)" />
```

Never pick a hex or opacity by eye for neutrals. Status colors (blue / red / amber / green) are for meaning, not decoration.

### Typography — named roles only

```tsx
import { TYPE, SITE_TYPE } from "@/lib/geist-typography";

<h1 className={TYPE.heading16}>Appearance</h1>
<p className={TYPE.copy13}>Supporting copy.</p>
<label className={TYPE.label14}>Color</label>
<button className={TYPE.button14}>Save</button>

<h1 className={SITE_TYPE.pageTitle}>All works</h1>
<p className={SITE_TYPE.meta}>2024 · Oil on linen</p>
```

Weights: 400 / 500 / 600 only. No `font-bold` (700). Strong emphasis: nest `<strong>`.
Numbers in labels: add `tabular-nums`, do not invent a new size.

### Materials — one preset

```tsx
import { MATERIAL } from "@/lib/geist-materials";

<div className={MATERIAL.medium} />
<div className={MATERIAL.menu} />
```

| Preset | When | Radius |
|--------|------|--------|
| `MATERIAL.base` | Control, input, row | 6 |
| `MATERIAL.small` | Raised chip / well | 6 |
| `MATERIAL.medium` | Card, inset panel | 12 |
| `MATERIAL.large` | Featured panel | 12 |
| `MATERIAL.menu` | Dropdown, popover | 12 |
| `MATERIAL.modal` | Dialog | 12 |
| `MATERIAL.fullscreen` | Sheet | 16 |

Hover/active change fill or stroke (`100→200`, `400→500`), not shadow escalation.

### Landing tokens (document the class names)

| Constant | Use |
|----------|-----|
| `PLATFORM_LANDING_CONTENT_SHELL_CLASS` | Section rail |
| `PLATFORM_LANDING_DISPLAY_CLASS` | Section titles (Garaje) |
| `PLATFORM_LANDING_LEDGER_TITLE_CLASS` | Plan names, step labels |
| `PLATFORM_LANDING_SURFACE_RADIUS_CLASS` | Cards, tables, menus |
| `PLATFORM_LANDING_SURFACE_INNER_RADIUS_CLASS` | Menu rows |
| `PLATFORM_LANDING_CTA_RADIUS_CLASS` | Action buttons |
| `PLATFORM_LANDING_NAV_MENU_PANEL_CLASS` | Header menus |
| `PLATFORM_LANDING_NAV_MENU_ITEM_CLASS` | Items inside header menus |

---

## Layout rules (observable)

1. **Negative space over borders** (artist sites + editorial): separate with `space-y-*` / `gap-*`, not card chrome or hairline dividers between title and body.
2. **Borders belong on** forms, focus rings, dense data tables, true controls — not list rows or provenance blocks.
3. **Evidence tables** use the full width available to them when the page has room.
4. **Loading states move**: spinner (`animate-spin`) or layout-matched shimmer skeleton. Never text-only “Loading…”. Respect `prefers-reduced-motion`.
5. **React:** no `useEffect` / `useLayoutEffect`. Use `useMountEffect()` for mount-only DOM sync only.

---

## Named anti-patterns (never ship these)

Give failures names so they are recognizable. If an output matches one, rewrite.

### Generic SaaS Dashboard
Metric card grids, identical three-column feature rows, purple/indigo accents, Inter/Roboto, “hero metrics” strips. Uncommon is not a B2B analytics product.

### Invented Type
Hand-rolled `text-[13px] font-medium tracking-tight` (or similar) instead of `TYPE.*` / `SITE_TYPE.*`.

### Opacity Guessing
`border-border/45`, `bg-black/5`, `text-black`, `bg-white`, `neutral-*` where numbered Geist / landing tokens exist.

### Card Chrome Default
Border + fill + shadow around editorial rows or provenance when spacing alone would suffice.

### Hero Clutter
Detached badges, floating promo chips, stats, schedule snippets, or secondary CTAs stacked on the first viewport / hero media.

### Gradient Slop
Cyan-on-dark, purple-to-indigo gradients, glassmorphism, glow stacks, multi-layer shadows for “premium.”

### Cream Terracotta Default
Warm cream paper + high-contrast serif display + terracotta accent as a generic “tasteful” AI default. Use Uncommon’s actual surface tokens and faces instead.

### Broadsheet Density
Hairline rules everywhere, zero breathing room, newspaper columns that fight gallery calm.

### Appearance Ladder Leak
Exposing the ten-step gray ladder, accent pickers, independent font catalogs, or nav size sliders to artists.

---

## Copy

- Concrete claims; honest caveats.
- No hype (“revolutionary,” “seamless,” “next-gen”).
- Prefer short sentences. Every word earns its place.
- On artist sites, nothing should outshine the work.

---

## Checklist before shipping

- [ ] Correct surface class (`.dashboard-ui` | `.artist-site` | `.platform-landing`)
- [ ] Page structured for the reader’s job (table above)
- [ ] Colors use numbered steps / landing tokens — no Opacity Guessing
- [ ] Type uses `TYPE.*` / `SITE_TYPE.*` — no Invented Type
- [ ] Surfaces use `MATERIAL.*` or landing radius constants — no Card Chrome Default
- [ ] No named anti-pattern from the list above
- [ ] Loading states animate; reduced motion respected
- [ ] No new `useEffect` without team discussion

---

## How to keep this file current

1. Encode repeated review corrections as **observable** rules (not “feel less cramped”).
2. Put judgment here; put repeatable mechanics in token modules / CSS; put greppable failures in `src/lib/agent-design-contract.ts` tests.
3. When tokens change, update this file, `docs/DESIGN-SYSTEM.md`, `/resources/design-system`, and `.cursor/rules` together.
