# PharmData Design System - Análise Arquitetural

> Análise crítica e recomendações para resolver o ciclo de refatoração dark mode/Tailwind
>
> Data: Dezembro 2024

---

## Sumário Executivo

| Aspecto | Situação |
|---------|----------|
| **Problema Central** | Três camadas de abstração conflitantes + ausência de enforcement |
| **Arquivos Afetados** | ~50+ arquivos com cores hardcoded |
| **Decisão Tailwind** | Manter, mas substituir cores built-in por variáveis |
| **Solução** | Tokens semânticos + config restritivo + validação automatizada |
| **Dark Mode Automático** | Alcançável se usar APENAS variáveis semânticas |

---

## 1. Diagnóstico: Causa Raiz

### O Ciclo de Refatoração

```
CSS Puro → Tailwind → Overrides → Centralização → CSS Puro (repete)
```

Este ciclo ocorre porque o sistema permite **três formas de definir cores**, cada uma com comportamento diferente em dark mode:

```
┌─────────────────────────────────────────────────────────────┐
│  CAMADA 3: Inline Styles (background: white)                │  ← Sem abstração
├─────────────────────────────────────────────────────────────┤
│  CAMADA 2: Tailwind Classes (bg-white, bg-cloud)            │  ← Compilação estática
├─────────────────────────────────────────────────────────────┤
│  CAMADA 1: CSS Variables (var(--cloud))                     │  ← Runtime dinâmico
└─────────────────────────────────────────────────────────────┘
```

### O Conflito Técnico

O Tailwind CDN, ao processar classes como `bg-white`, gera CSS estático:

```css
/* Gerado pelo Tailwind - HARDCODED */
.bg-white { background-color: #fff; }
```

Mesmo com a configuração correta de variáveis no `tailwind-config.js`:

```javascript
'cloud': 'var(--cloud)',  // Correto, funciona
```

O problema é que **`bg-white` não usa essa configuração** — usa o valor built-in do Tailwind.

### Anti-Patterns Identificados

#### Anti-Pattern 1: Classes Tailwind Built-in

**119+ ocorrências** de `bg-white` encontradas:

```html
<!-- Tailwind gera #fff, não var(--cloud) -->
<div class="bg-white">
```

Arquivos mais afetados:
- `showcase/components/drops-showcase.html` (30+ ocorrências)
- `showcase/components/tables.html` (20+ ocorrências)
- `showcase/examples/*.html` (40+ ocorrências)

#### Anti-Pattern 2: Inline Styles Hardcoded

**52+ ocorrências** de `background: white`:

```html
<!-- showcase/examples-hub.html -->
<div style="background: white; padding: 1.5rem;">
```

Arquivos afetados:
- `tokens/forms.css` (6 ocorrências)
- `showcase/index.html` (3 ocorrências)
- `showcase/examples-hub.html` (3 ocorrências)
- `showcase/pages/login.html` (2 ocorrências)

#### Anti-Pattern 3: Duplicação de Variáveis Dark Mode

Mesma variável definida em múltiplos arquivos com valores diferentes:

| Arquivo | `--teal-intense` (dark) |
|---------|------------------------|
| `colors.css:222` | `#3dc9bd` |
| `dark-mode-base.css:51` | `#58d5c9` |

Isso causa inconsistência visual dependendo da ordem de carregamento CSS.

---

## 2. Arquitetura Proposta

### Princípio: Uma Variável, Um Lugar

#### Estrutura Atual (Problemática)

```
tokens/
├── colors.css           # Define variáveis + dark mode
├── dark-mode.css        # Redefine dark mode (duplicado!)
showcase/shared/
├── dark-mode-base.css   # Mais overrides (triplica!)
```

#### Estrutura Proposta

```
tokens/
├── colors.css           # ÚNICA fonte de verdade
│   ├── :root { }        # Light mode
│   └── html.dark-mode   # Dark mode
│
showcase/shared/
├── tailwind-config.js   # Mapeia para var(), sem cores próprias
├── utilities.css        # Classes utilitárias do DS
│
[REMOVIDO] dark-mode-base.css
[REMOVIDO] dark-mode.css (merge em colors.css)
```

### Nomenclatura Semântica

Renomear variáveis para indicar **propósito**, não **aparência**:

