Ctrl K
ComunidadGuías…

DESIGN_SYSTEM.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Lyriks — Design System

Reverse-engineered from the Step 01 mockup, codified as **Tailwind v4 design tokens** in
[`src/app.css`](src/app.css) and a small set of headless-ish **primitives** in
[`src/lib/ui/design-system/`](src/lib/ui/design-system/).

> **One rule:** components compose **tokens only** (`bg-surface`, `text-ink-900`, `rounded-card`,
> `shadow-card`…). No raw hex in components. Re-theming = editing `@theme` in `app.css`, nothing else.

---

## 1. Visual anatomy of the screen

```
┌──────────────────────────────────────────────────────────────────────┐
│  TOP BAR — full width, brand gradient, h-14                            │  ← chrome
├───────────────┬────────────────────────────────────────────────────-─┤
│  SIDEBAR      │  MAIN (canvas, scrolls)                                │
│  dark rail    │   eyebrow · H1 · subtitle                              │
│  w-64         │   ┌── SectionCard (surface, rounded-card, shadow) ──┐  │
│               │   │  field label · control                          │  │
│  · project    │   └─────────────────────────────────────────────────┘ │
│  · nav items  │   …more section cards…                                 │
│  · readiness  │                                                        │
│               ├────────────────────────────────────────────────────-─┤
│               │  BOTTOM BAR — surface, sticky: nav · coherence · save  │  ← chrome
└───────────────┴────────────────────────────────────────────────────-─┘
```

Three regions: **chrome** (top bar + sidebar + bottom bar) frames a single scrolling **canvas** of
stacked **section cards**. Step 01 has 6 content sections (see the feature spec).

---

## 2. Color tokens

All colors live under `@theme` and generate `bg-*`, `text-*`, `border-*` utilities.

### Brand — violet→pink (identity, primary actions, active state)
Aligned to the the v3 mockup palette (the Tailwind violet/pink family).
| Token | Hex | Used for |
|---|---|---|
| `brand-50…300` | `#f5f3ff`→`#c4b5fd` | chips, soft fills, focus ring |
| `brand-400` | `#a78bfa` | soft accents on dark |
| `brand-500` | `#7c3aed` | **the violet** — gradient start, primary solid |
| `brand-600` | `#6d28d9` | hover |
| `brand-700` | `#5b21b6` | pressed |
| `magenta-500` | `#ec4899` | **the pink** — gradient end |

`bg-brand-gradient` → the signature **`linear-gradient(135deg, #7C3AED 0% → #EC4899 100%)`**
(via `brand-500 → magenta-500`). Applied to the **top bar**, the **active sidebar item**, the
**avatar**, and the **primary button** (which also carries `shadow-brand`, the violet glow).
`gradient-warm` (amber→pink) and `glass` (dark blur panel) mirror the mockup's secondary utilities.

### Accent — blue (selection affordance)
The Form-Factor tiles select with **blue** (`#3b82f6`, mockup blue-500), deliberately distinct from
brand violet so "selected" never reads as "primary action". `accent-50` fill + `accent-400` border
+ `accent-500` dot/text.

### Surfaces
| Token | Hex | Role |
|---|---|---|
| `canvas` | `#f8fafc` | app background (mockup lightmode) |
| `surface` | `#ffffff` | cards, top of bottom bar |
| `surface-sunken` | `#f1f5f9` | inset/secondary fields |
| `sidebar` | `#0b0b14` | left rail (mockup ink-900) |
| `sidebar-soft` | `#16161f` | hovered rail item (mockup ink-800) |
| `sidebar-line` | `#1f1f2c` | rail dividers (mockup ink-700) |

Ink text and lines use the **slate** ramp (`ink-900 #0f172a` … `ink-400 #94a3b8`,
`line #e2e8f0`), matching the mockup's lightmode content colors.

### Ink (text) — a 4-step ramp + 2 on-dark
`ink-900` headings · `ink-700` body · `ink-500` muted · `ink-400` labels/hints ·
`ink-on-dark` / `ink-on-dark-muted` for the sidebar.

