# dossie — Design System (mockup)

Catálogo dos componentes/classes usados no `index.html`. Serve de **referência pra implementação React/Tauri** em `apps/desktop/ui/`. Cada classe CSS aqui mapeia 1:1 para um primitive React.

> **Convenção de naming**:
> - Classes do tema FlowOps (sem prefixo): `card`, `btn`, `nav-item`, `badge`, `modal`, `term`, `chat-bubble`, `kbd`, etc.
> - Classes utilitárias do dossie (prefixo `dx-`): `dx-row-center`, `dx-gap-10`, `dx-mb-14`, `dx-modal-icon`, `dx-tile-row`, etc.
> - Tailwind play CDN gera utilitárias padrão (`flex`, `items-center`, `gap-2`, `mb-3`, `ml-auto`, etc.).
>
> **Decisão de uso**:
> - Tailwind cobre **scale default** (4/8/12/16/24/32px → `gap-1/2/3/4/6/8`).
> - `dx-*` cobre valores **custom do FlowOps** (6/10/14/18/22px) e composições nomeadas.
> - Classes sem prefixo (`card`, `btn`) representam componentes do design system — vão virar primitives React.

---

## Camadas de CSS

| Arquivo | Conteúdo | Vai virar (Tauri) |
|---|---|---|
| [theme.css](theme.css) | Tokens (`:root`, `[data-theme=dark]`) | `apps/desktop/ui/theme/tokens.css` |
| [components.css](components.css) | Classes de componente (`btn`, `card`, etc) | `apps/desktop/ui/primitives/*.tsx` |
| [utilities.css](utilities.css) | Helpers `dx-*` | `apps/desktop/ui/utilities.css` (similar) |

---

## Tokens (theme.css)

### Paleta

| Token | Light | Dark | Uso |
|---|---|---|---|
| `--primary` | `#111827` | `#FFEDD5` | Accent principal, botão primário, ativos |
| `--primary-text` | `#FFFFFF` | `#111827` | Texto que vai sobre `--primary` |
| `--secondary` | `#FFEDD5` | `#2A2F3A` | Destaque secundário, peach (light) |
| `--bg` | `#E5E7EB` | `#0B0E13` | Background do app |
| `--surface` | `#FFFFFF` | `#1A1F2A` | Cards, modais |
| `--text-primary` | `#111827` | `#F5F5F7` | Headings, valores |
| `--text-body` | `#4B5563` | `#C8CAD0` | Texto corpo |
| `--text-muted` | `#6B7280` | `#8D9097` | Suporte/captions |

### Semantic (não-extrapolam paleta)

| Token | Light | Dark | Uso |
|---|---|---|---|
| `--semantic-success` / `--semantic-success-soft` | `#166534` / `#DCFCE7` | mesmo | Status ok |
| `--semantic-warning` / `--semantic-warning-soft` | `#B45309` / `#FFEDD5` | mesmo | Atenção |
| `--semantic-danger` / `--semantic-danger-soft` | `#C2410C` / `#FEE4D5` | mesmo | Erro/crítico |
| `--semantic-info` / `--semantic-info-soft` | `#1E3A8A` / `#DBEAFE` | mesmo | Info neutra |

### Surfaces especiais

| Token | Uso |
|---|---|
| `--term-bg` / `--term-fg` / `--term-prompt` / `--term-ok/warn/err/dim` | Terminal — sempre escuro independente de tema |
| `--code-bg` / `--code-fg` | Code blocks (diff de tema) |
| `--code-bg-soft` / `--code-fg-soft` | Inline code, kbd |
| `--gradient-card-warm` / `--gradient-card-danger` | Gradients tema-aware |
| `--hover-bg` / `--hover-bg-strong` | Hover backgrounds |

### Radii / Spacing

```
--r-xs: 6px;    --r-sm: 12px;   --r-md: 20px;
--r-lg: 28px;   --r-xl: 32px;   --r-pill: 9999px;

--s-1: 4px;  --s-2: 8px;  --s-3: 12px;
--s-4: 16px; --s-5: 24px; --s-6: 32px;
--s-7: 64px; --s-8: 88px;
```

### Shadows / Motion