| Atual (Aparência) | Proposto (Semântico) | Uso |
|-------------------|---------------------|-----|
| `--cloud` | `--surface-primary` | Background principal |
| `--arctic-mist` | `--surface-elevated` | Cards, modais |
| `--soft-arctic` | `--surface-muted` | Áreas secundárias |
| `--graphite-depth` | `--text-primary` | Texto principal |
| `--soft-steel` | `--text-secondary` | Texto secundário |
| `--teal-intense` | `--accent-primary` | Links, CTAs |
| `--mint-signal` | `--accent-subtle` | Highlights |

### Nova Estrutura do colors.css

```css
/* ============================================
   PHARMDATA DESIGN SYSTEM - COLOR TOKENS
   Single Source of Truth
   ============================================ */

/* ==========  PRIMITIVES  ==========
   Valores base - NUNCA usar diretamente em componentes
   ================================================== */
:root {
    /* Light primitives */
    --primitive-white: #F5F8FA;
    --primitive-gray-50: #E9ECEF;
    --primitive-gray-100: #E5E8EB;
    --primitive-gray-800: #1F2937;
    --primitive-gray-600: #374151;

    /* Dark primitives */
    --primitive-dark-900: #0d1117;
    --primitive-dark-800: #161b22;
    --primitive-dark-700: #21262d;
    --primitive-dark-text: #f0f6fc;

    /* Brand */
    --primitive-emerald: #0B2D2A;
    --primitive-teal: #2AA198;
    --primitive-mint: #B7E4D5;
}

/* ==========  SEMANTIC TOKENS  ==========
   Usar ESTES em componentes
   ======================================== */
:root {
    /* Surfaces */
    --surface-primary: var(--primitive-white);
    --surface-elevated: #ffffff;
    --surface-muted: var(--primitive-gray-50);

    /* Text */
    --text-primary: var(--primitive-gray-800);
    --text-secondary: var(--primitive-gray-600);
    --text-inverse: #ffffff;

    /* Borders */
    --border-default: var(--primitive-gray-100);
    --border-subtle: rgba(183, 228, 213, 0.15);

    /* Accent */
    --accent-primary: var(--primitive-teal);
    --accent-hover: #238b80;
    --accent-subtle: var(--primitive-mint);
    --accent-ring: rgba(42, 161, 152, 0.2);

    /* Brand */
    --brand-primary: var(--primitive-emerald);
    --brand-accent: var(--primitive-mint);
}

/* ==========  DARK MODE  ==========
   Redefine tokens semânticos
   ================================= */
html.dark-mode,
:root.dark-mode,
[data-theme="dark"] {
    /* Surfaces */
    --surface-primary: var(--primitive-dark-900);
    --surface-elevated: var(--primitive-dark-800);
    --surface-muted: var(--primitive-dark-700);

    /* Text */
    --text-primary: var(--primitive-dark-text);
    --text-secondary: #b1bac4;

    /* Borders */
    --border-default: #30363d;
    --border-subtle: rgba(183, 228, 213, 0.1);

    /* Accent - mais vibrante em dark */
    --accent-primary: #58d5c9;
    --accent-hover: #7ee2d0;
    --accent-ring: rgba(88, 213, 201, 0.25);

    /* Brand invertido */
    --brand-primary: #7ee2d0;
    --brand-accent: #1a3d3a;

    /* Browser hint */
    color-scheme: dark;
}

/* ==========  ALIASES (Retrocompatibilidade)  ==========
   Manter temporariamente durante migração
   ====================================================== */
:root {
    --cloud: var(--surface-primary);
    --arctic-mist: var(--surface-muted);
    --soft-arctic: var(--surface-muted);
    --graphite-depth: var(--text-primary);
    --soft-steel: var(--text-secondary);
    --emerald-abyss: var(--brand-primary);
    --mint-signal: var(--brand-accent);
    --teal-intense: var(--accent-primary);
}
```

---

## 3. Decisão Tailwind

### Recomendação: MANTER com Restrições

| Opção | Prós | Contras |
|-------|------|---------|
| **Manter Tailwind CDN** | Produtividade, familiaridade | Requer config restritivo |
| Remover Tailwind | Controle total | Perda de velocidade, retrabalho |
| Migrar para Tailwind Build | Melhor tree-shaking | Adiciona complexidade de build |

