# TOI Shortcut — Evolucao do Design System

> **Projeto:** TOI Shortcut
> **Dominio:** `https://toi.shinp.ai`
> **Arquiteto de Design System:** Albiere
> **Data:** 2026-04-03
> **Versao:** 2.0 — Production-Grade Evolution
> **Baseline:** VISUAL_DIRECTION.md v1.0

---

> **NOTA:** Este documento NAO repete o conteudo de VISUAL_DIRECTION.md. Ele EVOLUI o sistema para producao real. Leia o documento original primeiro.

---

## 1. Analise de Gaps — O Que Falta Para Producao

### 1.1 Estados Ausentes

| Componente | Estados definidos na v1 | Estados faltando |
|---|---|---|
| Button | default, hover, active, disabled | **focus, loading, icon-only, sizes (sm/lg)** |
| Input | default, focus, error, disabled | **hover, success, readonly, com label/helper/counter** |
| Table | default, hover | **loading (skeleton rows), empty, sortable, selectable, responsive** |
| Card | default, hover | **selected, loading/skeleton, collapsed** |
| Badge | ativo, inativo | **warning, info, count, sizes** |
| Modal | enter animation | **exit animation, focus trap, scroll lock, responsive full-screen** |
| Toast | success, error, warning, info | **action button, stack behavior, progress bar, pause on hover** |
| Sidebar | expanded, active | **collapsed (64px), mobile overlay, transition** |
| Select/Dropdown | mencionado | **ZERO spec — componente inteiro ausente** |
| Toggle | visual definido | **focus, disabled, loading, label, sizes** |
| Checkbox | nao existe | **componente inteiro ausente** |
| Radio | nao existe | **componente inteiro ausente** |
| Date Picker | nao existe | **trigger style ausente** |
| Skeleton | shimmer definido | **variantes por componente ausentes** |
| Empty State | nao existe | **pattern inteiro ausente** |
| Error State | nao existe | **pattern inteiro ausente** |
| Drawer | nao existe | **componente inteiro ausente** |

### 1.2 Responsividade

A v1 define apenas:
- Login: "< 768px layout empilhado"
- Dashboard: nenhuma regra responsiva
- Tabela: nenhuma regra responsiva
- Sidebar: nenhuma regra responsiva

**Gap critico:** Um SaaS sem responsividade nao sobrevive. Usuarios acessam dashboards no celular para checar metricas rapidamente.

### 1.3 Acessibilidade

A v1 define ZERO sobre:
- Contraste WCAG
- Focus indicators (apenas border-color em inputs)
- Navegacao por teclado
- Screen readers
- `prefers-reduced-motion`
- `prefers-contrast`
- ARIA patterns

**Gap critico:** Alem de ser obrigacao moral e legal, acessibilidade e requisito tecnico para qualquer produto serio.

### 1.4 Inconsistencias Encontradas