| Token | Uso |
|---|---|
| `--shadow-card` | Padrão de elevação cards |
| `--shadow-card-hover` | Hover state de cards |
| `--shadow-press` | Buttons primários, ativos (inset complexo) |
| `--shadow-soft` | Sutil pra chips/inputs |
| `--ease` | `cubic-bezier(0.4, 0, 0.2, 1)` |
| `--t-fast` / `--t-mid` | 150ms / 300ms |

---

## Tipografia

```css
.t-display     /* 48px / 500 / display-lg variant */
.t-display-sm  /* 32px / 500 */
.t-h2          /* 22px / 500 */
.t-h3          /* 16px / 500 */
.t-body        /* 16px / 300 / body-md */
.t-body-sm     /* 14px / 300 */
.t-label       /* 14px / 500 / 0.35px tracking — label-md */
.t-label-sm    /* 12px / 500 / 0.4px */
.t-caption     /* 11px / 500 / 0.6px / uppercase */
```

**Mapping React**: `<Text size="display"|"h2"|"body"|"label"|"caption">`

---

## Componentes

### Card · `.card`

Surface elevada, padrão pra agrupamento.

| Class | Efeito |
|---|---|
| `.card` | Base: `bg=surface`, `border-soft`, `radius=lg`, `shadow-card` |
| `.card-hover` | + Translate Y -1px e shadow-card-hover no hover |
| `.card-tight` | radius=md + padding=12px |
| `.card-hero` | radius=xl |

```html
<div class="card card-hover dx-pad-card">
  <h3 class="t-h3">Título</h3>
  <p class="t-body-sm">Conteúdo</p>
</div>
```

**React**: `<Card hoverable>`, `<Card.Tight>`, `<Card.Hero>`.

---

### Glass surface · `.glass`

Background translúcido com `backdrop-filter`. Usado em top-bar, nav-rail, right-panel, status-bar, canvas.

```html
<aside class="glass dx-pad-card">...</aside>
```

Variantes: `.glass-sm` (radius=sm), `.glass-md` (radius=md), `.glass-xl` (radius=xl).

**React**: `<Glass>` ou `<Surface variant="glass">`.

---

### Button · `.btn` + `.btn-{variant}`

Pill (radius=9999px), font-weight 500, letter-spacing 0.35px.

| Class | Variant |
|---|---|
| `.btn-primary` | bg=primary, text=primary-text, shadow-press |
| `.btn-secondary` | bg=secondary peach, text=primary |
| `.btn-ghost` | transparent, text=body, hover=hover-bg |
| `.btn-outline` | bg=surface, ring 1px, hover=ring-strong |
| `.btn-danger` | bg=danger-soft, text=danger |
| `.btn-link` | sem fundo, sem padding, text=muted |

Sizes: `.btn-sm` (30px alto, 14px padding). `.btn-icon` (square, 36px). `.btn-icon.btn-sm` (square 30px).

```html
<button class="btn btn-primary"><iconify-icon icon="solar:play-linear"></iconify-icon>Rodar</button>
<button class="btn btn-outline btn-sm">Cancelar</button>
<button class="btn btn-ghost btn-icon btn-sm" title="Mais"><iconify-icon icon="solar:menu-dots-linear"></iconify-icon></button>
```

**React**: `<Button variant="primary"|"secondary"|"ghost"|"outline"|"danger"|"link" size="default"|"sm" icon>`.

---

### Input · `.input`

Pill (radius=9999px), height=38, ring no focus.

```html
<input class="input" placeholder="Buscar..." />
<textarea class="input input-area" rows="3"></textarea>
<input class="input input-flat" />  <!-- radius=sm pra input embedded -->
```

**React**: `<Input>`, `<Textarea>`.

---

### Badge · `.badge` + `.badge-{variant}`

Pill compacta de status/meta.

| Class | Cor |
|---|---|
| `.badge-primary` | bg=primary, text=primary-text |
| `.badge-secondary` | bg=secondary peach, text=primary |
| `.badge-outline` | bg=surface, ring 1px |
| `.badge-success/warning/danger/info` | semantic-* |
| `.badge-muted` | bg=hover-bg, text=body |

```html
<span class="badge badge-success"><span class="dot dx-bg-success"></span>running</span>
```

**React**: `<Badge variant="success"|"warning"|...>`.

---

### Dot · `.dot`

Indicador 8x8 redondo. Cor via `style="background: ..."` ou `dx-bg-*`.