### Lines
`line` (`#e9e9ee`) default borders · `line-strong` (`#d7d7df`) emphasized / hovered.

### Semantic (status) — each ships a `-500` ink and a `-50` soft background
| Token | Meaning in the UI |
|---|---|
| `success-500` / `success-50` | "Auto-saved", success criteria, readiness "Strong" |
| `warning-500` / `warning-50` | coherence "At risk", project label accent |
| `danger-500` / `danger-50` | failure criteria, coherence "Critical" |

**Score → color** mapping (coherence ring, readiness ring) is centralized in
[`scoreTone()`](src/lib/ui/design-system/tone.ts): `<34` danger · `34–66` warning · `≥67` success.

---

## 3. Typography

Font: **Inter** with a system fallback (`--font-sans`). Roles used across the screen:

| Role | Tailwind | Notes |
|---|---|---|
| Eyebrow (`STEP 01 · INITIALIZATION`) | `text-xs font-semibold uppercase tracking-[0.14em] text-brand-500` | |
| Page title (H1) | `text-3xl font-bold text-ink-900 tracking-tight` | |
| Subtitle | `text-sm text-ink-500` | |
| Field label | `text-[11px] font-semibold uppercase tracking-[0.12em] text-ink-400` | |
| Card value / section title | `text-lg font-semibold text-ink-900` | |
| Body | `text-sm text-ink-700` | |
| Help / hint | `text-xs text-ink-500` | |

---

## 4. Shape, elevation, spacing

- **Radii:** `rounded-field` (`0.625rem`) inputs & tiles · `rounded-card` (`1rem`) section cards ·
  `rounded-pill` chips/buttons-as-pills.
- **Elevation:** `shadow-card` (cards: hairline + soft ambient) · `shadow-pop` (menus/dialogs).
- **Focus:** every interactive element gets `shadow-focus` (3px `brand-200` halo) via a base rule —
  no per-component focus styling needed.
- **Spacing rhythm:** cards `p-6`→`p-7`, `gap-4` grids, `space-y-6` between section cards, content
  column maxed at `max-w-5xl`.

---

## 5. Primitives (`src/lib/ui/design-system/`)

Small, composable Svelte 5 components. Each is a thin, typed wrapper over tokens.

| Component | Purpose |
|---|---|
| `Button.svelte` | `variant: primary \| ghost \| outline \| danger`, `size`, gradient primary |
| `Card.svelte` | surface + `rounded-card` + `shadow-card` + border |
| `SectionCard.svelte` | `Card` with eyebrow icon, title, subtitle slot + content |
| `Field.svelte` | label + control wrapper + optional counter/error |
| `TextInput.svelte` / `Textarea.svelte` | tokenized inputs with char counters |
| `Select.svelte` | native select styled as the mockup dropdown |
| `Chip.svelte` | pill; `tone: brand \| neutral \| success \| warning \| danger` |
| `TagInput.svelte` | add/remove string tags (pain points, criteria) |
| `ToggleTile.svelte` | multi-select tile w/ accent-blue selected state (form factors, sizes) |
| `ScoreRing.svelte` | SVG ring for coherence / readiness, colored by `scoreTone()` |
| `Icon.svelte` | inline SVG set used by chrome + sections |

Primitives are **presentation only** — no data fetching, no domain logic. They receive props and
emit callbacks, keeping the dependency arrow pointing inward (UI → application → domain).

---

## 6. How to extend / re-theme

1. **New color or scale:** add a `--color-*` token in `@theme`. Utilities are generated instantly.
2. **New status:** add `--color-x-500` + `--color-x-50`, extend `Chip` tone + `scoreTone()`.
3. **Brand refresh:** change `brand-*` / `magenta-*` — the gradient, buttons, active nav, focus ring,
   and avatar all follow because they reference the tokens, not literals.
4. **New control:** build it from existing primitives/tokens; never reach for raw hex.