# ROA2WEB Design System
**Version:** 1.0.0 | **Updated:** 2026-03-23 | **Status:** Source of Truth
---
## 1. Design Philosophy
ROA2WEB is an ERP application for accounting and financial data management. The design prioritizes:
- **Data density over whitespace** — Users process hundreds of records daily; every pixel earns its space
- **Scan-friendly hierarchy** — Bold totals, muted labels, color-coded sections guide the eye
- **Compact, not cramped** — 32px input height, 8px gaps, systematic spacing scale
- **Professional restraint** — No decorative elements, no hero sections, no gratuitous animation
- **Trust at the pixel level** — Financial data demands precision; misaligned inputs erode confidence
- **System fonts for speed** — No custom font loading; native OS typography feels fast and familiar
- **Progressive disclosure** — Show summary first, reveal detail on demand (collapsible sections, tooltips, bottom sheets)
---
## 2. Visual Identity
### Brand Colors
| Role | Token | Hex (Light) | Usage |
|------|-------|-------------|-------|
| Primary | `--color-primary` | #2563eb | Actions, links, focus rings, active states |
| Primary Dark | `--color-primary-dark` | #1d4ed8 | Hover states, pressed buttons |
| Success | `--color-success` | #059669 | Approvals, positive values, confirmations |
| Warning | `--color-warning` | #d97706 | Pending states, caution alerts, mismatches |
| Error | `--color-error` | #dc2626 | Rejections, validation errors, negative values |
| Info | `--color-info` | #0891b2 | Informational badges, OCR hints |
### Surface Hierarchy
```
Ground (#f8fafc) → Section → Card (#ffffff) → Overlay
↓ darkest ↓ lightest ↓ modal/dropdown
```
Each level uses progressively elevated surface tokens. In dark mode, the scale inverts (darker = lower, lighter = higher).
| Token | Light | Dark | Purpose |
|-------|-------|------|---------|
| `--surface-ground` | #f8fafc | #0f172a | Page background |
| `--surface-card` | #ffffff | #1e293b | Card/container backgrounds |
| `--surface-hover` | #f1f5f9 | #334155 | Hover states, chips |
| `--surface-border` | #e2e8f0 | #475569 | Borders, dividers |
| `--text-color` | #111827 | #f9fafb | Primary text |
| `--text-color-secondary` | #6b7280 | #d1d5db | Labels, hints, metadata |
> **Full palette reference**: [DESIGN_TOKENS.md](./DESIGN_TOKENS.md)
---
## 3. Color System
### Semantic Color Roles
Always use semantic tokens, never raw hex values:
```css
/* Backgrounds */
background: var(--surface-card); /* Cards, modals */
background: var(--surface-ground); /* Page background */
background: var(--surface-hover); /* Hover states, chips */
/* Text */
color: var(--text-color); /* Primary text */
color: var(--text-color-secondary); /* Labels, hints */
/* Borders */
border-color: var(--surface-border); /* Standard borders */
```
### Status Color Scales
Each status has a 50-900 scale. Use **100** for backgrounds, **800** for text in light mode:
| Status | Background | Text | Border | Use For |
|--------|-----------|------|--------|---------|
| Success | `--green-100` | `--green-800` | `--green-300` | Approvals, positive values, OCR high confidence |
| Warning | `--yellow-100` | `--yellow-800` | `--yellow-300` | Pending, caution, OCR medium confidence |
| Error | `--red-100` | `--red-800` | `--red-300` | Rejections, errors, OCR low confidence |
| Info | `--blue-100` | `--blue-800` | `--blue-300` | Informational, OCR hints, categorization |
### OCR Confidence Colors
| Level | Threshold | Background | Text | Icon |
|-------|-----------|-----------|------|------|
| High | >= 85% | `--green-100` | `--green-800` | `pi-check-circle` |
| Medium | >= 60% | `--yellow-100` | `--yellow-800` | `pi-exclamation-circle` |
| Low | < 60% | `--red-100` | `--red-800` | `pi-question-circle` |
### Color-Coded Form Sections
- **Green background** (`--green-50`): Financial values (TOTAL, payments, TVA)
- **Blue background** (`--blue-50`): Categorization (expense type, description)
- **Cyan background** (`--cyan-50`): Client/B2B information
- **No background**: Standard form fields (supplier, document)
---
## 4. Typography
### Font Stack
```css
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-family: var(--font-mono); /* For financial values, code */
```
### Scale
| Token | Size | Usage |
|-------|------|-------|
| `--text-xs` | 12px | Labels, badges, metadata, timestamps, hints |
| `--text-sm` | 14px | Table cells, form inputs, secondary text, buttons |
| `--text-base` | 16px | Body text, primary content (default) |
| `--text-lg` | 18px | Subheadings |
| `--text-xl` | 20px | Card titles, section headings |
| `--text-2xl` | 24px | Page titles, metric values, KPI numbers |
| `--text-3xl` | 32px | Dashboard hero numbers |
| `--text-4xl` | 40px | Reserved for exceptional emphasis |
### Weight Rules
| Token | Value | Usage |
|-------|-------|-------|
| `--font-normal` | 400 | Body text, table cells, descriptions |
| `--font-medium` | 500 | Labels, buttons, badges, emphasis |
| `--font-semibold` | 600 | Headings, financial totals, card titles |
| `--font-bold` | 700 | TOTAL labels, strong emphasis, alerts |
### Financial Numbers
All financial values use `font-variant-numeric: tabular-nums` for column alignment.
---
## 5. Spacing & Layout
### Spacing Scale
| Token | Value | Primary Use |
|-------|-------|------------|
| `--space-xs` | 4px | Icon gaps, badge padding, tight internal spacing |
| `--space-sm` | 8px | Related item gaps, compact form spacing |
| `--space-md` | 16px | Standard component padding, section gaps |
| `--space-lg` | 24px | Card padding, section separation |
| `--space-xl` | 32px | Page margins, major separations |
| `--space-2xl` | 48px | Layout sections |
| `--space-3xl` | 64px | Page-level spacing |
### Form Layout Rules
- **Input height**: 32px for compact forms, 40px for standalone forms
- **Input font**: `--text-sm` (14px) for form inputs
- **Numeric inputs**: `text-align: right` always
- **Labels**: `--text-xs` (12px), `--font-semibold`, `--text-color-secondary`
- **Layout**: Inline labels next to inputs on desktop, stacked on mobile
- **Row gaps**: `--space-sm` (8px) between form rows
- **Row borders**: `1px solid var(--surface-border)` between rows
### Breakpoints
| Name | Width | Layout Behavior |
|------|-------|----------------|
| Extra-small | ≤360px | Payment inputs stack vertically, minimal padding |
| Mobile | ≤768px | Single column, stacked forms, bottom sheets for filters |
| Tablet | 769-1023px | Hybrid layout, wider cards |
| Desktop | ≥1024px | Full multi-column, inline forms, side-by-side panels |
| Wide | ≥1400px | Max content width, centered layout |
---
## 6. Component Patterns
### Cards
```css
/* Standard card */
background: var(--surface-card);
border-radius: var(--radius-md); /* 8px */
padding: var(--space-lg); /* 24px */
box-shadow: var(--shadow-sm);
/* Compact card (data-dense views) */
padding: var(--space-md); /* 16px */
/* Metric/KPI card */
/* Icon + --text-2xl value + --text-xs label + trend indicator */
```
### Buttons
- Primary: `--color-primary` background, white text
- Secondary: Outlined or text-only (`severity="secondary"`)
- Minimum touch target: 44x44px on mobile
- Icon buttons: 32x32px on desktop, 44x44px on mobile
### Tables (PrimeVue DataTable)
- Separate Debit/Credit columns (never stacked in one cell)
- Filter buttons on dedicated row below filters
- Export exports ALL data, not just current page
- All overrides in `vendor/primevue-overrides.css` — never use `:deep()` in components
### Dropdowns in Compact Forms
Use `dropdown-borderless` class for inline dropdowns:
```html