```html
<span class="dot dx-bg-success"></span>
```

---

### Nav item · `.nav-item`

Item de lista navegável (sidebar, command palette, docs sidebar).

```html
<div class="nav-item active">
  <iconify-icon icon="solar:..."></iconify-icon>
  <span>Texto</span>
  <span class="badge ml-auto">2</span>
</div>
```

`.nav-item.active` aplica primary bg + primary-text.

**React**: `<NavItem icon active>{children}</NavItem>`.

---

### Workspace tab · `.ws-tab`

Pill que vira tab horizontal, ativa pinta primary.

```html
<div class="ws-tab active" data-tab="overview">
  <iconify-icon icon="solar:widget-2-linear"></iconify-icon>
  <span>Visão geral</span>
  <iconify-icon icon="solar:close-circle-linear" class="ws-tab-close"></iconify-icon>
</div>
```

**React**: `<Tab active value="overview" closable>{label}</Tab>`.

---

### Modal · `.modal` + `.modal-backdrop`

Dialog flutuante. Pattern recorrente:

```html
<div class="fixed inset-0 z-50 hidden items-center justify-center modal-backdrop"
     id="modal-foo" onclick="closeModalIfBackdrop(event, 'foo')">
  <div class="modal modal-anim" style="width: 100%; max-width: 560px;" onclick="event.stopPropagation()">

    <!-- HEADER -->
    <div class="dx-row-between dx-pad-modal-header">
      <div class="dx-row-center gap-2">
        <iconify-icon icon="solar:..." class="dx-modal-icon"></iconify-icon>
        <h2 class="t-h2">Título</h2>
        <span class="badge badge-secondary">opcional</span>
      </div>
      <button class="btn btn-ghost btn-icon btn-sm" onclick="closeModal('foo')">
        <iconify-icon icon="solar:close-circle-linear"></iconify-icon>
      </button>
    </div>

    <!-- BODY -->
    <div class="dx-pad-modal-body">
      <!-- conteúdo -->
    </div>

    <!-- FOOTER (opcional) -->
    <div class="dx-row-between dx-pad-modal-footer gap-2">
      <span class="t-label-sm">hint</span>
      <div class="dx-actions">
        <button class="btn btn-ghost">Cancelar</button>
        <button class="btn btn-primary">Confirmar</button>
      </div>
    </div>
  </div>
</div>
```

**React**: `<Modal id="foo">`, com slots `<Modal.Header icon title>`, `<Modal.Body>`, `<Modal.Footer>`.

---

### Stat row / card / list-item / grid

Padrão pra detalhes em modais (VPN, SMS, Wallet, etc).

```html
<!-- horizontal label+value -->
<div class="stat-row"><span class="lbl">Status</span><span class="val">Conectada</span></div>

<!-- vertical label+value box -->
<div class="stat-card">
  <div class="lbl">Provider</div>
  <div class="val">Tailscale</div>
</div>

<!-- grid 2-col de stat-cards -->
<div class="stat-grid">
  <div class="stat-card">...</div>
  <div class="stat-card">...</div>
</div>

<!-- list item: icon + content + actions -->
<div class="stat-list-item">
  <div class="stat-icon-box dx-bg-secondary"><iconify-icon icon="..."></iconify-icon></div>
  <div class="dx-flex-1-min0">
    <div class="dx-row-center gap-2"><span class="t-label">title</span><span class="badge badge-success">ok</span></div>
    <div class="t-label-sm dx-mt-2">meta info</div>
  </div>
  <button class="btn btn-ghost btn-icon btn-sm">...</button>
</div>
```

**React**: `<StatRow label value>`, `<StatCard label value>`, `<StatList.Item icon actions>`, `<StatGrid cols={2}>`.

---

### Surface tile (cards das 6 superfícies)

Card grande clicável com ícone colorido + title + body + footer.

```html
<div class="card card-hover surf-app dx-card-clickable" onclick="setTab('surface-app')">
  <div class="surf-icon dx-mb-14">
    <iconify-icon icon="solar:smartphone-linear"></iconify-icon>
  </div>
  <h3 class="t-h3 mb-1">App</h3>
  <p class="t-body-sm dx-mb-14">Mobile + desktop.</p>
  <div class="dx-row-between">
    <span class="t-label-sm">igreen-estudo.html · 4 dias</span>
    <iconify-icon icon="solar:arrow-right-linear"></iconify-icon>
  </div>
</div>
```