**Decisão: Manter Tailwind CDN** com configuração que **remove** cores built-in.

### Configuração Restritiva

```javascript
// tailwind-config.js - VERSÃO RESTRITIVA
tailwind.config = {
    darkMode: 'class',
    theme: {
        // SUBSTITUIR cores (não extend!)
        // Isso REMOVE bg-white, bg-gray-*, etc.
        colors: {
            transparent: 'transparent',
            current: 'currentColor',

            // === SURFACES ===
            'surface': 'var(--surface-primary)',
            'surface-elevated': 'var(--surface-elevated)',
            'surface-muted': 'var(--surface-muted)',

            // === TEXT ===
            'text': 'var(--text-primary)',
            'text-secondary': 'var(--text-secondary)',
            'text-inverse': 'var(--text-inverse)',

            // === BORDERS ===
            'border': 'var(--border-default)',
            'border-subtle': 'var(--border-subtle)',

            // === ACCENT ===
            'accent': 'var(--accent-primary)',
            'accent-hover': 'var(--accent-hover)',
            'accent-subtle': 'var(--accent-subtle)',

            // === BRAND ===
            'brand': 'var(--brand-primary)',
            'brand-accent': 'var(--brand-accent)',

            // === STATUS ===
            'success': 'var(--success)',
            'warning': 'var(--warning)',
            'error': 'var(--error)',
            'info': 'var(--info)',
        },

        extend: {
            boxShadow: {
                'xs': 'var(--shadow-xs)',
                'sm': 'var(--shadow-sm)',
                'md': 'var(--shadow-md)',
                'lg': 'var(--shadow-lg)',
                'xl': 'var(--shadow-xl)',
            },
            fontFamily: {
                'sans': ['Inter', 'system-ui', 'sans-serif'],
                'serif': ['Lora', 'Georgia', 'serif'],
                'mono': ['JetBrains Mono', 'Consolas', 'monospace'],
            },
            borderRadius: {
                'ds': '12px',
            }
        }
    }
};
```

Com esta configuração, `bg-white` **não existe** — forçando uso de `bg-surface`.

---

## 4. Padrões de Código

### Padrão Correto

```html
<!-- Card com dark mode automático -->
<div class="bg-surface-elevated border border-subtle rounded-ds p-6 shadow-md">
    <h3 class="text-text font-semibold">Título</h3>
    <p class="text-text-secondary">Descrição do card</p>
    <button class="bg-accent text-text-inverse px-4 py-2 rounded-lg">
        Ação
    </button>
</div>
```

```css
/* CSS customizado usando variáveis */
.custom-component {
    background: var(--surface-elevated);
    border: 1px solid var(--border-default);
    color: var(--text-primary);
    /* Dark mode funciona automaticamente! */
}

.custom-component:hover {
    border-color: var(--accent-primary);
}
```

### Padrões Proibidos

```html
<!-- PROIBIDO: Inline style com valor hardcoded -->
<div style="background: white;">

<!-- PROIBIDO: Classes Tailwind built-in -->
<div class="bg-white text-gray-900 border-gray-200">

<!-- PROIBIDO: Hex colors em atributos -->
<div style="background: #ffffff; color: #1f2937;">
```

```css
/* PROIBIDO: Hex direto em CSS */
.component {
    background: #ffffff;
    color: #333;
}

/* PROIBIDO: Overrides com !important para dark mode */
html.dark-mode .component {
    background: #161b22 !important;
}
```

---

## 5. Checklist de Validação

### Checklist por Componente

```markdown
## Dark Mode Validation Checklist

### 1. Zero Cores Hardcoded
- [ ] Nenhum `background: white` ou `background: #fff`
- [ ] Nenhum `color: #xxx` com hex direto
- [ ] Nenhum `border-color` hardcoded
- [ ] Nenhum `box-shadow` com cores inline

### 2. Zero Classes Tailwind Built-in
- [ ] Nenhum `bg-white`, `bg-gray-*`, `bg-slate-*`
- [ ] Nenhum `text-gray-*`, `text-slate-*`
- [ ] Nenhum `border-gray-*`

### 3. Apenas Tokens Semânticos
- [ ] Backgrounds usam `--surface-*` ou `bg-surface-*`
- [ ] Textos usam `--text-*` ou `text-text-*`
- [ ] Borders usam `--border-*` ou `border-*`
- [ ] Accents usam `--accent-*` ou `accent-*`