1. **Disabled state generico:** `opacity: 0.4` em botoes mas `opacity: 0.5` em inputs. Precisa ser consistente.
2. **Transition mismatch:** Botoes usam `0.2s ease`, ghost usa `0.15s ease`, sem justificativa semantica.
3. **Color bleeding:** `--text-link` e `--color-primary` sao identicos (#E4502A), mas nao ha token de referencia cruzada.
4. **Z-index gap:** Nao ha camada para Drawer (entre modal e dropdown).
5. **Shadow inconsistency:** Cards definem shadow inline (`0 1px 3px...`) que e identico ao `--shadow-sm` mas nao o referencia.
6. **Spacing token gap:** `--space-7` (28px), `--space-9` (36px), `--space-14` (56px) nao existem. Cria buracos na escala.

### 1.5 Performance

A v1 ignora:
- `will-change` para animacoes frequentes
- `contain` para layout isolation
- Font loading strategy (apenas `display=swap` sem fallback metrics)
- Animation frame budget (16ms)
- Skeleton choreography (evitar layout shift)

---

## 2. Arquitetura de Design Tokens — Tres Camadas

### 2.1 Filosofia

A v1 mistura valores primitivos com semantica em um unico nivel. Isso quebra quando:
- Voce adiciona light mode
- Voce cria temas por cliente (white-label)
- Voce precisa de tokens por componente

**Solucao: Arquitetura de tres camadas.**

```
PRIMITIVE (valores brutos)     -->  --primitive-coral-500: #E4502A
SEMANTIC (intencao de uso)     -->  --color-action-primary: var(--primitive-coral-500)
COMPONENT (contexto especifico) --> --button-primary-bg: var(--color-action-primary)
```

**Por que tres camadas?**
- **Primitive:** Nunca muda. E o dicionario de valores.
- **Semantic:** Muda por tema (dark/light). E a traducao de intencao.
- **Component:** Muda por componente. Permite override cirurgico.

### 2.2 Bloco Completo de Tokens — Production-Ready

```css
/* ================================================================
   TOI Shortcut — Design Tokens v2.0
   Production-Grade Three-Layer Architecture
   ================================================================ */

:root {
  /* ================================================================
     CAMADA 1: PRIMITIVE TOKENS
     Valores brutos. Nunca referenciam outros tokens.
     Convencao: --primitive-{categoria}-{escala}
     ================================================================ */

  /* --- Primitive: Escala de Cinzas (Blue-Gray) --- */
  --primitive-gray-50:  #F0EDE8;
  --primitive-gray-100: #D4CFC8;
  --primitive-gray-200: #B8B1A8;
  --primitive-gray-300: #8A9BB0;
  --primitive-gray-400: #6E7B8B;
  --primitive-gray-500: #515B6A;
  --primitive-gray-600: #2A3040;
  --primitive-gray-700: #232830;
  --primitive-gray-800: #1C2028;
  --primitive-gray-900: #161920;
  --primitive-gray-925: #12151B;
  --primitive-gray-950: #0F1114;

  /* --- Primitive: Coral (Brand) --- */
  --primitive-coral-300: #F2896E;
  --primitive-coral-400: #E86A4A;
  --primitive-coral-500: #E4502A;
  --primitive-coral-600: #CC3F1F;
  --primitive-coral-700: #B8361A;
  --primitive-coral-800: #932B15;

  /* --- Primitive: Semanticas --- */
  --primitive-green-400: #5AD98E;
  --primitive-green-500: #2ECC71;
  --primitive-green-600: #27AE60;
  --primitive-green-700: #1E8C4C;

  --primitive-yellow-400: #F5B041;
  --primitive-yellow-500: #F39C12;
  --primitive-yellow-600: #D4860E;

  --primitive-red-400: #EC7063;
  --primitive-red-500: #E74C3C;
  --primitive-red-600: #C0392B;
  --primitive-red-700: #A93226;

  --primitive-blue-400: #5DADE2;
  --primitive-blue-500: #3498DB;
  --primitive-blue-600: #2E86C1;

  /* --- Primitive: Preto e Branco --- */
  --primitive-black: #000000;
  --primitive-white: #FFFFFF;
  --primitive-white-warm: #FBF7F2;

  /* --- Primitive: Transparencias --- */
  --primitive-alpha-5:  0.05;
  --primitive-alpha-10: 0.10;
  --primitive-alpha-15: 0.15;
  --primitive-alpha-20: 0.20;
  --primitive-alpha-30: 0.30;
  --primitive-alpha-40: 0.40;
  --primitive-alpha-50: 0.50;
  --primitive-alpha-60: 0.60;

  /* --- Primitive: Tipografia --- */
  --primitive-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --primitive-font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;

  --primitive-size-11: 0.6875rem;  /* 11px */
  --primitive-size-12: 0.75rem;    /* 12px */
  --primitive-size-13: 0.8125rem;  /* 13px */
  --primitive-size-14: 0.875rem;   /* 14px */
  --primitive-size-15: 0.9375rem;  /* 15px */
  --primitive-size-16: 1rem;       /* 16px */
  --primitive-size-20: 1.25rem;    /* 20px */
  --primitive-size-24: 1.5rem;     /* 24px */
  --primitive-size-28: 1.75rem;    /* 28px */
  --primitive-size-32: 2rem;       /* 32px */

  --primitive-weight-regular: 400;
  --primitive-weight-medium: 500;
  --primitive-weight-semibold: 600;
  --primitive-weight-bold: 700;

  --primitive-leading-tight: 1.2;
  --primitive-leading-snug: 1.3;
  --primitive-leading-normal: 1.4;
  --primitive-leading-relaxed: 1.5;
  --primitive-leading-loose: 1.6;

  /* --- Primitive: Espacamento (base 4px) --- */
  --primitive-space-0:  0;
  --primitive-space-1:  0.25rem;   /* 4px */
  --primitive-space-2:  0.5rem;    /* 8px */
  --primitive-space-3:  0.75rem;   /* 12px */
  --primitive-space-4:  1rem;      /* 16px */
  --primitive-space-5:  1.25rem;   /* 20px */
  --primitive-space-6:  1.5rem;    /* 24px */
  --primitive-space-7:  1.75rem;   /* 28px */
  --primitive-space-8:  2rem;      /* 32px */
  --primitive-space-9:  2.25rem;   /* 36px */
  --primitive-space-10: 2.5rem;    /* 40px */
  --primitive-space-12: 3rem;      /* 48px */
  --primitive-space-14: 3.5rem;    /* 56px */
  --primitive-space-16: 4rem;      /* 64px */
  --primitive-space-20: 5rem;      /* 80px */

  /* --- Primitive: Border Radius --- */
  --primitive-radius-4:  0.25rem;
  --primitive-radius-6:  0.375rem;
  --primitive-radius-8:  0.5rem;
  --primitive-radius-12: 0.75rem;
  --primitive-radius-16: 1rem;
  --primitive-radius-full: 9999px;

  /* --- Primitive: Duracoes --- */
  --primitive-duration-0:    0ms;
  --primitive-duration-75:   75ms;
  --primitive-duration-100:  100ms;
  --primitive-duration-150:  150ms;
  --primitive-duration-200:  200ms;
  --primitive-duration-250:  250ms;
  --primitive-duration-350:  350ms;
  --primitive-duration-500:  500ms;

  /* --- Primitive: Easings --- */
  --primitive-ease-linear:    linear;
  --primitive-ease-in:        cubic-bezier(0.4, 0, 1, 1);
  --primitive-ease-out:       cubic-bezier(0, 0, 0.2, 1);
  --primitive-ease-in-out:    cubic-bezier(0.4, 0, 0.2, 1);
  --primitive-ease-bounce:    cubic-bezier(0.34, 1.56, 0.64, 1);
  --primitive-ease-spring:    cubic-bezier(0.175, 0.885, 0.32, 1.275);

  /* --- Primitive: Z-Index --- */
  --primitive-z-0:    0;
  --primitive-z-10:   10;
  --primitive-z-100:  100;
  --primitive-z-200:  200;
  --primitive-z-300:  300;
  --primitive-z-400:  400;
  --primitive-z-500:  500;
  --primitive-z-600:  600;
  --primitive-z-700:  700;
  --primitive-z-9999: 9999;

  /* ================================================================
     CAMADA 2: SEMANTIC TOKENS
     Mapeiam intencao para primitives. Mudam por tema.
     Convencao: --{categoria}-{propriedade}-{variante}
     ================================================================ */

  /* --- Semantic: Backgrounds --- */
  --bg-base:      var(--primitive-gray-950);
  --bg-surface:   var(--primitive-gray-900);
  --bg-elevated:  var(--primitive-gray-800);
  --bg-hover:     var(--primitive-gray-700);
  --bg-input:     var(--primitive-gray-925);
  --bg-overlay:   rgba(0, 0, 0, 0.60);
  --bg-overlay-heavy: rgba(0, 0, 0, 0.80);
  --bg-selection: rgba(228, 80, 42, 0.15);
  --bg-skeleton:  var(--primitive-gray-900);
  --bg-skeleton-shimmer: var(--primitive-gray-800);

  /* --- Semantic: Texto --- */
  --text-primary:   var(--primitive-gray-50);
  --text-secondary: var(--primitive-gray-300);
  --text-muted:     var(--primitive-gray-500);
  --text-inverse:   var(--primitive-gray-950);
  --text-link:      var(--primitive-coral-500);
  --text-link-hover: var(--primitive-coral-400);
  --text-on-primary: var(--primitive-white);
  --text-on-success: var(--primitive-white);
  --text-on-danger:  var(--primitive-white);
  --text-disabled:  var(--primitive-gray-500);
  --text-placeholder: var(--primitive-gray-500);

  /* --- Semantic: Cores de Acao --- */
  --color-action-primary:        var(--primitive-coral-500);
  --color-action-primary-hover:  var(--primitive-coral-600);
  --color-action-primary-active: var(--primitive-coral-700);
  --color-action-primary-subtle: rgba(228, 80, 42, 0.10);

  /* --- Semantic: Cores de Status --- */
  --color-success:        var(--primitive-green-500);
  --color-success-hover:  var(--primitive-green-600);
  --color-success-subtle: rgba(46, 204, 113, 0.10);
  --color-success-muted:  rgba(46, 204, 113, 0.20);

  --color-warning:        var(--primitive-yellow-500);
  --color-warning-hover:  var(--primitive-yellow-600);
  --color-warning-subtle: rgba(243, 156, 18, 0.10);
  --color-warning-muted:  rgba(243, 156, 18, 0.20);

  --color-error:          var(--primitive-red-500);
  --color-error-hover:    var(--primitive-red-600);
  --color-error-subtle:   rgba(231, 76, 60, 0.10);
  --color-error-muted:    rgba(231, 76, 60, 0.20);

  --color-info:           var(--primitive-blue-500);
  --color-info-hover:     var(--primitive-blue-600);
  --color-info-subtle:    rgba(52, 152, 219, 0.10);
  --color-info-muted:     rgba(52, 152, 219, 0.20);

  /* --- Semantic: Bordas --- */
  --border-default:  var(--primitive-gray-600);
  --border-subtle:   rgba(30, 35, 48, 0.60);
  --border-strong:   var(--primitive-gray-500);
  --border-hover:    var(--primitive-gray-600);
  --border-focus:    var(--primitive-coral-500);
  --border-error:    var(--primitive-red-500);
  --border-success:  var(--primitive-green-500);
  --border-disabled: var(--primitive-gray-800);

  /* --- Semantic: Focus Ring --- */
  --focus-ring-color: rgba(228, 80, 42, 0.40);
  --focus-ring-offset: 2px;
  --focus-ring-width: 2px;
  --focus-ring: var(--focus-ring-width) solid var(--focus-ring-color);
  --focus-ring-shadow: 0 0 0 var(--focus-ring-offset) var(--bg-base), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);

  /* --- Semantic: Scrollbar --- */
  --scrollbar-width: 6px;
  --scrollbar-track: transparent;
  --scrollbar-thumb: var(--primitive-gray-700);
  --scrollbar-thumb-hover: var(--primitive-gray-600);

  /* --- Semantic: Selection --- */
  --selection-bg: rgba(228, 80, 42, 0.30);
  --selection-text: var(--primitive-white);

  /* --- Semantic: Tipografia --- */
  --font-sans: var(--primitive-font-sans);
  --font-mono: var(--primitive-font-mono);

  --text-h1:       var(--primitive-size-32);
  --text-h2:       var(--primitive-size-24);
  --text-h3:       var(--primitive-size-20);
  --text-h4:       var(--primitive-size-16);
  --text-body:     var(--primitive-size-14);
  --text-body-lg:  var(--primitive-size-16);
  --text-small:    var(--primitive-size-12);
  --text-caption:  var(--primitive-size-11);
  --text-mono:     var(--primitive-size-13);
  --text-mono-lg:  var(--primitive-size-15);

  --weight-regular:  var(--primitive-weight-regular);
  --weight-medium:   var(--primitive-weight-medium);
  --weight-semibold: var(--primitive-weight-semibold);
  --weight-bold:     var(--primitive-weight-bold);

  --leading-tight:   var(--primitive-leading-tight);
  --leading-snug:    var(--primitive-leading-snug);
  --leading-normal:  var(--primitive-leading-normal);
  --leading-relaxed: var(--primitive-leading-relaxed);
  --leading-loose:   var(--primitive-leading-loose);

  /* --- Semantic: Espacamento --- */
  --space-0:  var(--primitive-space-0);
  --space-1:  var(--primitive-space-1);
  --space-2:  var(--primitive-space-2);
  --space-3:  var(--primitive-space-3);
  --space-4:  var(--primitive-space-4);
  --space-5:  var(--primitive-space-5);
  --space-6:  var(--primitive-space-6);
  --space-7:  var(--primitive-space-7);
  --space-8:  var(--primitive-space-8);
  --space-9:  var(--primitive-space-9);
  --space-10: var(--primitive-space-10);
  --space-12: var(--primitive-space-12);
  --space-14: var(--primitive-space-14);
  --space-16: var(--primitive-space-16);
  --space-20: var(--primitive-space-20);

  /* --- Semantic: Radius --- */
  --radius-xs:   var(--primitive-radius-4);
  --radius-sm:   var(--primitive-radius-6);
  --radius-md:   var(--primitive-radius-8);
  --radius-lg:   var(--primitive-radius-12);
  --radius-xl:   var(--primitive-radius-16);
  --radius-full: var(--primitive-radius-full);

  /* --- Semantic: Sombras --- */
  --shadow-xs:  0 1px 2px rgba(0, 0, 0, 0.16);
  --shadow-sm:  0 1px 3px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);
  --shadow-md:  0 4px 16px rgba(0, 0, 0, 0.20);
  --shadow-lg:  0 8px 24px rgba(0, 0, 0, 0.30);
  --shadow-xl:  0 24px 48px rgba(0, 0, 0, 0.40);
  --shadow-inner: inset 0 1px 2px rgba(0, 0, 0, 0.20);
  --shadow-glow-primary: 0 0 0 3px rgba(228, 80, 42, 0.15);
  --shadow-glow-error:   0 0 0 3px rgba(231, 76, 60, 0.15);
  --shadow-glow-success: 0 0 0 3px rgba(46, 204, 113, 0.15);
  --shadow-glow-info:    0 0 0 3px rgba(52, 152, 219, 0.15);
  --shadow-button-hover: 0 4px 12px rgba(228, 80, 42, 0.25);

  /* --- Semantic: Motion --- */
  --duration-instant:  var(--primitive-duration-75);
  --duration-fast:     var(--primitive-duration-150);
  --duration-normal:   var(--primitive-duration-250);
  --duration-slow:     var(--primitive-duration-350);
  --duration-dramatic: var(--primitive-duration-500);

  --ease-enter:       var(--primitive-ease-out);
  --ease-exit:        var(--primitive-ease-in);
  --ease-move:        var(--primitive-ease-in-out);
  --ease-interaction: var(--primitive-ease-in-out);
  --ease-bounce:      var(--primitive-ease-bounce);
  --ease-spring:      var(--primitive-ease-spring);

  --transition-instant:     var(--duration-instant) var(--ease-interaction);
  --transition-fast:        var(--duration-fast) var(--ease-interaction);
  --transition-normal:      var(--duration-normal) var(--ease-interaction);
  --transition-slow:        var(--duration-slow) var(--ease-interaction);
  --transition-enter:       var(--duration-normal) var(--ease-enter);
  --transition-exit:        var(--duration-fast) var(--ease-exit);
  --transition-move:        var(--duration-normal) var(--ease-move);

  /* --- Semantic: Z-Index --- */
  --z-base:           var(--primitive-z-0);
  --z-sticky:         var(--primitive-z-10);
  --z-sidebar:        var(--primitive-z-100);
  --z-header:         var(--primitive-z-200);
  --z-dropdown:       var(--primitive-z-300);
  --z-drawer-overlay: var(--primitive-z-400);
  --z-drawer:         var(--primitive-z-400);
  --z-modal-overlay:  var(--primitive-z-500);
  --z-modal:          var(--primitive-z-500);
  --z-toast:          var(--primitive-z-600);
  --z-tooltip:        var(--primitive-z-700);
  --z-max:            var(--primitive-z-9999);

  /* --- Semantic: Layout --- */
  --sidebar-width-expanded:  240px;
  --sidebar-width-collapsed: 64px;
  --content-max-width:       1200px;
  --content-padding-x:       var(--space-10);
  --content-padding-y:       var(--space-8);

  /* ================================================================
     CAMADA 3: COMPONENT TOKENS
     Tokens especificos por componente. Permitem override isolado.
     Convencao: --{componente}-{propriedade}-{estado}
     ================================================================ */

  /* --- Component: Button --- */
  --button-font:            var(--font-sans);
  --button-font-size:       var(--text-body);
  --button-font-weight:     var(--weight-semibold);
  --button-radius:          var(--radius-md);
  --button-height-sm:       32px;
  --button-height-md:       40px;
  --button-height-lg:       48px;
  --button-padding-sm:      var(--space-1) var(--space-3);
  --button-padding-md:      var(--space-2) var(--space-5);
  --button-padding-lg:      var(--space-3) var(--space-7);
  --button-gap:             var(--space-2);
  --button-transition:      var(--transition-fast);
  --button-disabled-opacity: 0.45;

  --button-primary-bg:          var(--color-action-primary);
  --button-primary-bg-hover:    var(--color-action-primary-hover);
  --button-primary-bg-active:   var(--color-action-primary-active);
  --button-primary-text:        var(--text-on-primary);
  --button-primary-shadow-hover: var(--shadow-button-hover);

  --button-secondary-bg:          transparent;
  --button-secondary-bg-hover:    var(--bg-elevated);
  --button-secondary-bg-active:   var(--bg-hover);
  --button-secondary-text:        var(--text-primary);
  --button-secondary-border:      var(--border-default);
  --button-secondary-border-hover: var(--border-hover);

  --button-ghost-bg:          transparent;
  --button-ghost-bg-hover:    var(--bg-surface);
  --button-ghost-bg-active:   var(--bg-elevated);
  --button-ghost-text:        var(--text-secondary);
  --button-ghost-text-hover:  var(--text-primary);

  --button-danger-bg:          var(--color-error-subtle);
  --button-danger-bg-hover:    var(--color-error);
  --button-danger-text:        var(--color-error);
  --button-danger-text-hover:  var(--text-on-danger);
  --button-danger-border:      rgba(231, 76, 60, 0.20);

  --button-success-bg:          var(--color-success-subtle);
  --button-success-bg-hover:    var(--color-success);
  --button-success-text:        var(--color-success);
  --button-success-text-hover:  var(--text-on-success);
  --button-success-border:      rgba(46, 204, 113, 0.20);

  /* --- Component: Input --- */
  --input-font:            var(--font-sans);
  --input-font-size:       var(--text-body);
  --input-font-weight:     var(--weight-regular);
  --input-radius:          var(--radius-md);
  --input-height:          40px;
  --input-padding-x:       var(--space-3);
  --input-padding-y:       var(--space-2);
  --input-bg:              var(--bg-input);
  --input-bg-hover:        var(--bg-input);
  --input-bg-disabled:     var(--bg-base);
  --input-text:            var(--text-primary);
  --input-placeholder:     var(--text-placeholder);
  --input-border:          #1E2330;
  --input-border-hover:    var(--border-hover);
  --input-border-focus:    var(--border-focus);
  --input-border-error:    var(--border-error);
  --input-border-success:  var(--border-success);
  --input-border-disabled: var(--border-disabled);
  --input-shadow-focus:    var(--shadow-glow-primary);
  --input-shadow-error:    var(--shadow-glow-error);
  --input-shadow-success:  var(--shadow-glow-success);
  --input-transition:      var(--transition-fast);
  --input-disabled-opacity: 0.50;
  --input-label-size:      var(--text-small);
  --input-label-weight:    var(--weight-semibold);
  --input-label-color:     var(--text-secondary);
  --input-helper-size:     var(--text-small);
  --input-helper-color:    var(--text-muted);
  --input-error-color:     var(--color-error);

  /* --- Component: Card --- */
  --card-bg:            var(--bg-surface);
  --card-border:        #1E2330;
  --card-border-hover:  var(--border-hover);
  --card-radius:        var(--radius-lg);
  --card-padding:       var(--space-6);
  --card-shadow:        var(--shadow-sm);
  --card-shadow-hover:  var(--shadow-md);
  --card-transition:    var(--transition-fast);

  /* --- Component: Badge --- */
  --badge-font-size:    var(--text-caption);
  --badge-font-weight:  var(--weight-semibold);
  --badge-radius:       var(--radius-full);
  --badge-padding-sm:   2px 8px;
  --badge-padding-md:   4px 10px;
  --badge-dot-size-sm:  5px;
  --badge-dot-size-md:  6px;

  /* --- Component: Table --- */
  --table-header-bg:       transparent;
  --table-header-text:     var(--text-muted);
  --table-header-size:     var(--text-caption);
  --table-header-weight:   var(--weight-semibold);
  --table-header-tracking: 0.06em;
  --table-row-bg:          transparent;
  --table-row-bg-hover:    var(--bg-surface);
  --table-row-bg-selected: var(--color-action-primary-subtle);
  --table-cell-padding:    14px 16px;
  --table-border:          var(--border-subtle);
  --table-transition:      var(--transition-instant);

  /* --- Component: Modal --- */
  --modal-bg:        var(--bg-surface);
  --modal-border:    #1E2330;
  --modal-radius:    var(--radius-xl);
  --modal-padding:   var(--space-8);
  --modal-shadow:    var(--shadow-xl);
  --modal-max-width: 520px;
  --modal-min-width: 360px;

  /* --- Component: Drawer --- */
  --drawer-bg:     var(--bg-surface);
  --drawer-border: #1E2330;
  --drawer-shadow: -8px 0 32px rgba(0, 0, 0, 0.40);
  --drawer-width:  480px;

  /* --- Component: Toast --- */
  --toast-bg:       var(--bg-hover);
  --toast-border:   var(--border-hover);
  --toast-radius:   10px;
  --toast-padding:  14px 20px;
  --toast-shadow:   var(--shadow-lg);
  --toast-max-width: 420px;
  --toast-gap:      8px;

  /* --- Component: Sidebar --- */
  --sidebar-bg:         var(--bg-base);
  --sidebar-border:     #1E2330;
  --sidebar-item-height: 40px;
  --sidebar-item-padding: 10px 20px;
  --sidebar-item-radius: 0;
  --sidebar-item-text:   var(--text-secondary);
  --sidebar-item-text-hover: var(--text-primary);
  --sidebar-item-text-active: var(--color-action-primary);
  --sidebar-item-bg-hover:  var(--bg-surface);
  --sidebar-item-bg-active: rgba(228, 80, 42, 0.04);
  --sidebar-indicator-width: 3px;
  --sidebar-indicator-color: var(--color-action-primary);
  --sidebar-transition:  var(--transition-normal);

  /* --- Component: Skeleton --- */
  --skeleton-bg:       var(--bg-surface);
  --skeleton-shimmer:  var(--bg-elevated);
  --skeleton-radius:   var(--radius-md);
  --skeleton-duration: 1.5s;

  /* --- Component: Toggle --- */
  --toggle-width:     40px;
  --toggle-height:    22px;
  --toggle-thumb:     18px;
  --toggle-bg-off:    #1E2330;
  --toggle-bg-on:     var(--color-success);
  --toggle-thumb-bg:  var(--primitive-gray-50);
  --toggle-transition: var(--transition-normal);

  /* --- Component: Pagination --- */
  --pagination-size:         36px;
  --pagination-radius:       var(--radius-md);
  --pagination-bg:           transparent;
  --pagination-bg-hover:     var(--bg-elevated);
  --pagination-bg-active:    var(--color-action-primary);
  --pagination-text:         var(--text-secondary);
  --pagination-text-active:  var(--text-on-primary);
  --pagination-border:       #1E2330;
}

/* ================================================================
   GLOBAL RESETS E UTILITARIOS BASE
   ================================================================ */

::selection {
  background: var(--selection-bg);
  color: var(--selection-text);
}

* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}

*::-webkit-scrollbar {
  width: var(--scrollbar-width);
  height: var(--scrollbar-width);
}

*::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
}

*::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: var(--radius-full);
}

*::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

/* ================================================================
   KEYFRAMES COMPLETOS
   ================================================================ */

@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideDown {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideInRight {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

@keyframes slideOutRight {
  from { transform: translateX(0); }
  to { transform: translateX(100%); }
}

@keyframes slideInLeft {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

@keyframes slideOutLeft {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.95); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes scaleOut {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(0.95); }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

@keyframes progress {
  from { width: 100%; }
  to { width: 0%; }
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

@keyframes expandWidth {
  from { width: 0; }
  to { width: 100%; }
}

@keyframes staggerFadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
```

---

## 3. Spec Completa de Componentes

### 3.a Button

**Por que evoluir:** A v1 define apenas 4 variantes sem sizes, sem icon-only, sem loading, sem focus. Um botao e o componente mais usado — precisa ser bullet-proof.

```css
/* ================================================================
   BUTTON — Todas as variantes, sizes e estados
   ================================================================ */

/* --- Base --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--button-gap);
  font-family: var(--button-font);
  font-size: var(--button-font-size);
  font-weight: var(--button-font-weight);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  border: 1px solid transparent;
  border-radius: var(--button-radius);
  padding: var(--button-padding-md);
  height: var(--button-height-md);
  transition:
    background-color var(--button-transition),
    color var(--button-transition),
    border-color var(--button-transition),
    box-shadow var(--button-transition),
    transform var(--button-transition),
    opacity var(--button-transition);
  position: relative;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}

/* --- Sizes --- */
.btn--sm {
  height: var(--button-height-sm);
  padding: var(--button-padding-sm);
  font-size: var(--text-small);
}

.btn--lg {
  height: var(--button-height-lg);
  padding: var(--button-padding-lg);
  font-size: var(--text-body-lg);
}

/* --- Icon Only --- */
.btn--icon {
  padding: 0;
  width: var(--button-height-md);
  /* Largura = altura para quadrado perfeito */
}
.btn--icon.btn--sm { width: var(--button-height-sm); }
.btn--icon.btn--lg { width: var(--button-height-lg); }

/* --- Variante: Primary --- */
.btn--primary {
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
  border-color: var(--button-primary-bg);
}
.btn--primary:hover:not(:disabled) {
  background: var(--button-primary-bg-hover);
  border-color: var(--button-primary-bg-hover);
  transform: translateY(-1px);
  box-shadow: var(--button-primary-shadow-hover);
}
.btn--primary:active:not(:disabled) {
  background: var(--button-primary-bg-active);
  border-color: var(--button-primary-bg-active);
  transform: translateY(0);
  box-shadow: none;
}

/* --- Variante: Secondary --- */
.btn--secondary {
  background: var(--button-secondary-bg);
  color: var(--button-secondary-text);
  border-color: var(--button-secondary-border);
}
.btn--secondary:hover:not(:disabled) {
  background: var(--button-secondary-bg-hover);
  border-color: var(--button-secondary-border-hover);
}
.btn--secondary:active:not(:disabled) {
  background: var(--button-secondary-bg-active);
}

/* --- Variante: Ghost --- */
.btn--ghost {
  background: var(--button-ghost-bg);
  color: var(--button-ghost-text);
}
.btn--ghost:hover:not(:disabled) {
  background: var(--button-ghost-bg-hover);
  color: var(--button-ghost-text-hover);
}
.btn--ghost:active:not(:disabled) {
  background: var(--button-ghost-bg-active);
}

/* --- Variante: Danger --- */
.btn--danger {
  background: var(--button-danger-bg);
  color: var(--button-danger-text);
  border-color: var(--button-danger-border);
}
.btn--danger:hover:not(:disabled) {
  background: var(--button-danger-bg-hover);
  color: var(--button-danger-text-hover);
  border-color: var(--button-danger-bg-hover);
}
.btn--danger:active:not(:disabled) {
  background: var(--primitive-red-700);
  border-color: var(--primitive-red-700);
}

/* --- Variante: Success --- */
.btn--success {
  background: var(--button-success-bg);
  color: var(--button-success-text);
  border-color: var(--button-success-border);
}
.btn--success:hover:not(:disabled) {
  background: var(--button-success-bg-hover);
  color: var(--button-success-text-hover);
  border-color: var(--button-success-bg-hover);
}
.btn--success:active:not(:disabled) {
  background: var(--primitive-green-700);
  border-color: var(--primitive-green-700);
}

/* --- Estado: Disabled --- */
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: var(--button-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}

/* --- Estado: Loading --- */
.btn--loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}
.btn--loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: var(--radius-full);
  animation: spin 0.6s linear infinite;
  /* currentColor herda a cor do botao, mas como text e transparent,
     precisamos forcar: */
}
.btn--primary.btn--loading::after {
  border-color: var(--button-primary-text);
  border-right-color: transparent;
}
.btn--secondary.btn--loading::after,
.btn--ghost.btn--loading::after {
  border-color: var(--text-secondary);
  border-right-color: transparent;
}
.btn--danger.btn--loading::after {
  border-color: var(--color-error);
  border-right-color: transparent;
}
.btn--success.btn--loading::after {
  border-color: var(--color-success);
  border-right-color: transparent;
}

/* Icon dentro de botao */
.btn__icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.btn--sm .btn__icon { width: 14px; height: 14px; }
.btn--lg .btn__icon { width: 18px; height: 18px; }
```

### 3.b Input

**Por que evoluir:** Inputs sao onde o usuario mais interage. A v1 nao define hover, success, readonly, labels, helpers, character count, nem variantes (search, password toggle, URL prefix).

```css
/* ================================================================
   INPUT — Todos os estados e variantes
   ================================================================ */

/* --- Container do campo (label + input + helper) --- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-family: var(--font-sans);
  font-size: var(--input-label-size);
  font-weight: var(--input-label-weight);
  color: var(--input-label-color);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.field__label--required::after {
  content: ' *';
  color: var(--color-error);
}

.field__helper {
  font-family: var(--font-sans);
  font-size: var(--input-helper-size);
  color: var(--input-helper-color);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.field__error {
  font-family: var(--font-sans);
  font-size: var(--input-helper-size);
  color: var(--input-error-color);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  animation: slideDown 150ms var(--ease-enter);
}

.field__counter {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  color: var(--text-muted);
  margin-left: auto;
}

/* --- Input Base --- */
.input {
  font-family: var(--input-font);
  font-size: var(--input-font-size);
  font-weight: var(--input-font-weight);
  color: var(--input-text);
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--input-radius);
  height: var(--input-height);
  padding: var(--input-padding-y) var(--input-padding-x);
  width: 100%;
  transition:
    border-color var(--input-transition),
    box-shadow var(--input-transition),
    background-color var(--input-transition);
  outline: none;
  -webkit-appearance: none;
}

.input::placeholder {
  color: var(--input-placeholder);
}

/* Hover */
.input:hover:not(:focus):not(:disabled):not([readonly]):not(.input--error) {
  border-color: var(--input-border-hover);
}

/* Focus */
.input:focus {
  border-color: var(--input-border-focus);
  box-shadow: var(--input-shadow-focus);
}

/* Error */
.input--error,
.field--error .input {
  border-color: var(--input-border-error);
}
.input--error:focus,
.field--error .input:focus {
  border-color: var(--input-border-error);
  box-shadow: var(--input-shadow-error);
}

/* Success */
.input--success,
.field--success .input {
  border-color: var(--input-border-success);
}
.input--success:focus,
.field--success .input:focus {
  border-color: var(--input-border-success);
  box-shadow: var(--input-shadow-success);
}

/* Disabled */
.input:disabled {
  opacity: var(--input-disabled-opacity);
  cursor: not-allowed;
  background: var(--input-bg-disabled);
  border-color: var(--input-border-disabled);
}

/* Readonly */
.input[readonly] {
  cursor: default;
  background: var(--bg-base);
  border-style: dashed;
}

/* --- Variante: Search (com icone) --- */
.input-group--search {
  position: relative;
}
.input-group--search .input {
  padding-left: 40px;
}
.input-group--search .input-group__icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  pointer-events: none;
}

/* --- Variante: Password (com toggle) --- */
.input-group--password {
  position: relative;
}
.input-group--password .input {
  padding-right: 44px;
}
.input-group--password .input-group__toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast), background var(--transition-fast);
}
.input-group--password .input-group__toggle:hover {
  color: var(--text-secondary);
  background: var(--bg-hover);
}

/* --- Variante: URL (com prefix) --- */
.input-group--url {
  display: flex;
  align-items: center;
}
.input-group--url .input-group__prefix {
  display: flex;
  align-items: center;
  height: var(--input-height);
  padding: 0 var(--space-3);
  background: var(--bg-base);
  border: 1px solid var(--input-border);
  border-right: none;
  border-radius: var(--input-radius) 0 0 var(--input-radius);
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  color: var(--text-muted);
  white-space: nowrap;
  user-select: none;
}
.input-group--url .input {
  border-radius: 0 var(--input-radius) var(--input-radius) 0;
  font-family: var(--font-mono);
  font-size: var(--text-mono);
}

/* --- Textarea --- */
.textarea {
  font-family: var(--input-font);
  font-size: var(--input-font-size);
  font-weight: var(--input-font-weight);
  color: var(--input-text);
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--input-radius);
  padding: var(--input-padding-y) var(--input-padding-x);
  width: 100%;
  min-height: 100px;
  resize: vertical;
  transition:
    border-color var(--input-transition),
    box-shadow var(--input-transition);
  outline: none;
}
.textarea::placeholder { color: var(--input-placeholder); }
.textarea:focus {
  border-color: var(--input-border-focus);
  box-shadow: var(--input-shadow-focus);
}
```

### 3.c Table

**Por que evoluir:** A v1 define uma tabela estatica. Producao precisa de: sort indicators, selecao, empty state, skeleton rows, e comportamento responsivo.

```css
/* ================================================================
   TABLE — Responsiva, sortable, selectable
   ================================================================ */

.table-container {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--card-radius);
  border: 1px solid var(--card-border);
  background: var(--card-bg);
}

.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}

/* --- Header --- */
.table__head th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--table-header-bg);
  color: var(--table-header-text);
  font-family: var(--font-sans);
  font-size: var(--table-header-size);
  font-weight: var(--table-header-weight);
  text-transform: uppercase;
  letter-spacing: var(--table-header-tracking);
  padding: var(--table-cell-padding);
  text-align: left;
  border-bottom: 1px solid var(--card-border);
  white-space: nowrap;
  user-select: none;
}

/* --- Sortable Column --- */
.table__head th[aria-sort] {
  cursor: pointer;
}
.table__head th[aria-sort]:hover {
  color: var(--text-secondary);
}
.table__sort-icon {
  display: inline-flex;
  margin-left: var(--space-1);
  opacity: 0.3;
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}
.table__head th[aria-sort="ascending"] .table__sort-icon,
.table__head th[aria-sort="descending"] .table__sort-icon {
  opacity: 1;
  color: var(--color-action-primary);
}
.table__head th[aria-sort="descending"] .table__sort-icon {
  transform: rotate(180deg);
}

/* --- Rows --- */
.table__body tr {
  transition: background-color var(--table-transition);
}
.table__body tr:hover {
  background: var(--table-row-bg-hover);
}
.table__body tr[aria-selected="true"] {
  background: var(--table-row-bg-selected);
}

/* --- Cells --- */
.table__body td {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  padding: var(--table-cell-padding);
  border-bottom: 1px solid var(--table-border);
  vertical-align: middle;
}

/* --- Checkbox Column --- */
.table__checkbox {
  width: 48px;
  text-align: center;
}
.table__checkbox input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
}

/* --- Empty State --- */
.table__empty {
  padding: var(--space-16) var(--space-8);
  text-align: center;
}
.table__empty-icon {
  width: 48px;
  height: 48px;
  color: var(--text-muted);
  margin: 0 auto var(--space-4);
  opacity: 0.5;
}
.table__empty-title {
  font-size: var(--text-body-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}
.table__empty-description {
  font-size: var(--text-body);
  color: var(--text-muted);
  max-width: 320px;
  margin: 0 auto;
}

/* --- Skeleton Rows --- */
.table__skeleton td {
  padding: var(--table-cell-padding);
}
.table__skeleton .skeleton-line {
  height: 14px;
  border-radius: var(--radius-xs);
  background: var(--skeleton-bg);
  position: relative;
  overflow: hidden;
}
.table__skeleton .skeleton-line::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(90deg, transparent, var(--skeleton-shimmer), transparent);
  animation: shimmer var(--skeleton-duration) infinite;
}
/* Larguras variadas para parecer natural */
.table__skeleton td:nth-child(1) .skeleton-line { width: 60%; }
.table__skeleton td:nth-child(2) .skeleton-line { width: 80%; }
.table__skeleton td:nth-child(3) .skeleton-line { width: 45%; }
.table__skeleton td:nth-child(4) .skeleton-line { width: 30%; }

/* --- Pagination --- */
.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-5) var(--space-4);
  border-top: 1px solid var(--card-border);
}

.pagination__info {
  font-family: var(--font-sans);
  font-size: var(--text-small);
  color: var(--text-muted);
}

.pagination__controls {
  display: flex;
  gap: var(--space-1);
}

.pagination__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--pagination-size);
  height: var(--pagination-size);
  border-radius: var(--pagination-radius);
  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--pagination-text);
  background: var(--pagination-bg);
  border: 1px solid var(--pagination-border);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
  padding: 0 var(--space-2);
}

.pagination__btn:hover:not(:disabled):not(.pagination__btn--active) {
  background: var(--pagination-bg-hover);
  border-color: var(--border-hover);
}

.pagination__btn--active {
  background: var(--pagination-bg-active);
  color: var(--pagination-text-active);
  border-color: var(--pagination-bg-active);
  cursor: default;
}

.pagination__btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.pagination__btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}
```

### 3.d Card

**Por que evoluir:** A v1 define apenas card base e stat card. Faltam: interactive, selected, loading, chart-container.

```css
/* ================================================================
   CARD — Variantes e estados completos
   ================================================================ */

.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  padding: var(--card-padding);
  box-shadow: var(--card-shadow);
  transition:
    border-color var(--card-transition),
    box-shadow var(--card-transition),
    transform var(--card-transition);
}

/* --- Variante: Interactive (clicavel) --- */
.card--interactive {
  cursor: pointer;
}
.card--interactive:hover {
  border-color: var(--card-border-hover);
  box-shadow: var(--card-shadow-hover);
}
.card--interactive:active {
  transform: scale(0.995);
  /* Scale sutil transmite "clique" sem parecer bugado */
}

/* --- Estado: Selected --- */
.card--selected {
  border-color: var(--color-action-primary);
  box-shadow: var(--shadow-glow-primary);
}

/* --- Variante: Stat --- */
.card--stat {
  padding: var(--space-5) var(--space-6);
  position: relative;
}
.card--stat::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: var(--card-radius) var(--card-radius) 0 0;
  /* Cor definida via variavel inline: style="--stat-color: var(--color-action-primary)" */
  background: var(--stat-color, var(--color-action-primary));
}
.card--stat .card__label {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.card--stat .card__value {
  font-size: var(--primitive-size-28);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
  margin-top: var(--space-2);
  font-variant-numeric: tabular-nums;
}
.card--stat .card__trend {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  margin-top: var(--space-1);
}
.card__trend--up { color: var(--color-success); }
.card__trend--down { color: var(--color-error); }
.card__trend--neutral { color: var(--text-muted); }

/* --- Variante: Chart Container --- */
.card--chart {
  padding: var(--space-6);
}
.card--chart .card__chart-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: var(--space-6);
}
.card--chart .card__chart-title {
  font-size: var(--text-h4);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}
.card--chart .card__chart-subtitle {
  font-size: var(--text-small);
  color: var(--text-muted);
  margin-top: var(--space-1);
}
.card--chart .card__chart-area {
  position: relative;
  min-height: 200px;
}

/* --- Estado: Loading (Skeleton) --- */
.card--loading {
  pointer-events: none;
}
.card--loading .skeleton-block {
  background: var(--skeleton-bg);
  border-radius: var(--radius-xs);
  position: relative;
  overflow: hidden;
}
.card--loading .skeleton-block::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--skeleton-shimmer), transparent);
  animation: shimmer var(--skeleton-duration) infinite;
}
```

### 3.e Badge/Tag

**Por que evoluir:** A v1 define apenas ativo/inativo. Faltam: warning, info, count badge, sizes, sem dot.

```css
/* ================================================================
   BADGE — Variantes de status, count, sizes
   ================================================================ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: var(--badge-font-size);
  font-weight: var(--badge-font-weight);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: var(--badge-radius);
  padding: var(--badge-padding-md);
  line-height: 1;
  white-space: nowrap;
}

/* --- Sizes --- */
.badge--sm {
  padding: var(--badge-padding-sm);
  font-size: 10px;
}

/* --- Dot indicator --- */
.badge__dot {
  width: var(--badge-dot-size-md);
  height: var(--badge-dot-size-md);
  border-radius: var(--radius-full);
  flex-shrink: 0;
}
.badge--sm .badge__dot {
  width: var(--badge-dot-size-sm);
  height: var(--badge-dot-size-sm);
}

/* --- Status: Active --- */
.badge--active {
  background: var(--color-success-subtle);
  color: var(--color-success);
}
.badge--active .badge__dot { background: var(--color-success); }

/* --- Status: Inactive --- */
.badge--inactive {
  background: var(--color-error-subtle);
  color: var(--color-error);
}
.badge--inactive .badge__dot { background: var(--color-error); }

/* --- Status: Warning --- */
.badge--warning {
  background: var(--color-warning-subtle);
  color: var(--color-warning);
}
.badge--warning .badge__dot { background: var(--color-warning); }

/* --- Status: Info --- */
.badge--info {
  background: var(--color-info-subtle);
  color: var(--color-info);
}
.badge--info .badge__dot { background: var(--color-info); }

/* --- Variante: Count --- */
.badge--count {
  background: var(--bg-elevated);
  color: var(--text-secondary);
  min-width: 20px;
  text-align: center;
  justify-content: center;
  text-transform: none;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* --- Variante: Label (neutro) --- */
.badge--label {
  background: var(--bg-elevated);
  color: var(--text-secondary);
  text-transform: none;
  letter-spacing: 0;
}
```

### 3.f Modal/Drawer

**Por que evoluir:** A v1 define modal basico sem exit animation, sem focus trap spec, sem scroll lock, sem drawer. Drawer e essencial para editar links no mobile.

```css
/* ================================================================
   MODAL
   ================================================================ */

/* --- Overlay --- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: var(--z-modal-overlay);
  animation: fadeIn var(--duration-fast) var(--ease-enter);
}
.modal-overlay--exit {
  animation: fadeOut var(--duration-fast) var(--ease-exit);
}

/* --- Container --- */
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--modal-bg);
  border: 1px solid var(--modal-border);
  border-radius: var(--modal-radius);
  padding: var(--modal-padding);
  max-width: var(--modal-max-width);
  min-width: var(--modal-min-width);
  width: 90vw;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: var(--modal-shadow);
  z-index: var(--z-modal);
  animation: scaleIn var(--duration-normal) var(--ease-enter);
}
.modal--exit {
  animation: scaleOut var(--duration-fast) var(--ease-exit);
}

/* Scroll lock no body */
body.modal-open {
  overflow: hidden;
  /* Padding-right para compensar scrollbar desaparecendo
     (calculado via JS: document.body.style.paddingRight = scrollbarWidth + 'px') */
}

.modal__header {
  margin-bottom: var(--space-6);
}
.modal__title {
  font-family: var(--font-sans);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}
.modal__description {
  font-size: var(--text-body);
  color: var(--text-secondary);
  margin-top: var(--space-2);
}

/* Botao de fechar */
.modal__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.modal__close:hover {
  background: var(--bg-hover);
  color: var(--text-secondary);
}
.modal__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}

.modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--modal-border);
}

/* ================================================================
   DRAWER
   ================================================================ */

.drawer-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: var(--z-drawer-overlay);
  animation: fadeIn var(--duration-fast) var(--ease-enter);
}
.drawer-overlay--exit {
  animation: fadeOut var(--duration-fast) var(--ease-exit);
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--drawer-width);
  max-width: 100vw;
  background: var(--drawer-bg);
  border-left: 1px solid var(--drawer-border);
  box-shadow: var(--drawer-shadow);
  z-index: var(--z-drawer);
  overflow-y: auto;
  animation: slideInRight var(--duration-normal) var(--ease-enter);
}
.drawer--exit {
  animation: slideOutRight var(--duration-fast) var(--ease-exit);
}

.drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-6);
  border-bottom: 1px solid var(--drawer-border);
  position: sticky;
  top: 0;
  background: var(--drawer-bg);
  z-index: 1;
}

.drawer__body {
  padding: var(--space-6);
}

.drawer__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-6);
  border-top: 1px solid var(--drawer-border);
  position: sticky;
  bottom: 0;
  background: var(--drawer-bg);
}

/* ================================================================
   FOCUS TRAP — Regras CSS complementares (logica via JS)
   O JS deve:
   1. Ao abrir: salvar document.activeElement, focar primeiro elemento focavel dentro do modal/drawer
   2. Em keydown Tab: ciclar focus entre elementos focaveis internos
   3. Em keydown Escape: fechar e restaurar focus ao elemento salvo
   ================================================================ */
.modal:focus,
.drawer:focus {
  outline: none;
}
```

### 3.g Toast/Notification

**Por que evoluir:** A v1 define toast basico sem action button, sem stack, sem progress bar, sem pause on hover.

```css
/* ================================================================
   TOAST — Stack, progress, action button
   ================================================================ */

.toast-container {
  position: fixed;
  bottom: var(--space-6);
  right: var(--space-6);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column-reverse;
  gap: var(--toast-gap);
  pointer-events: none;
  max-width: var(--toast-max-width);
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  background: var(--toast-bg);
  border: 1px solid var(--toast-border);
  border-radius: var(--toast-radius);
  padding: var(--toast-padding);
  box-shadow: var(--toast-shadow);
  pointer-events: auto;
  position: relative;
  overflow: hidden;
  animation: slideInRight var(--duration-slow) var(--ease-spring);
}
.toast--exit {
  animation: slideOutRight var(--duration-fast) var(--ease-exit) forwards;
}

/* Barra lateral de cor */
.toast::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: 3px 0 0 3px;
  background: var(--toast-accent, var(--color-info));
}
.toast--success { --toast-accent: var(--color-success); }
.toast--error   { --toast-accent: var(--color-error); }
.toast--warning { --toast-accent: var(--color-warning); }
.toast--info    { --toast-accent: var(--color-info); }

/* Icone */
.toast__icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--toast-accent, var(--color-info));
}

/* Conteudo */
.toast__content {
  flex: 1;
  min-width: 0;
}
.toast__message {
  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  line-height: var(--leading-relaxed);
}
.toast__description {
  font-size: var(--text-small);
  color: var(--text-secondary);
  margin-top: var(--space-1);
}

/* Action button */
.toast__action {
  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  color: var(--toast-accent, var(--color-info));
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-1) 0;
  margin-top: var(--space-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.toast__action:hover {
  opacity: 0.8;
}

/* Close button */
.toast__close {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
  border-radius: var(--radius-xs);
  transition: color var(--transition-fast);
}
.toast__close:hover {
  color: var(--text-secondary);
}

/* Progress bar (auto-dismiss visual) */
.toast__progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  background: var(--toast-accent, var(--color-info));
  border-radius: 0 0 0 var(--toast-radius);
  animation: progress 4s linear forwards;
  opacity: 0.5;
}

/* Pause progress on hover */
.toast:hover .toast__progress {
  animation-play-state: paused;
}

/* Stack behavior: toasts mais antigos ficam menores e atras */
.toast-container .toast:not(:last-child) {
  opacity: 0.8;
  transform: scale(0.97);
}
.toast-container .toast:not(:last-child):not(:nth-last-child(2)) {
  opacity: 0.6;
  transform: scale(0.94);
}
/* Maximo 3 vistos, restante escondido */
.toast-container .toast:nth-child(n+4) {
  display: none;
}
```

### 3.h Sidebar Navigation

**Por que evoluir:** A v1 define apenas estado expandido. Faltam: collapsed (64px icons-only), mobile overlay, transicao animada.

```css
/* ================================================================
   SIDEBAR — Expanded, Collapsed, Mobile Overlay
   ================================================================ */

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-width-expanded);
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  z-index: var(--z-sidebar);
  transition: width var(--sidebar-transition);
  overflow: hidden;
}

/* --- Logo --- */
.sidebar__logo {
  padding: var(--space-5) var(--space-5) var(--space-6) var(--space-5);
  border-bottom: 1px solid var(--sidebar-border);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 64px;
}
.sidebar__logo-text {
  font-family: var(--font-sans);
  font-size: var(--text-h4);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  transition: opacity var(--transition-fast);
}

/* --- Nav --- */
.sidebar__nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) 0;
}

.sidebar__section-label {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-5) var(--space-5) var(--space-2) var(--space-5);
  white-space: nowrap;
  overflow: hidden;
}

.sidebar__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--sidebar-item-padding);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  color: var(--sidebar-item-text);
  text-decoration: none;
  cursor: pointer;
  border-left: var(--sidebar-indicator-width) solid transparent;
  transition:
    color var(--transition-fast),
    background var(--transition-fast),
    border-color var(--transition-fast);
  white-space: nowrap;
  min-height: var(--sidebar-item-height);
}
.sidebar__item:hover {
  color: var(--sidebar-item-text-hover);
  background: var(--sidebar-item-bg-hover);
}
.sidebar__item--active {
  color: var(--sidebar-item-text-active);
  background: var(--sidebar-item-bg-active);
  border-left-color: var(--sidebar-indicator-color);
  font-weight: var(--weight-semibold);
}
.sidebar__item:focus-visible {
  outline: none;
  box-shadow: inset var(--focus-ring-shadow);
}

.sidebar__item-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.sidebar__item-text {
  overflow: hidden;
  text-overflow: ellipsis;
  transition: opacity var(--transition-fast);
}

/* --- Footer --- */
.sidebar__footer {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--sidebar-border);
}

/* --- Collapsed State (64px, icons only) --- */
.sidebar--collapsed {
  width: var(--sidebar-width-collapsed);
}
.sidebar--collapsed .sidebar__logo-text,
.sidebar--collapsed .sidebar__item-text,
.sidebar--collapsed .sidebar__section-label {
  opacity: 0;
  width: 0;
  overflow: hidden;
}
.sidebar--collapsed .sidebar__item {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
  border-left-width: 0;
}
.sidebar--collapsed .sidebar__item--active {
  /* No collapsed, usar background mais forte em vez de border-left */
  background: var(--color-action-primary-subtle);
  border-radius: var(--radius-sm);
  margin: 0 var(--space-2);
}

/* Tooltip no collapsed (via title ou custom tooltip) */
.sidebar--collapsed .sidebar__item {
  position: relative;
}

/* --- Collapse Toggle Button --- */
.sidebar__toggle {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elevated);
  border: 1px solid var(--sidebar-border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
}
.sidebar__toggle:hover {
  color: var(--text-secondary);
  background: var(--bg-hover);
}

/* --- Content area adjustment --- */
.layout__content {
  margin-left: var(--sidebar-width-expanded);
  transition: margin-left var(--sidebar-transition);
}
.sidebar--collapsed ~ .layout__content,
.layout__content--collapsed {
  margin-left: var(--sidebar-width-collapsed);
}

/* --- Mobile overlay (via media query na secao 4) --- */
.sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  z-index: calc(var(--z-sidebar) - 1);
  animation: fadeIn var(--duration-fast) var(--ease-enter);
}
.sidebar-overlay--visible {
  display: block;
}
```

### 3.i Form Components

**Por que evoluir:** A v1 nao define select, checkbox, radio, toggle com todos os estados, nem date picker trigger.

```css
/* ================================================================
   SELECT / DROPDOWN
   ================================================================ */

.select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  background-color: var(--bg-input);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23515B6A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
  border: 1px solid var(--input-border);
  border-radius: var(--input-radius);
  height: var(--input-height);
  padding: var(--input-padding-y) 36px var(--input-padding-y) var(--input-padding-x);
  cursor: pointer;
  transition:
    border-color var(--input-transition),
    box-shadow var(--input-transition);
  outline: none;
  width: 100%;
}
.select:hover:not(:disabled) {
  border-color: var(--input-border-hover);
}
.select:focus {
  border-color: var(--input-border-focus);
  box-shadow: var(--input-shadow-focus);
}
.select:disabled {
  opacity: var(--input-disabled-opacity);
  cursor: not-allowed;
}

/* ================================================================
   TOGGLE / SWITCH
   ================================================================ */

.toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
}

.toggle__track {
  position: relative;
  width: var(--toggle-width);
  height: var(--toggle-height);
  background: var(--toggle-bg-off);
  border-radius: var(--radius-full);
  transition: background var(--toggle-transition);
  flex-shrink: 0;
}

.toggle__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: var(--toggle-thumb);
  height: var(--toggle-thumb);
  background: var(--toggle-thumb-bg);
  border-radius: var(--radius-full);
  transition: transform var(--toggle-transition);
  box-shadow: var(--shadow-xs);
}

/* Hidden input drives state */
.toggle__input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.toggle__input:checked + .toggle__track {
  background: var(--toggle-bg-on);
}
.toggle__input:checked + .toggle__track .toggle__thumb {
  transform: translateX(calc(var(--toggle-width) - var(--toggle-thumb) - 4px));
}

.toggle__input:focus-visible + .toggle__track {
  box-shadow: var(--focus-ring-shadow);
}

.toggle__input:disabled + .toggle__track {
  opacity: var(--button-disabled-opacity);
  cursor: not-allowed;
}

.toggle__label {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  user-select: none;
}

/* Toggle loading (durante optimistic update) */
.toggle--loading .toggle__track {
  opacity: 0.6;
}
.toggle--loading .toggle__thumb {
  animation: pulse 1s infinite;
}

/* ================================================================
   CHECKBOX
   ================================================================ */

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  position: relative;
}

.checkbox__input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.checkbox__box {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border-default);
  border-radius: var(--radius-xs);
  background: var(--bg-input);
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
  flex-shrink: 0;
}

.checkbox__icon {
  width: 12px;
  height: 12px;
  color: var(--text-on-primary);
  opacity: 0;
  transform: scale(0.5);
  transition: all var(--transition-fast);
}

.checkbox__input:checked + .checkbox__box {
  background: var(--color-action-primary);
  border-color: var(--color-action-primary);
}
.checkbox__input:checked + .checkbox__box .checkbox__icon {
  opacity: 1;
  transform: scale(1);
}

.checkbox__input:focus-visible + .checkbox__box {
  box-shadow: var(--focus-ring-shadow);
}

.checkbox__input:disabled + .checkbox__box {
  opacity: var(--button-disabled-opacity);
  cursor: not-allowed;
}

/* Indeterminate */
.checkbox__input:indeterminate + .checkbox__box {
  background: var(--color-action-primary);
  border-color: var(--color-action-primary);
}
.checkbox__input:indeterminate + .checkbox__box .checkbox__icon {
  opacity: 1;
  transform: scale(1);
  /* Icon muda para dash via JS/HTML */
}

.checkbox__label {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  user-select: none;
}

/* ================================================================
   RADIO GROUP
   ================================================================ */

.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.radio-group--horizontal {
  flex-direction: row;
  gap: var(--space-6);
}

.radio {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  position: relative;
}

.radio__input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.radio__circle {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border-default);
  border-radius: var(--radius-full);
  background: var(--bg-input);
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
  flex-shrink: 0;
}

.radio__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-action-primary);
  opacity: 0;
  transform: scale(0);
  transition: all var(--transition-fast) var(--ease-spring);
}

.radio__input:checked + .radio__circle {
  border-color: var(--color-action-primary);
}
.radio__input:checked + .radio__circle .radio__dot {
  opacity: 1;
  transform: scale(1);
}

.radio__input:focus-visible + .radio__circle {
  box-shadow: var(--focus-ring-shadow);
}

.radio__input:disabled + .radio__circle {
  opacity: var(--button-disabled-opacity);
  cursor: not-allowed;
}

.radio__label {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  user-select: none;
}

/* ================================================================
   DATE PICKER TRIGGER
   (O datepicker em si usa biblioteca nativa ou leve;
    aqui definimos apenas o trigger button style)
   ================================================================ */

.date-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--input-border);
  border-radius: var(--input-radius);
  height: var(--input-height);
  padding: var(--input-padding-y) var(--input-padding-x);
  cursor: pointer;
  transition:
    border-color var(--input-transition),
    box-shadow var(--input-transition);
  white-space: nowrap;
}
.date-trigger:hover {
  border-color: var(--input-border-hover);
}
.date-trigger:focus-visible {
  outline: none;
  border-color: var(--input-border-focus);
  box-shadow: var(--input-shadow-focus);
}
.date-trigger__icon {
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.date-trigger__placeholder {
  color: var(--text-placeholder);
}
```

### 3.j Data Display

**Por que evoluir:** A v1 define skeleton shimmer generico, mas producao precisa de skeletons especificos, empty states, error patterns, copy button completo, e URL/slug display formatado.

```css
/* ================================================================
   SKELETON LOADERS — Por tipo de componente
   ================================================================ */

/* Base skeleton */
.skeleton {
  background: var(--skeleton-bg);
  border-radius: var(--skeleton-radius);
  position: relative;
  overflow: hidden;
  animation: pulse 2s ease-in-out infinite;
}
.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--skeleton-shimmer) 50%,
    transparent 100%
  );
  animation: shimmer var(--skeleton-duration) infinite;
}

/* Skeleton: Text line */
.skeleton--text {
  height: 14px;
  width: 100%;
  border-radius: var(--radius-xs);
}
.skeleton--text-short { width: 40%; }
.skeleton--text-medium { width: 70%; }

/* Skeleton: Heading */
.skeleton--heading {
  height: 24px;
  width: 50%;
  border-radius: var(--radius-xs);
}

/* Skeleton: Avatar/Circle */
.skeleton--circle {
  border-radius: var(--radius-full);
}

/* Skeleton: Card */
.skeleton--card {
  height: 120px;
  border-radius: var(--card-radius);
}

/* Skeleton: Stat Card */
.skeleton--stat {
  padding: var(--space-5) var(--space-6);
  border-radius: var(--card-radius);
  border: 1px solid var(--card-border);
}

/* Skeleton: Chart */
.skeleton--chart {
  height: 240px;
  border-radius: var(--card-radius);
}

/* Skeleton: Badge */
.skeleton--badge {
  height: 22px;
  width: 64px;
  border-radius: var(--radius-full);
}

/* ================================================================
   EMPTY STATE PATTERN
   ================================================================ */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-16) var(--space-8);
  max-width: 400px;
  margin: 0 auto;
}

.empty-state__icon {
  width: 64px;
  height: 64px;
  color: var(--text-muted);
  opacity: 0.4;
  margin-bottom: var(--space-6);
}

.empty-state__title {
  font-family: var(--font-sans);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}

.empty-state__description {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-muted);
  line-height: var(--leading-loose);
  margin-bottom: var(--space-8);
}

.empty-state__action {
  /* Usa .btn--primary */
}

/* ================================================================
   ERROR STATE PATTERN
   ================================================================ */

.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-16) var(--space-8);
  max-width: 400px;
  margin: 0 auto;
}

.error-state__icon {
  width: 48px;
  height: 48px;
  color: var(--color-error);
  opacity: 0.6;
  margin-bottom: var(--space-6);
}

.error-state__title {
  font-family: var(--font-sans);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}

.error-state__description {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-muted);
  line-height: var(--leading-loose);
  margin-bottom: var(--space-8);
}

.error-state__action {
  /* Usa .btn--secondary */
}

/* ================================================================
   STAT NUMBER COM TREND
   ================================================================ */

.stat-value {
  font-family: var(--font-sans);
  font-size: var(--primitive-size-28);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.stat-trend {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
}
.stat-trend--up {
  color: var(--color-success);
}
.stat-trend--down {
  color: var(--color-error);
}
.stat-trend__icon {
  width: 14px;
  height: 14px;
}

/* ================================================================
   PROGRESS BAR
   ================================================================ */

.progress {
  width: 100%;
  height: 4px;
  background: var(--border-default);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.progress__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: var(--color-action-primary);
  transition: width var(--transition-slow);
  /* Cor customizavel: style="--progress-color: var(--color-info)" */
  background: var(--progress-color, var(--color-action-primary));
}

.progress--lg {
  height: 8px;
}

/* ================================================================
   COPY-TO-CLIPBOARD BUTTON
   ================================================================ */

.copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition-fast);
  position: relative;
}
.copy-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.copy-btn:active {
  transform: scale(0.92);
}
.copy-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}
.copy-btn__icon {
  width: 16px;
  height: 16px;
  transition: opacity var(--transition-instant);
}

/* Estado: Copiado */
.copy-btn--copied {
  color: var(--color-success);
}
.copy-btn--copied:hover {
  color: var(--color-success);
}

/* Tooltip "Copiado!" */
.copy-btn__tooltip {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--color-success);
  color: var(--text-inverse);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  font-weight: var(--weight-medium);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}
.copy-btn--copied .copy-btn__tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ================================================================
   URL DISPLAY (truncado com dominio)
   ================================================================ */

.url-display {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  max-width: 100%;
  min-width: 0;
}

.url-display__domain {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.url-display__path {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* ================================================================
   SLUG DISPLAY
   ================================================================ */

.slug-display {
  display: inline-flex;
  align-items: center;
  gap: 0;
}

.slug-display__prefix {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  color: var(--text-muted);
}

.slug-display__value {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: var(--weight-medium);
  color: var(--color-action-primary);
  cursor: pointer;
  text-decoration: none;
}
.slug-display__value:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
```

---

## 4. Design Responsivo Completo

### 4.1 Filosofia

**Por que definir agora:** A v1 ignorou responsividade quase completamente. Um dashboard SaaS precisa funcionar no celular para checar metricas rapidamente, e no tablet para apresentacoes.

**Abordagem:** Desktop-first (porque o dashboard e a experiencia primaria), com adaptacoes regressivas para telas menores.

### 4.2 Breakpoints e Comportamento

```css
/* ================================================================
   RESPONSIVE — Breakpoints e comportamento
   ================================================================ */

/* --- WIDE: 1440px+ --- */
/* Comportamento padrao do sistema. Nada muda. */

/* --- DESKTOP: 1024px - 1439px --- */
@media (max-width: 1439px) {
  :root {
    --content-padding-x: var(--space-8);
    --content-padding-y: var(--space-6);
  }

  /* Stats cards: 2x2 em vez de 4x1 */
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Tabela: colunas menos prioritarias ficam menores */
  .table__col--hide-desktop {
    display: none;
  }
}

/* --- TABLET: 768px - 1023px --- */
@media (max-width: 1023px) {
  :root {
    --content-padding-x: var(--space-6);
    --content-padding-y: var(--space-5);
    --text-h1: var(--primitive-size-28);
    --text-h2: var(--primitive-size-20);
    --text-h3: var(--primitive-size-16);
  }

  /* Sidebar: collapsed por padrao, toggle para expandir como overlay */
  .sidebar {
    width: var(--sidebar-width-collapsed);
  }
  .sidebar.sidebar--mobile-open {
    width: var(--sidebar-width-expanded);
    z-index: var(--z-modal);
    box-shadow: var(--shadow-xl);
  }

  .layout__content {
    margin-left: var(--sidebar-width-collapsed);
  }

  /* Stats cards: 2x2 */
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Grid de dados complementares: empilhado */
  .data-grid-2col {
    grid-template-columns: 1fr;
  }

  /* Tabela: scroll horizontal com sombra de indicacao */
  .table-container {
    position: relative;
  }
  .table-container::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 24px;
    background: linear-gradient(to right, transparent, var(--bg-base));
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--transition-fast);
  }
  .table-container--scrollable::after {
    opacity: 1;
  }

  /* Colunas de menor prioridade somem */
  .table__col--hide-tablet {
    display: none;
  }

  /* Modal: quase full width */
  .modal {
    width: 95vw;
    min-width: unset;
  }

  /* Drawer: full screen */
  .drawer {
    width: 100vw;
    border-left: none;
  }
}

/* --- MOBILE: 320px - 767px --- */
@media (max-width: 767px) {
  :root {
    --content-padding-x: var(--space-4);
    --content-padding-y: var(--space-4);
    --text-h1: var(--primitive-size-24);
    --text-h2: var(--primitive-size-20);
    --text-h3: var(--primitive-size-16);
    --text-body: var(--primitive-size-14);
    --card-padding: var(--space-4);
    --modal-padding: var(--space-5);
  }

  /* Sidebar: escondida. Abre como overlay full com slide da esquerda */
  .sidebar {
    transform: translateX(-100%);
    width: var(--sidebar-width-expanded);
    z-index: var(--z-modal);
    transition: transform var(--sidebar-transition);
  }
  .sidebar.sidebar--mobile-open {
    transform: translateX(0);
    box-shadow: var(--shadow-xl);
  }
  .sidebar-overlay--visible {
    display: block;
  }

  .layout__content {
    margin-left: 0;
  }

  /* Mobile header fixo com hamburger */
  .mobile-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 56px;
    padding: 0 var(--space-4);
    background: var(--bg-base);
    border-bottom: 1px solid var(--border-default);
    position: sticky;
    top: 0;
    z-index: var(--z-header);
  }

  /* Stats cards: empilhados, 2 por linha */
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3);
  }

  /* Page header: empilhado */
  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
  }
  .page-header .btn {
    width: 100%;
  }

  /* Filtros: empilhados */
  .filters-bar {
    flex-direction: column;
  }
  .filters-bar .input,
  .filters-bar .select {
    max-width: 100%;
    width: 100%;
  }

  /* Tabela: scroll horizontal obrigatorio */
  .table {
    min-width: 600px;
  }
  .table__col--hide-mobile {
    display: none;
  }

  /* Acoes de tabela: menu overflow (tres pontos) em vez de botoes inline */
  .table__actions--desktop {
    display: none;
  }
  .table__actions--mobile {
    display: flex;
  }

  /* Modal: bottom sheet no mobile */
  .modal {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    transform: none;
    width: 100%;
    max-width: 100%;
    min-width: unset;
    max-height: 90vh;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    animation: slideUp var(--duration-normal) var(--ease-enter);
  }
  .modal--exit {
    animation: slideDown var(--duration-fast) var(--ease-exit);
  }

  /* Drawer: full screen no mobile */
  .drawer {
    width: 100vw;
    border-left: none;
  }

  /* Toast: full width no mobile */
  .toast-container {
    left: var(--space-4);
    right: var(--space-4);
    bottom: var(--space-4);
    max-width: 100%;
  }

  /* Pagination: simplificada */
  .pagination {
    flex-direction: column;
    gap: var(--space-3);
    align-items: center;
  }

  /* Login: full screen form */
  .login-split__brand {
    display: none;
  }
  .login-split__form {
    width: 100%;
    padding: var(--space-6);
  }
}

/* --- Esconder/mostrar helpers --- */
.hide-mobile  { /* visivel acima de 768 */ }
.hide-tablet  { /* visivel acima de 1024 */ }
.hide-desktop { /* visivel abaixo de 1024 */ }

@media (max-width: 767px) {
  .hide-mobile { display: none !important; }
}
@media (max-width: 1023px) {
  .hide-tablet { display: none !important; }
}
@media (min-width: 1024px) {
  .hide-desktop { display: none !important; }
}

/* Mobile: mostrar header com hamburger */
@media (min-width: 768px) {
  .mobile-header { display: none; }
}

/* Desktop: esconder acoes mobile da tabela */
@media (min-width: 768px) {
  .table__actions--mobile { display: none; }
}
```

---

## 5. Acessibilidade

### 5.1 Verificacao de Contraste WCAG AA

**Por que isso importa:** WCAG AA exige ratio minimo de 4.5:1 para texto normal e 3:1 para texto grande (18px+ bold ou 24px+).

| Combinacao | Ratio | WCAG AA | Status |
|---|---|---|---|
| `#F0EDE8` (text) em `#0F1114` (bg-base) | **14.8:1** | Passa | OK |
| `#F0EDE8` (text) em `#161920` (bg-card) | **12.6:1** | Passa | OK |
| `#8A9BB0` (secondary) em `#0F1114` | **5.8:1** | Passa | OK |
| `#8A9BB0` (secondary) em `#161920` | **4.9:1** | Passa | OK |
| `#515B6A` (muted) em `#0F1114` | **3.2:1** | **Falha para texto normal** | ATENCAO |
| `#515B6A` (muted) em `#161920` | **2.7:1** | **Falha** | PROBLEMA |
| `#E4502A` (primary) em `#0F1114` | **4.6:1** | Passa (limite) | OK |
| `#E4502A` (primary) em `#161920` | **3.9:1** | **Falha para texto normal** | ATENCAO |
| `#E4502A` (primary) em `#FFFFFF` (btn text) | **3.9:1** | Passa para texto grande | ATENCAO |
| `#2ECC71` (success) em `#0F1114` | **7.4:1** | Passa | OK |
| `#E74C3C` (error) em `#0F1114` | **4.4:1** | Passa (limite) | OK |

**Resolucoes necessarias:**

1. **`--text-muted` (`#515B6A`):** Usar apenas em texto large (>=12px semibold/uppercase como headers de tabela) ou texto decorativo. Para texto informativo legivel, usar `--text-secondary` (`#8A9BB0`).

2. **`--color-action-primary` em cards:** Quando o coral e usado como texto sobre `#161920`, garantir que e pelo menos 14px semibold (ratio 3.9:1 passa para texto grande).

3. **Botao primario:** O branco sobre coral (#E4502A) tem ratio 3.9:1 — passa para texto 14px bold (que e o caso). Se reduzir o peso ou tamanho, falha. Manter `font-weight: 600` obrigatorio.

### 5.2 Focus Indicators

```css
/* ================================================================
   ACESSIBILIDADE — Focus visible consistente
   ================================================================ */

/*
  Estrategia: Usar :focus-visible (nao :focus) para mostrar
  indicadores apenas via teclado, nao via mouse.
  Por que: Mouse users nao precisam do indicador visual,
  e ele pode parecer um bug para eles.
*/

/* Reset global — remover outline padrao do browser */
*:focus {
  outline: none;
}

/* Aplicar focus ring consistente via :focus-visible */
*:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Componentes que usam box-shadow em vez de outline
   (porque outline nao respeita border-radius em todos browsers) */
.btn:focus-visible,
.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible,
.toggle__input:focus-visible + .toggle__track,
.checkbox__input:focus-visible + .checkbox__box,
.radio__input:focus-visible + .radio__circle,
.copy-btn:focus-visible,
.pagination__btn:focus-visible,
.date-trigger:focus-visible,
.modal__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}

/* Inputs ja tem seus proprios focus styles (border + glow),
   entao o focus-visible adiciona o ring externo */
.input:focus-visible {
  border-color: var(--input-border-focus);
  box-shadow: var(--input-shadow-focus), var(--focus-ring-shadow);
}

/* Skip to content link (primeiro elemento focavel da pagina) */
.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-4);
  background: var(--color-action-primary);
  color: var(--text-on-primary);
  padding: var(--space-2) var(--space-4);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  z-index: var(--z-max);
  text-decoration: none;
  transition: top var(--transition-fast);
}
.skip-link:focus {
  top: 0;
}
```

### 5.3 Navegacao por Teclado

| Contexto | Tecla | Acao |
|---|---|---|
| Geral | `Tab` | Navegar entre elementos focaveis |
| Geral | `Shift+Tab` | Navegar reverso |
| Modal/Drawer | `Escape` | Fechar |
| Modal/Drawer | `Tab` | Ciclar focus interno (trap) |
| Dropdown | `Enter/Space` | Abrir |
| Dropdown | `Arrow Down/Up` | Navegar opcoes |
| Dropdown | `Escape` | Fechar |
| Tabela sortable | `Enter` | Sort pela coluna focada |
| Toggle | `Space` | Alternar estado |
| Checkbox | `Space` | Alternar estado |
| Radio | `Arrow Down/Right` | Proximo |
| Radio | `Arrow Up/Left` | Anterior |
| Toast | `Escape` | Dispensar |

### 5.4 Screen Readers

```css
/* Classe para conteudo visivel apenas por screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* Quando focado (skip link precisa ser visivel ao focar) */
.sr-only:focus {
  position: static;
  width: auto;
  height: auto;
  padding: inherit;
  margin: inherit;
  overflow: visible;
  clip: auto;
  white-space: normal;
}
```

**ARIA patterns obrigatorios:**

- Modal: `role="dialog"`, `aria-modal="true"`, `aria-labelledby`
- Toast: `role="status"`, `aria-live="polite"` (info/success) ou `aria-live="assertive"` (error)
- Toggle: `role="switch"`, `aria-checked`
- Tabela sortable: `aria-sort="ascending|descending|none"` nos `<th>`
- Sidebar nav: `role="navigation"`, `aria-label="Menu principal"`
- Botao loading: `aria-busy="true"`, `aria-label="Carregando..."`
- Badge status: `aria-label` descritivo (ex: "Status: ativo")

### 5.5 Reduced Motion e High Contrast

```css
/* ================================================================
   PREFERENCIAS DE USUARIO
   ================================================================ */

/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Manter spinner visivel mas sem animacao */
  .btn--loading::after {
    animation: none;
    border-color: currentColor;
    opacity: 0.5;
  }

  /* Skeleton sem shimmer — usar pulse sutil */
  .skeleton::after {
    animation: none;
    display: none;
  }
  .skeleton {
    animation: none;
    opacity: 0.7;
  }

  /* Toast sem slide — aparecer direto */
  .toast {
    animation: none;
  }

  /* Modal sem scale — aparecer direto */
  .modal {
    animation: none;
  }
}

/* --- High Contrast --- */
@media (prefers-contrast: more) {
  :root {
    --border-default: var(--primitive-gray-500);
    --border-subtle: var(--primitive-gray-600);
    --text-muted: var(--primitive-gray-300);
    --button-disabled-opacity: 0.6;
    --input-disabled-opacity: 0.6;
  }

  .btn--primary {
    border: 2px solid var(--primitive-white);
  }

  .badge {
    border: 1px solid currentColor;
  }

  /* Focus ring mais forte */
  *:focus-visible {
    outline-width: 3px;
  }
}

/* --- Forced Colors (Windows High Contrast) --- */
@media (forced-colors: active) {
  .btn--primary {
    border: 2px solid ButtonText;
  }

  .toggle__track {
    border: 2px solid ButtonText;
  }

  .badge {
    border: 1px solid ButtonText;
  }

  /* Garantir que focus e visivel */
  *:focus-visible {
    outline: 2px solid Highlight;
  }
}
```

---

## 6. Sistema de Animacao

### 6.1 Principios

1. **Proposito:** Toda animacao deve comunicar algo (feedback, relacao espacial, estado). Animacao decorativa e eliminada.
2. **Velocidade:** Usuarios de SaaS sao impacientes. Manter tudo abaixo de 350ms para interacoes, 500ms para transicoes de pagina.
3. **Naturalidade:** Easings que imitam fisica real — desacelerar ao chegar, acelerar ao sair.
4. **Performance:** Animar apenas `transform` e `opacity` (nao `width`, `height`, `top`, `left`). Usar `will-change` apenas quando necessario e remover apos a animacao.

### 6.2 Easings por Contexto

| Contexto | Easing | Valor | Por que |
|---|---|---|---|
| Elemento aparecendo | ease-out | `cubic-bezier(0, 0, 0.2, 1)` | Chega rapido, desacelera suavemente |
| Elemento saindo | ease-in | `cubic-bezier(0.4, 0, 1, 1)` | Acelera e sai. Ninguem quer ver algo ir embora devagar |
| Elemento se movendo | ease-in-out | `cubic-bezier(0.4, 0, 0.2, 1)` | Material Design standard — natural |
| Micro-interacao (hover, toggle) | ease-in-out | `cubic-bezier(0.4, 0, 0.2, 1)` | Suave, imperceptivel como animacao |
| Bounce (sucesso, copy) | bounce | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Overshoots e volta — celebratorio |
| Spring (radio dot, checkbox) | spring | `cubic-bezier(0.175, 0.885, 0.32, 1.275)` | Leve overshoot mecanico |

### 6.3 Duracao por Contexto

| Nome | Valor | Uso |
|---|---|---|
| Instant | 75ms | Color changes, opacity micro-adjustments |
| Fast | 150ms | Hover states, tooltips, micro-feedback |
| Normal | 250ms | Modal enter, drawer, general transitions |
| Slow | 350ms | Complex animations, page content enter |
| Dramatic | 500ms | Rare — full page transitions, onboarding |

### 6.4 Stagger Patterns

```css
/* ================================================================
   STAGGER — Entrada sequencial de elementos
   ================================================================ */

/*
  Para listas e grids: cada item entra com delay incremental.
  Limite de 8 itens para evitar espera longa.
  Delay base: 50ms entre itens.
*/

.stagger-enter > * {
  opacity: 0;
  transform: translateY(4px);
  animation: staggerFadeIn var(--duration-slow) var(--ease-enter) forwards;
}

.stagger-enter > *:nth-child(1)  { animation-delay: 0ms; }
.stagger-enter > *:nth-child(2)  { animation-delay: 50ms; }
.stagger-enter > *:nth-child(3)  { animation-delay: 100ms; }
.stagger-enter > *:nth-child(4)  { animation-delay: 150ms; }
.stagger-enter > *:nth-child(5)  { animation-delay: 200ms; }
.stagger-enter > *:nth-child(6)  { animation-delay: 250ms; }
.stagger-enter > *:nth-child(7)  { animation-delay: 300ms; }
.stagger-enter > *:nth-child(8)  { animation-delay: 350ms; }
/* Itens apos o 8o entram todos juntos no 350ms */
.stagger-enter > *:nth-child(n+9) { animation-delay: 350ms; }

/* Variante rapida para cards/stats */
.stagger-enter--fast > * {
  animation-duration: var(--duration-normal);
}
.stagger-enter--fast > *:nth-child(1)  { animation-delay: 0ms; }
.stagger-enter--fast > *:nth-child(2)  { animation-delay: 30ms; }
.stagger-enter--fast > *:nth-child(3)  { animation-delay: 60ms; }
.stagger-enter--fast > *:nth-child(4)  { animation-delay: 90ms; }
```

### 6.5 Coreografia de Pagina

```
Dashboard load:
  1. Sidebar ja visivel (sem animacao — e persistente)
  2. Page title: fadeIn (0ms delay)
  3. Stats cards: stagger-enter--fast (4 cards, 0-90ms)
  4. Chart card: fadeIn + slideUp (150ms delay)
  5. Table: fadeIn (200ms delay), skeleton -> dados real (swap instant)

Navegacao entre paginas:
  1. Conteudo atual: fadeOut rapido (100ms)
  2. Novo conteudo: fadeIn + slideUp (0ms delay apos carregamento)
  3. Sidebar: indicador ativo anima suavemente (border-left transition)
```

---

## 7. Sistema de Iconografia

### 7.1 Biblioteca

**Lucide Icons** — Confirmado.

**Por que Lucide:**
- Fork mantido do Feather Icons com mais icones (1400+)
- Consistencia visual: 24x24 grid, 2px stroke, round caps
- Tree-shakeable (importar apenas os usados)
- ~15KB total para 30 icones tipicos de SaaS
- Sem dependencias

### 7.2 Tamanhos por Contexto

| Contexto | Tamanho | Stroke | Exemplo |
|---|---|---|---|
| Navegacao (sidebar) | 20px | 2px | LayoutDashboard, Link, BarChart |
| Botao com texto | 16px | 2px | Plus, Copy, Pencil |
| Botao icon-only | 18px | 2px | Trash, MoreHorizontal |
| Inline text | 14px | 1.5px | ExternalLink, Info |
| Decorativo (empty state) | 48-64px | 1.5px | LinkOff, Search |
| Stats card | 16px | 2px | TrendingUp, TrendingDown |

### 7.3 Heranca de Cor

```css
/* Icones herdam cor do parent via currentColor */
.icon {
  color: inherit;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

/* Tamanhos */
.icon--xs { width: 14px; height: 14px; stroke-width: 1.5; }
.icon--sm { width: 16px; height: 16px; }
.icon--md { width: 20px; height: 20px; }
.icon--lg { width: 24px; height: 24px; }
.icon--xl { width: 32px; height: 32px; stroke-width: 1.5; }
.icon--decorative { width: 48px; height: 48px; stroke-width: 1.5; }
```

### 7.4 Abordagem de Performance

**Inline SVG** (nao sprite sheet).

**Por que:**
- Permite `currentColor` para heranca de cor
- Tree-shaking funciona (so carrega icones usados)
- Sem request HTTP extra
- Melhor para animacao individual de paths se necessario
- Com vanilla JS: importar como string e inserir via `innerHTML`

### 7.5 Icones Customizados Necessarios

| Icone | Uso | Nota |
|---|---|---|
| Logo TOI | Sidebar, login, favicon | Wordmark + icon version |
| Empty Links | Empty state da lista | Link2Off do Lucide adaptado |
| Empty Chart | Empty state de analytics | BarChart3 + slash |
| Link expiration | Link expirado | Clock + slash |

---

## 8. Chart/Data Viz Style Guide

### 8.1 Configuracao Chart.js Completa

```javascript
/* ================================================================
   CHART.JS — Configuracao de tema TOI Shortcut
   ================================================================ */

const TOI_CHART_THEME = {
  // Paleta sequencial para multi-series
  colorSequence: [
    '#E4502A', // Coral (primary)
    '#3498DB', // Blue
    '#2ECC71', // Green
    '#F39C12', // Yellow
    '#9B59B6', // Purple
    '#1ABC9C', // Teal
    '#E74C3C', // Red
    '#F2896E', // Light coral
  ],

  // Configuracao global defaults
  defaults: {
    font: {
      family: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
      size: 11,
      weight: 400,
    },
    color: '#515B6A',
    responsive: true,
    maintainAspectRatio: false,
    animation: {
      duration: 500,
      easing: 'easeOutCubic',
    },

    plugins: {
      legend: {
        display: true,
        position: 'top',
        align: 'end',
        labels: {
          font: { family: "'Inter'", size: 12, weight: 500 },
          color: '#8A9BB0',
          usePointStyle: true,
          pointStyle: 'circle',
          padding: 16,
          boxWidth: 8,
          boxHeight: 8,
        },
      },

      tooltip: {
        backgroundColor: '#232830',
        borderColor: '#2A3040',
        borderWidth: 1,
        titleFont: { family: "'Inter'", size: 12, weight: 600 },
        titleColor: '#F0EDE8',
        bodyFont: { family: "'Inter'", size: 12, weight: 400 },
        bodyColor: '#8A9BB0',
        footerFont: { family: "'Inter'", size: 11, weight: 400 },
        footerColor: '#515B6A',
        padding: { top: 10, right: 14, bottom: 10, left: 14 },
        cornerRadius: 8,
        displayColors: true,
        boxWidth: 8,
        boxHeight: 8,
        boxPadding: 4,
        usePointStyle: true,
        caretSize: 0,
        // Sombra via CSS no canvas container
      },
    },

    scales: {
      x: {
        grid: {
          color: '#1E2330',
          lineWidth: 1,
          drawBorder: false,
          drawTicks: false,
        },
        ticks: {
          font: { family: "'Inter'", size: 11, weight: 400 },
          color: '#515B6A',
          padding: 8,
          maxRotation: 0,
        },
        border: {
          display: false,
        },
      },
      y: {
        grid: {
          color: '#1E2330',
          lineWidth: 1,
          drawBorder: false,
          drawTicks: false,
        },
        ticks: {
          font: { family: "'Inter'", size: 11, weight: 400 },
          color: '#515B6A',
          padding: 12,
          maxTicksLimit: 6,
        },
        border: {
          display: false,
        },
        beginAtZero: true,
      },
    },
  },

  // Template para line/area chart
  lineChartOptions: {
    elements: {
      line: {
        tension: 0.3,
        borderWidth: 2,
        borderColor: '#E4502A',
        fill: true,
        backgroundColor: (ctx) => {
          const gradient = ctx.chart.ctx.createLinearGradient(0, 0, 0, ctx.chart.height);
          gradient.addColorStop(0, 'rgba(228, 80, 42, 0.12)');
          gradient.addColorStop(1, 'rgba(228, 80, 42, 0)');
          return gradient;
        },
      },
      point: {
        radius: 0,
        hoverRadius: 4,
        hoverBorderWidth: 2,
        hoverBorderColor: '#161920',
        hoverBackgroundColor: '#E4502A',
        hitRadius: 20,
      },
    },
    interaction: {
      mode: 'index',
      intersect: false,
    },
  },

  // Template para bar chart
  barChartOptions: {
    elements: {
      bar: {
        borderRadius: 4,
        borderSkipped: false,
        backgroundColor: '#E4502A',
        hoverBackgroundColor: '#CC3F1F',
        maxBarThickness: 40,
      },
    },
  },

  // Template para doughnut/pie
  doughnutOptions: {
    cutout: '70%',
    elements: {
      arc: {
        borderWidth: 2,
        borderColor: '#161920',
        hoverBorderColor: '#161920',
        hoverOffset: 4,
      },
    },
    plugins: {
      legend: {
        position: 'right',
      },
    },
  },
};
```

### 8.2 Responsividade de Graficos

```css
/* Chart containers responsivos */
.chart-container {
  position: relative;
  width: 100%;
  min-height: 200px;
}

@media (max-width: 767px) {
  .chart-container {
    min-height: 160px;
  }

  /* Legenda abaixo no mobile */
  .chart-container--mobile-legend-bottom {
    /* Via Chart.js options: legend.position = 'bottom' */
  }
}
```

### 8.3 Empty Chart State

```css
.chart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  text-align: center;
}
.chart-empty__icon {
  width: 48px;
  height: 48px;
  color: var(--text-muted);
  opacity: 0.3;
  margin-bottom: var(--space-4);
}
.chart-empty__message {
  font-size: var(--text-body);
  color: var(--text-muted);
}
```

---

## 9. Error e Empty States

### 9.1 Pagina 404 — Link Nao Encontrado

**Contexto:** Pagina publica quando alguem acessa um slug que nao existe.

```
Layout: Centralizado vertical e horizontal, full viewport
Background: --bg-base
Logo: TOI pequeno (24px) no topo esquerdo, padding 24px

Conteudo:
  Icone: LinkOff (48px, --text-muted, opacity 0.4)
  Titulo: "Link nao encontrado" — H2, --text-primary
  Descricao: "O link que voce esta procurando nao existe ou foi removido."
             — Body, --text-muted, max-width 360px
  CTA: "Voltar ao inicio" — btn--secondary, margin-top 32px

Detalhe visual:
  Codigo "404" em fonte mono, 120px, --primitive-gray-900, atras do conteudo
  como marca d'agua decorativa (position absolute, z-index -1)
```

### 9.2 Pagina 410 — Link Desativado

```
Mesmo layout do 404, com diferencas:
  Icone: LinkOff com badge de "pause" (ou icone Ban)
  Titulo: "Link desativado"
  Descricao: "Este link foi desativado pelo proprietario."
  Sem CTA de acao (usuario nao tem o que fazer)

Detalhe visual:
  Badge sutil "INATIVO" em vermelho acima do titulo
```

### 9.3 Dashboard Vazio — Nenhum Link

```
Layout: Dentro da area de conteudo do dashboard (com sidebar)

Conteudo:
  Icone: Link2 (64px, --text-muted, opacity 0.3)
  Titulo: "Nenhum link criado" — H2
  Descricao: "Crie seu primeiro link encurtado para comecar a rastrear cliques."
  CTA: "Criar primeiro link" — btn--primary com icone Plus

Detalhe visual:
  Background sutil com pattern de grid pontilhado (mesma do login)
  Cards de stats mostram "0" com skeleton-like placeholder
```

### 9.4 Busca Sem Resultados

```
Layout: Dentro da tabela, substituindo as rows

Conteudo:
  Icone: Search (48px, --text-muted, opacity 0.3)
  Titulo: "Nenhum resultado" — H3
  Descricao: "Nenhum link corresponde a "{termo}". Tente outra busca."
  CTA: "Limpar busca" — btn--ghost

Animacao: fadeIn simples ao trocar de estado
```

### 9.5 Erro de Rede

```
Layout: Overlay ou inline, dependendo do contexto

Conteudo:
  Icone: WifiOff (48px, --color-warning, opacity 0.6)
  Titulo: "Sem conexao"
  Descricao: "Verifique sua conexao com a internet e tente novamente."
  CTA: "Tentar novamente" — btn--secondary (com icone RefreshCw)

Comportamento: Auto-retry a cada 10s com countdown visual
```

### 9.6 Erro do Servidor (500)

```
Layout: Full page ou inline

Conteudo:
  Icone: ServerCrash (48px, --color-error, opacity 0.5)
  Titulo: "Algo deu errado"
  Descricao: "Nosso servidor encontrou um problema. Tente novamente em alguns instantes."
  CTA: "Recarregar pagina" — btn--primary

Detalhe: Incluir request ID em --text-muted para suporte
```

### 9.7 Sessao Expirada

```
Layout: Modal overlay centralizado (nao descartavel)

Conteudo:
  Icone: LogOut (32px, --color-warning)
  Titulo: "Sessao expirada"
  Descricao: "Sua sessao expirou por inatividade. Faca login novamente."
  CTA unico: "Fazer login" — btn--primary, width 100%

Overlay: --bg-overlay-heavy (80% opacity, sem click-to-dismiss)
```

---

## 10. Patterns de UI para Producao

### 10.1 Optimistic Updates (Toggle de Status)

```
Fluxo:
  1. Usuario clica toggle ativo/inativo
  2. UI atualiza IMEDIATAMENTE (toggle muda, badge muda)
  3. Request vai para API em background
  4. Se sucesso: nada muda (ja esta correto)
  5. Se erro:
     a. Reverte toggle e badge ao estado anterior
     b. Shake animation no toggle (150ms)
     c. Toast de erro: "Nao foi possivel alterar o status. Tente novamente."

CSS para revert + shake:
```

```css
.toggle--reverting .toggle__track {
  animation: shake 300ms var(--ease-move);
}
```

### 10.2 Debounced Search

```
Comportamento:
  1. Usuario digita no campo de busca
  2. Debounce de 300ms (nao envia request a cada tecla)
  3. Apos 300ms sem digitar: request
  4. Durante request: spinner de 14px no lugar do icone de lupa
  5. Ao receber resultados: tabela atualiza com fadeIn sutil
  6. Se input ficar vazio: limpar filtro e restaurar lista completa

Nao usar: Loading overlay na tabela inteira (invasivo demais)
Usar: Spinner inline no search input + skeleton rows
```

### 10.3 Paginacao vs Infinite Scroll

**Decisao: Paginacao.**

**Por que:**
- Links tem contagem finita e controlavel (nao e feed social)
- Paginacao permite URLs compartilhaveis (`/links?page=3`)
- Paginacao permite "ir direto para pagina X"
- Infinite scroll quebra o footer e dificulta alcanccar acoes de bulk
- Paginacao e mais previsivel para analytics (quantos links tem?)

### 10.4 Skeleton Loading Choreography

```
Regra: Skeleton deve espelhar EXATAMENTE o layout do conteudo real.
Layout shift = 0px. O skeleton ocupa o mesmo espaco que o conteudo.

Ordem de carregamento:
  1. Shell (sidebar + page header): instantaneo (cached/SSR)
  2. Stats cards: 4 skeleton cards simultaneos -> dados reais (swap sem animacao)
  3. Chart: skeleton retangular -> chart renderizado (fadeIn 200ms)
  4. Tabela: 5 skeleton rows -> rows reais (swap instant, sem animacao)

Timing: Skeleton visivel por NO MINIMO 200ms
  Por que: Se o request volta em 50ms, o skeleton aparece e some
  tao rapido que parece um glitch. 200ms minimo cria percepcao
  de que algo carregou.
```

### 10.5 Form Validation Patterns

```
Estrategia hibrida:
  - Campos obrigatorios: validar on-blur (quando usuario sai do campo)
  - Formato (email, URL): validar on-blur
  - Slug (unico): validar on-blur com request async
  - Submit: validar todos de uma vez, scroll para primeiro erro

Feedback visual:
  - Erro: borda vermelha + mensagem abaixo do campo (slideDown 150ms)
  - Sucesso (apos correcao): borda verde por 1.5s, depois volta ao normal
  - Nunca mostrar sucesso antes de erro (nao "pre-validar" campos vazios)

Mensagens:
  - Claras e acionaveis: "O slug ja esta em uso. Tente outro." (nao "Erro de validacao")
  - Posicao: diretamente abaixo do campo, com icone AlertCircle de 14px
```

### 10.6 Confirmation Dialogs (Delete Link)

```
Trigger: Clicar botao de delete (icone Trash)

Modal:
  Titulo: "Excluir link?"
  Descricao: "O link toi.shinp.ai/{slug} sera permanentemente excluido.
              Esta acao nao pode ser desfeita."

  Slug em destaque: font-mono, --color-action-primary, background --color-action-primary-subtle,
                    padding 2px 6px, border-radius 4px

  Footer:
    "Cancelar" — btn--secondary (auto-focus por seguranca)
    "Excluir link" — btn--danger

  Ao confirmar:
    1. Botao "Excluir" entra em loading
    2. Request para API
    3. Sucesso: modal fecha, row da tabela faz fadeOut + height collapse (300ms)
    4. Toast: "Link excluido com sucesso"
    5. Erro: toast de erro, modal permanece aberta
```

### 10.7 Bulk Actions UI

```
Trigger: Selecionar 1+ rows via checkbox

Barra de bulk actions:
  Aparece com slideDown no topo da tabela
  Background: --bg-elevated
  Border: 1px solid --border-default
  Border-radius: --radius-md
  Padding: 8px 16px
  Display: flex, align-items center, justify-content space-between

  Lado esquerdo:
    Checkbox "select all" + texto "{n} links selecionados"

  Lado direito:
    Botoes: "Ativar" (btn--ghost), "Desativar" (btn--ghost), "Excluir" (btn--danger btn--sm)
    Separador: 1px solid --border-default, height 20px

  Animacao:
    Entrada: slideDown + fadeIn (200ms ease-out)
    Saida: slideUp + fadeOut (150ms ease-in)
```

### 10.8 Keyboard Shortcuts

```
Atalhos globais:
  / → Focar campo de busca
  n → Abrir modal "Novo Link"
  ? → Abrir overlay de atalhos
  Esc → Fechar modal/drawer/overlay

Overlay de atalhos (trigger: pressionar "?"):
  Modal centralizado com grid de atalhos
  Cada atalho: tecla em <kbd> style + descricao

<kbd> style:
  font-family: var(--font-mono)
  font-size: var(--text-small)
  background: var(--bg-base)
  border: 1px solid var(--border-default)
  border-bottom-width: 2px
  border-radius: var(--radius-xs)
  padding: 2px 6px
  color: var(--text-secondary)
  min-width: 24px
  text-align: center
  display: inline-block
```

```css
/* KBD style */
kbd {
  font-family: var(--font-mono);
  font-size: var(--text-small);
  background: var(--bg-base);
  border: 1px solid var(--border-default);
  border-bottom-width: 2px;
  border-radius: var(--radius-xs);
  padding: 2px 6px;
  color: var(--text-secondary);
  min-width: 24px;
  text-align: center;
  display: inline-block;
  line-height: 1.4;
}
```

---

## 11. Estrutura de Documentacao do Design System

### 11.1 Estrutura de Arquivos CSS

```
styles/
├── tokens/
│   ├── _primitives.css      /* Camada 1: valores brutos */
│   ├── _semantics.css       /* Camada 2: intencao */
│   └── _components.css      /* Camada 3: por componente */
├── base/
│   ├── _reset.css           /* Box-sizing, margin reset */
│   ├── _globals.css         /* Selection, scrollbar, body */
│   ├── _typography.css      /* H1-H4, body, small, mono */
│   └── _accessibility.css   /* sr-only, skip-link, focus, reduced-motion */
├── components/
│   ├── _button.css
│   ├── _input.css
│   ├── _select.css
│   ├── _checkbox.css
│   ├── _radio.css
│   ├── _toggle.css
│   ├── _card.css
│   ├── _badge.css
│   ├── _table.css
│   ├── _pagination.css
│   ├── _modal.css
│   ├── _drawer.css
│   ├── _toast.css
│   ├── _sidebar.css
│   ├── _skeleton.css
│   ├── _empty-state.css
│   ├── _error-state.css
│   ├── _progress.css
│   ├── _copy-btn.css
│   ├── _url-display.css
│   └── _date-trigger.css
├── layouts/
│   ├── _shell.css            /* Sidebar + content area */
│   ├── _login.css            /* Split screen login */
│   └── _public-pages.css     /* 404, 410, etc */
├── utilities/
│   ├── _responsive.css       /* Media queries e helpers */
│   ├── _animations.css       /* Keyframes e stagger */
│   └── _helpers.css          /* hide-mobile, etc */
├── vendors/
│   └── _chart-theme.css      /* Chart.js overrides */
└── main.css                  /* Import de tudo, na ordem correta */
```

**`main.css` — Ordem de importacao:**

```css
/* Tokens (sem output CSS, apenas variaveis) */
@import 'tokens/_primitives.css';
@import 'tokens/_semantics.css';
@import 'tokens/_components.css';

/* Base (low-specificity resets) */
@import 'base/_reset.css';
@import 'base/_globals.css';
@import 'base/_typography.css';
@import 'base/_accessibility.css';

/* Layouts */
@import 'layouts/_shell.css';
@import 'layouts/_login.css';
@import 'layouts/_public-pages.css';

/* Components (cada um independente) */
@import 'components/_button.css';
@import 'components/_input.css';
@import 'components/_select.css';
@import 'components/_checkbox.css';
@import 'components/_radio.css';
@import 'components/_toggle.css';
@import 'components/_card.css';
@import 'components/_badge.css';
@import 'components/_table.css';
@import 'components/_pagination.css';
@import 'components/_modal.css';
@import 'components/_drawer.css';
@import 'components/_toast.css';
@import 'components/_sidebar.css';
@import 'components/_skeleton.css';
@import 'components/_empty-state.css';
@import 'components/_error-state.css';
@import 'components/_progress.css';
@import 'components/_copy-btn.css';
@import 'components/_url-display.css';
@import 'components/_date-trigger.css';

/* Utilities (high-specificity overrides) */
@import 'utilities/_animations.css';
@import 'utilities/_responsive.css';
@import 'utilities/_helpers.css';

/* Vendors */
@import 'vendors/_chart-theme.css';
```

### 11.2 Convencao de Nomenclatura

**BEM Modificado** — sem duplo underscore nas profundidades.

**Por que BEM e nao Utility-first (Tailwind):**
- Este e um produto vanilla JS sem framework reativo
- BEM cria componentes autocontidos e legiveisem
- Sem build step necessario para purge de classes nao usadas
- CSS nativo e mais debuggavel no browser

**Convencao:**

```
.bloco             → Componente raiz         (.card, .btn, .input)
.bloco--modificador → Variante              (.card--stat, .btn--primary)
.bloco__elemento    → Filho direto          (.card__title, .btn__icon)
.bloco__elemento--mod → Filho com variante  (.card__trend--up)
```

**Regras:**
- Maximo 1 nivel de `__` (nao `.card__header__title`, use `.card__title`)
- Modificadores de estado preferem data-attributes ou ARIA quando possivel (`[aria-selected="true"]` em vez de `.card--selected` quando semanticamente correto)
- Classes utilitarias prefixadas com `u-` (ex: `u-sr-only`, `u-hide-mobile`)

### 11.3 Como Estender o Sistema

**Adicionando um novo componente:**

1. Criar `_novo-componente.css` em `components/`
2. Definir component tokens na camada 3 (`_components.css`)
3. Referenciar apenas semantic tokens (camada 2) nos component tokens
4. Adicionar import em `main.css` na secao correta
5. Definir TODOS os estados: default, hover, focus, active, disabled, loading, error
6. Definir comportamento responsivo em `_responsive.css`
7. Definir `prefers-reduced-motion` se tiver animacoes

**Overriding tokens por contexto:**

```css
/* Exemplo: card com tema diferente dentro de uma secao */
.promo-section {
  --card-bg: var(--bg-elevated);
  --card-border: var(--border-hover);
  --card-padding: var(--space-8);
}
/* Todos os .card dentro de .promo-section herdam automaticamente */
```

### 11.4 Composicao de Componentes

```html
<!-- Exemplo: Campo de input completo -->
<div class="field field--error">
  <label class="field__label field__label--required">Slug</label>
  <div class="input-group--url">
    <span class="input-group__prefix">toi.shinp.ai/</span>
    <input class="input input--error" type="text" value="meu-link" />
  </div>
  <div class="field__helper">
    <span class="field__error">
      <svg class="icon icon--xs"><!-- AlertCircle --></svg>
      Este slug ja esta em uso
    </span>
    <span class="field__counter">7 / 50</span>
  </div>
</div>

<!-- Exemplo: Tabela com skeleton loading -->
<div class="table-container">
  <table class="table">
    <thead class="table__head">
      <tr>
        <th class="table__checkbox"><input type="checkbox" /></th>
        <th aria-sort="ascending">Slug <span class="table__sort-icon">↑</span></th>
        <th>Destino</th>
        <th aria-sort="none">Cliques</th>
        <th>Status</th>
        <th class="table__col--hide-mobile">Criado</th>
        <th>Acoes</th>
      </tr>
    </thead>
    <tbody class="table__body">
      <!-- Skeleton row -->
      <tr class="table__skeleton">
        <td><div class="skeleton skeleton--badge" style="width:16px;height:16px"></div></td>
        <td><div class="skeleton skeleton--text" style="width:120px"></div></td>
        <td><div class="skeleton skeleton--text-medium"></div></td>
        <td><div class="skeleton skeleton--text-short" style="width:40px"></div></td>
        <td><div class="skeleton skeleton--badge"></div></td>
        <td><div class="skeleton skeleton--text-short"></div></td>
        <td><div class="skeleton skeleton--text-short" style="width:80px"></div></td>
      </tr>
    </tbody>
  </table>
</div>
```

---

## Resumo da Evolucao

| Area | v1 (VISUAL_DIRECTION) | v2 (Este documento) |
|---|---|---|
| Tokens | 1 camada, ~70 tokens | 3 camadas, ~200+ tokens |
| Componentes | 7 parciais | 15+ completos com todos os estados |
| Responsividade | 1 menncao vaga | 4 breakpoints com regras especificas |
| Acessibilidade | Zero | WCAG AA verificado, focus, ARIA, reduced motion, high contrast |
| Animacoes | 6 keyframes | 14 keyframes + stagger + coreografia |
| Estados | Basicos | Loading, error, empty, skeleton, disabled, readonly |
| Forms | Input basico | Input, select, checkbox, radio, toggle, date trigger |
| Error states | Zero | 7 patterns completos |
| Charts | Menncao | Config completa Chart.js |
| Patterns | Zero | 8 patterns de producao |
| Estrutura CSS | Bloco unico | 25+ arquivos organizados |
| Nomenclatura | Nenhuma | BEM modificado com regras |

---

*Este documento evolui VISUAL_DIRECTION.md v1.0 para production-grade. Ambos documentos devem ser lidos juntos. A v1 define a visao, a v2 define a execucao.*