`.surf-icon` usa CSS vars `--surf-color` e `--surf-soft` que são definidos por `.surf-{web|api|app|endpoint|infra|humano}` no parent.

| Surface | --surf-color | --surf-soft |
|---|---|---|
| `surf-web` | #1E3A8A | #DBEAFE |
| `surf-api` | #5B21B6 | #EDE9FE |
| `surf-app` | #B45309 | #FFEDD5 |
| `surf-endpoint` | #166534 | #DCFCE7 |
| `surf-infra` | #92400E | #FEF3C7 |
| `surf-humano` | #C2410C | #FEE4D5 |

**React**: `<SurfaceTile surface="app" icon title body footer />`.

---

### Terminal · `.term`

Sempre fundo deep escuro, independente de tema.

```html
<div class="term">
  <span class="dim"># comment</span>
  <span class="prompt">~ $</span> command
  <span class="ok">[ok]</span> message
  <span class="warn">[warn]</span> message
  <span class="err">[err]</span> message
</div>
```

**React**: `<Terminal output={...}>`. Tokens já isolados em `--term-*`.

---

### Chat bubble · `.chat-bubble`

```html
<div class="chat-bubble chat-user">User msg</div>
<div class="chat-bubble chat-bot">Bot msg</div>
```

**React**: `<ChatBubble role="user"|"bot">`.

---

### Toast · `.dx-toast` + `.dx-toast-{variant}`

Confirmação de ação (mockada via `mockAction(label, opts)` ou `data-mock="..."`).

Variants: `success`, `info`, `warning`, `danger`, `default`.

```js
showToast('Cliente criado', 'success');
mockAction('Reindexando RAG...', { variant: 'info' });
```

Botões podem ter atributo `data-mock="<label>"` — handler global em `app.js` mostra toast automaticamente.

**React**: `<Toast variant="success">` ou hook `useToast()`.

---

### Status bar item · `.status-item`

Botão compacto da status bar, abre modal com detalhes.

```html
<button class="status-item" onclick="openModal('statusVpn')" title="VPN">
  <span class="dot dx-bg-success"></span>
  <span class="flag">🇳🇱</span>
  <span class="mono">100.103.42.18</span>
</button>
```

**React**: `<StatusItem icon onClick>...</StatusItem>`.

---

### Chip-client (top bar)

```html
<div class="chip-client" onclick="openModal('clientPicker')">
  <iconify-icon icon="solar:buildings-3-linear"></iconify-icon>
  <span class="t-label">iGreen Energy</span>
  <span class="badge badge-secondary">em escopo</span>
  <iconify-icon icon="solar:alt-arrow-down-linear"></iconify-icon>
</div>
```

**React**: `<ClientChip current onClick>`.

---

### KBD · `.kbd`

```html
<span class="kbd">⌘K</span>
```

**React**: `<Kbd>⌘K</Kbd>`.

---

### Device-frame / Browser-frame (preview mobile/web)

Mock visual de device mobile e janela de browser.

```html
<div class="device-frame">
  <div class="device-screen">...</div>
</div>

<div class="browser-frame">
  <div class="browser-chrome">
    <span class="browser-dot dx-bg-danger"></span>
    <span class="browser-dot dx-bg-warning"></span>
    <span class="browser-dot dx-bg-success"></span>
    ...
  </div>
  <iframe>...</iframe>
</div>
```

**React**: `<DeviceFrame>`, `<BrowserFrame>`.

---

## Utilitárias `dx-*`

### Layout

| Class | CSS |
|---|---|
| `dx-row` | flex row |
| `dx-col` | flex column |
| `dx-row-center` | flex row + items-center |
| `dx-row-between` | flex row + items-center + justify-between |
| `dx-row-end` | flex row + items-center + justify-end |
| `dx-flex-1` | flex: 1 |
| `dx-flex-1-min0` | flex: 1; min-width: 0 |
| `dx-shrink-0` | flex-shrink: 0 |
| `dx-ml-auto` | margin-left: auto |
| `dx-mt-auto` | margin-top: auto |

### Gaps custom (fora scale Tailwind)