### 4. Teste Visual
- [ ] Testado em Light Mode
- [ ] Testado em Dark Mode
- [ ] Contraste mínimo 4.5:1 (WCAG AA) em ambos os modos
- [ ] Nenhum elemento "desaparece" em dark mode
```

### Script de Validação Automatizada

```bash
#!/bin/bash
# scripts/validate-colors.sh

echo "🔍 Validating color usage..."

ERRORS=0

# Check for hardcoded white backgrounds
echo "Checking for hardcoded backgrounds..."
HARDCODED_BG=$(grep -rn "background:\s*white\|background:\s*#fff\|background-color:\s*white\|background-color:\s*#fff" \
    --include="*.html" --include="*.css" \
    --exclude-dir=node_modules \
    | grep -v "dark-mode" \
    | grep -v "\.md:")

if [ -n "$HARDCODED_BG" ]; then
    echo "❌ Found hardcoded backgrounds:"
    echo "$HARDCODED_BG"
    ERRORS=$((ERRORS + 1))
fi

# Check for Tailwind built-in color classes
echo "Checking for Tailwind built-in colors..."
TAILWIND_BUILTIN=$(grep -rn "bg-white\|bg-gray-\|bg-slate-\|text-gray-\|text-slate-\|border-gray-" \
    --include="*.html" \
    --exclude-dir=node_modules \
    | grep -v "dark-mode")

if [ -n "$TAILWIND_BUILTIN" ]; then
    echo "❌ Found Tailwind built-in color classes:"
    echo "$TAILWIND_BUILTIN"
    ERRORS=$((ERRORS + 1))
fi

# Check for inline hex colors
echo "Checking for inline hex colors..."
INLINE_HEX=$(grep -rn 'style="[^"]*#[0-9a-fA-F]\{3,6\}' \
    --include="*.html" \
    --exclude-dir=node_modules)

if [ -n "$INLINE_HEX" ]; then
    echo "⚠️  Found inline hex colors (review manually):"
    echo "$INLINE_HEX"
fi

if [ $ERRORS -eq 0 ]; then
    echo "✅ All color validation checks passed!"
    exit 0
else
    echo "❌ Found $ERRORS validation error(s)"
    exit 1
fi
```

### Git Pre-commit Hook

```bash
#!/bin/bash
# .git/hooks/pre-commit

# Run color validation on staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(html|css)$')

if [ -n "$STAGED_FILES" ]; then
    echo "🎨 Validating color usage in staged files..."

    for file in $STAGED_FILES; do
        # Check for bg-white
        if grep -q "bg-white" "$file"; then
            echo "❌ $file contains 'bg-white' - use 'bg-surface' instead"
            exit 1
        fi

        # Check for background: white
        if grep -q "background:\s*white\|background:\s*#fff" "$file"; then
            echo "❌ $file contains hardcoded background - use var(--surface-*)"
            exit 1
        fi
    done

    echo "✅ Color validation passed"