| Class | Valor |
|---|---|
| `dx-gap-6` | 6px |
| `dx-gap-10` | 10px |
| `dx-gap-14` | 14px |
| `dx-gap-18` | 18px |
| `dx-gap-22` | 22px |

### Margins custom

`dx-mb-2/6/10/14/18/28`, `dx-mt-2/6/14/18`.

### Padding presets

| Class | Uso |
|---|---|
| `dx-pad-card` | `padding: 22px` |
| `dx-pad-card-tight` | `padding: 14px` |
| `dx-pad-canvas` | `padding: 32px 40px` |
| `dx-pad-section` | `padding: 18px 22px` |
| `dx-pad-modal-header` | `padding: 18px 22px; border-bottom: 1px solid border-soft` |
| `dx-pad-modal-body` | `padding: 20px 22px` |
| `dx-pad-modal-footer` | `padding: 14px 22px; border-top: 1px solid border-soft` |
| `dx-canvas` | canvas + max-width 1280 + margin auto |

### Cores texto/bg

`dx-text-primary/body/muted/subtle/accent/success/warning/danger/info`.
`dx-bg-success/warning/danger/info/secondary`.
`dx-modal-icon` (color=primary + size=22px).

### Misc

| Class | Uso |
|---|---|
| `dx-clickable` | `cursor: pointer` |
| `dx-card-clickable` | padding=22 + cursor=pointer |
| `dx-tile-row` | padding=12px 14px + cursor=pointer |
| `dx-btn-row` | width=100% + justify-start (botões em coluna) |
| `dx-fs-13` / `dx-fs-22` | font-size custom |
| `dx-vline-20` / `dx-vline-24` | divisor vertical |
| `dx-actions` / `dx-actions-end` | row de botões com gap=8 |

---

## Sistema de mockActions

Botões com `data-mock="Label"` mostram toast quando clicados (handler global em `app.js`).

```html
<button class="btn btn-secondary btn-sm" data-mock="Mockup · Reconectar VPN">
  Reconectar
</button>
```

`data-mock-variant="success|info|warning|danger"` controla cor do toast.

```js
// programático:
showToast('Cliente criado', 'success');
mockAction('Reindexando RAG...', { variant: 'info' });
mockAction('Cliente removido', {
  variant: 'danger',
  closeModal: 'clientPicker',
});
```

---

## Mapeamento futuro pro Tauri / React

| Mockup CSS | Primitive React (`apps/desktop/ui/primitives/`) |
|---|---|
| `.card`, `.card-hover` | `<Card hoverable>` |
| `.glass` | `<Glass>` |
| `.btn` + `.btn-{variant}` | `<Button variant size>` |
| `.input` / `.input-area` | `<Input>` / `<Textarea>` |
| `.badge-{variant}` | `<Badge variant>` |
| `.nav-item` | `<NavItem>` |
| `.ws-tab` | `<WorkspaceTab>` |
| `.modal` + `dx-pad-modal-*` | `<Modal>` + `<Modal.Header/Body/Footer>` |
| `.stat-row` | `<StatRow label value>` |
| `.stat-card` | `<StatCard>` |
| `.stat-list-item` | `<StatList.Item>` |
| `.surf-icon` + `.surf-{X}` | `<SurfaceIcon surface>` |
| `.term` | `<Terminal>` |
| `.chat-bubble` | `<ChatBubble role>` |
| `.dx-toast-{variant}` | `<Toast>` / `useToast()` |
| `.status-item` | `<StatusItem>` |
| `.chip-client` | `<ClientChip>` |
| `.kbd` | `<Kbd>` |
| `.device-frame` / `.browser-frame` | `<DeviceFrame>` / `<BrowserFrame>` |

`theme.css` migra direto pra `apps/desktop/ui/theme/tokens.css` — mesmos nomes de var.

---

## Roadmap de evolução do mockup

| Fase | Status |
|---|---|
| 1. Split em arquivos (theme/components/utilities/app.js/docs-content.js) | ✅ |
| 2. Utility classes pra inline styles repetidos | ✅ |
| 3. Componentes nomeados + classes BEM-light | ✅ |
| 4. JS extraído pra arquivo separado | ✅ |
| 5. Documentação de componentes (este doc) | ✅ |
| 6. Refinamento visual incremental | em aberto |
| 7. Tradução pra `apps/desktop/ui/primitives/` no Tauri | futuro |