fi
```

---

## 6. Roadmap de Migração

### Fase 1: Consolidação (Prioridade Crítica)

**Objetivo:** Eliminar duplicação de variáveis

| Tarefa | Arquivos | Estimativa |
|--------|----------|------------|
| Merge dark mode em colors.css | 3 arquivos | - |
| Criar tokens semânticos | colors.css | - |
| Adicionar aliases retrocompat | colors.css | - |
| Remover dark-mode-base.css | 1 arquivo | - |
| Remover dark-mode.css (tokens/) | 1 arquivo | - |

**Resultado:** Uma única fonte de verdade para todas as cores.

### Fase 2: Tailwind Restritivo

**Objetivo:** Impossibilitar uso de cores built-in

| Tarefa | Arquivos |
|--------|----------|
| Atualizar tailwind-config.js | 1 arquivo |
| Criar utilities.css | 1 arquivo (novo) |
| Documentar novas classes | README |

**Resultado:** `bg-white` deixa de existir, `bg-surface` é obrigatório.

### Fase 3: Migração de Componentes

**Objetivo:** Corrigir todos os arquivos existentes

#### Prioridade Alta (Mais Usados)
- `showcase/examples/*.html` (4 arquivos)
- `showcase/components/*.html` (12 arquivos)

#### Prioridade Média
- `showcase/pages/*.html` (5 arquivos)
- `tokens/*.css` (8 arquivos)

#### Prioridade Baixa
- Arquivos de documentação `.md`
- Comentários de exemplo em CSS

### Fase 4: Enforcement Contínuo

**Objetivo:** Prevenir regressões

| Tarefa | Tipo |
|--------|------|
| Criar validate-colors.sh | Script |
| Configurar pre-commit hook | Git |
| Adicionar CI check | GitHub Actions (opcional) |
| Documentar padrões | CONTRIBUTING.md |

---

## 7. Métricas de Sucesso

### Antes da Migração

| Métrica | Valor Atual |
|---------|-------------|
| Ocorrências `bg-white` | 119+ |
| Ocorrências `background: white` | 52+ |
| Arquivos com dark-mode vars | 3 (duplicados) |
| Overrides `!important` | ~50+ |

### Depois da Migração

| Métrica | Valor Esperado |
|---------|----------------|
| Ocorrências `bg-white` | 0 |
| Ocorrências `background: white` | 0 |
| Arquivos com dark-mode vars | 1 (colors.css) |
| Overrides `!important` | 0 (apenas transições) |

### Teste de Validação Final

```bash
# Deve retornar 0 resultados
grep -rn "bg-white\|background:\s*white" --include="*.html" --include="*.css" | wc -l
# Esperado: 0
```

---

## Apêndice A: Mapeamento de Classes

### Migração Tailwind

| Antes | Depois |
|-------|--------|
| `bg-white` | `bg-surface` ou `bg-surface-elevated` |
| `bg-gray-50` | `bg-surface-muted` |
| `bg-gray-100` | `bg-surface-muted` |
| `text-gray-900` | `text-text` |
| `text-gray-600` | `text-text-secondary` |
| `border-gray-200` | `border-border` |
| `border-gray-300` | `border-border` |

### Migração CSS

| Antes | Depois |
|-------|--------|
| `background: white` | `background: var(--surface-elevated)` |
| `background: #fff` | `background: var(--surface-elevated)` |
| `color: #1f2937` | `color: var(--text-primary)` |
| `border-color: #e5e7eb` | `border-color: var(--border-default)` |

---

## Apêndice B: Componentes Utilitários

### utilities.css (Novo Arquivo)

```css
/* ============================================
   PHARMDATA DESIGN SYSTEM - UTILITY CLASSES
   Componentes base com dark mode automático
   ============================================ */

/* === CARDS === */
.card {
    background: var(--surface-elevated);
    border: 1px solid var(--border-default);
    border-radius: 12px;
    padding: var(--space-6, 1.5rem);
}

.card-elevated {
    background: var(--surface-elevated);
    border: 1px solid var(--border-subtle);
    border-radius: 12px;
    padding: var(--space-6, 1.5rem);
    box-shadow: var(--shadow-md);
}

/* === INPUTS === */
.input-base {
    width: 100%;
    padding: 0.5rem 0.75rem;
    background: var(--surface-primary);
    border: 1px solid var(--border-default);
    border-radius: 8px;
    color: var(--text-primary);
    transition: border-color 0.2s, box-shadow 0.2s;
}

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

.input-base:focus {
    outline: none;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* === BUTTONS === */
.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.5rem 1rem;
    background: var(--accent-primary);
    color: var(--text-inverse);
    border: none;
    border-radius: 8px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s;
}

.btn-primary:hover {
    background: var(--accent-hover);
}

.btn-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.5rem 1rem;
    background: var(--surface-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-default);
    border-radius: 8px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s, border-color 0.2s;
}

.btn-secondary:hover {
    background: var(--surface-muted);
    border-color: var(--accent-primary);
}

/* === TABLES === */
.table-base {
    width: 100%;
    background: var(--surface-elevated);
    border: 1px solid var(--border-default);
    border-radius: 12px;
    overflow: hidden;
}

.table-base th {
    background: var(--surface-muted);
    color: var(--text-secondary);
    font-weight: 600;
    text-align: left;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border-default);
}

.table-base td {
    padding: 0.75rem 1rem;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-subtle);
}

.table-base tbody tr:hover {
    background: var(--surface-muted);
}
```

---

*Documento gerado em Dezembro 2024*
*PharmData Design System v3.x*
