# DESIGN.md: padrão Apple para HTML, dashboards e páginas

Acompanha a skill padrao-apple-html. Cada regra traz o porquê.

## 1. Tokens
```css
:root{
  --font:-apple-system,BlinkMacSystemFont,"SF Pro Text","SF Pro Display",system-ui,sans-serif; /* sem Google Fonts: carrega na hora e parece nativo */
  --ac:#007AFF;          /* a única cor de destaque (escuro: #0A84FF) */
  --ok:#34C759; --warn:#FF9500; --bad:#FF3B30;  /* só para status, nunca para enfeitar */
  --tx:#1D1D1F; --tx2:#6E6E73; --tx3:#86868B;   /* use --tx3 só em texto >=17px: tem contraste 3,5:1 */
  --bg:#F5F5F7; --card:#FFF; --line:#E5E5EA;
  --r:12px; --r-sm:8px;                         /* raio do card e raio de botão/chip */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; /* grade 4/8 */
}
body{font-family:var(--font);color:var(--tx);background:var(--bg);font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased}
```
- **Escala de texto:** 12 (meta, nunca menor que 11px) · 13 (rótulo) · 15 (corpo) · 17 (título de card) · 22 (título de página) · 28–34 (número de KPI, peso 600).
- **Peso:** 400 no corpo, 600 em títulos e números. Evite 800/900, porque dão cara de template.
- **Números:** `tabular-nums` em todos, para as colunas não "dançarem".

## 2. Layout
- **Cards compactos:** padding de 16 (12 no celular) e gap de 12. Pouco espaço em branco, porque painéis mostram muita informação em pouca tela.
- **Grade:** `repeat(auto-fit,minmax(160px,1fr))` nos KPIs. O conteúdo vai até 1200px.
- **Celular (390px):** nada vaza. Use `min-width:0` nos filhos de grid/flex, tabelas largas dentro de `overflow-x:auto` e texto com `overflow-wrap:anywhere`.
- **Toque:** todo alvo clicável tem no mínimo 44×44. Se precisar, use padding ou margem negativa.
- **Elevação:** borda de 1px `--line`. Sombra só em overlay (`0 8px 24px rgba(0,0,0,.16)`).
- **Ícones:** SVG de traço (estilo Lucide/SF), com stroke 2 e 14/18px e `currentColor`.

## 3. Trechos certos
**Card + KPI** (a variação sempre vem com contexto):
```html
<section class="card">
  <h2>Atendimentos</h2>
  <div class="kpi">1.284</div>
  <p class="var up">+8,2% <span>vs mês anterior</span></p>
</section>
<style>
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:var(--s4);min-width:0}
.card h2{font-size:13px;font-weight:600;color:var(--tx2);margin:0 0 var(--s2)}
.kpi{font-size:28px;font-weight:600;line-height:1.1}
.var{font-size:13px;margin:var(--s1) 0 0}.var.up{color:var(--ok)}.var.down{color:var(--bad)}
.var span{color:var(--tx2)}
@media(max-width:430px){.card{padding:var(--s3)}}
</style>
```
**Gráfico simples** (barras em SVG, uma cor, rótulo direto, sem moldura, grade ou legenda):
```html
<svg viewBox="0 0 300 120" width="100%" role="img" aria-label="Atendimentos por mês">
  <g fill="var(--ac)">
    <rect x="10" y="40" width="40" height="60" rx="4"/><rect x="70" y="20" width="40" height="80" rx="4"/>
  </g>
  <g font-size="12" fill="var(--tx2)" text-anchor="middle">
    <text x="30" y="116">Set</text><text x="90" y="116">Out</text>
    <text x="90" y="14" fill="var(--tx)" font-weight="600">1.284</text>
  </g>
</svg>
```
Em linhas, o rótulo vai no fim de cada linha, junto com o valor. A previsão fica tracejada e o dado real fica sólido.

## 4. Exceções (só quando pedirem)
- **Material de outra marca:** troque só a cor de destaque e a fonte pelas da marca. O resto do padrão continua valendo.

## 5. Proibido (unslop, partes 1 e 2)
1. Emoji na interface. Emoji dentro de dados reais, como mensagens, fica.
2. Gradiente, glow, glass/blur e Liquid Glass atrás de números.
3. Mais de uma cor de destaque. As cores semânticas são só para status.
4. Rótulo em caixa alta minúsculo acima do título. Título de seção vai em caixa normal.
5. Numeração decorativa ("01 / 02 / 03").
6. Subtítulo que repete o título.
7. Selos e bolinhas que não medem nada ("LIVE", "NEW", pílula preta de contador). Use um número discreto.
8. Card dentro de card.
9. Texto cinza sobre fundo colorido, porque o contraste fica fraco.
10. Gráfico com moldura, grade e legenda pesada.
11. Glifos de texto como ícone (▾ ✓ ✕ ×). Use SVG.
12. Variação sem contexto ("+8%" sozinho).
13. Fato não confirmado ou campo "[A PREENCHER]". Se não está na fonte, não entra.

## 6. Rodada final de acabamento
É uma passada separada, sem mexer no conteúdo, só em:
- espaçamento na grade 4/8;
- escala tipográfica;
- ícones consistentes;
- estados de hover/toque/foco;
- modo escuro (se houver).

Em slides, troque hover por alinhamento e respiro.

## 7. QA antes de entregar
- [ ] Render em 1440×900 e 390×844 (Playwright, deviceScaleFactor 2), conferindo os prints.
- [ ] `document.documentElement.scrollWidth == innerWidth` nas duas larguras, ou seja, sem scroll horizontal.
- [ ] 0 erros no console.
- [ ] Números iguais aos da fonte. Se for refação, compare antes e depois.
- [ ] Um detector de anti-padrões de HTML (ex.: Impeccable) sem achado relevante novo.
- [ ] Se tiver tabela, ela rola dentro do card, não a página.

## 8. Componentes de gráfico
Os padrões foram escritos do zero com os tokens da seção 1.

**Regras comuns a todos os gráficos**
- **Rótulo direto no dado, sem legenda.** *Gestalt (proximidade): o olho não precisa ir e voltar.*
- **Sem moldura, grade só em 1 linha de base ou meta.** *Data-ink ratio (Tufte).*
- **Uma cor de destaque (`--ac`) e o resto em cinza (`--line`/`--tx3`).** *Pré-atenção: a cor só serve se for rara.*
- **Semânticas (`--ok`/`--bad`) só para sinal (+/−).** *Consistência e padrões (Nielsen #4).*
- **SVG com `role="img"` e `aria-label` contando a conclusão; os valores também ficam em `<table class="sr">`.** *WCAG 1.1.1.*
- **Texto de rótulo em `--tx2` (4,6:1 sobre branco). `--tx3` só em ≥17px.** *WCAG 1.4.3.*
- **Animação só com `@media (prefers-reduced-motion:no-preference)` e até 200ms.** *WCAG 2.3.3: movimento não carrega informação.*
- **No celular (≤430px), o SVG usa `viewBox` e `width:100%`. Rótulos de eixo pulam 1 a cada 2. Nada passa de 100vw.** *Seção 2.*

```css
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.ch text{font-size:12px;fill:var(--tx2)} .ch .v{fill:var(--tx);font-weight:600}
@media (prefers-reduced-motion:no-preference){.ch rect,.ch path{transition:opacity .2s,height .2s}}
```

### 8.1 Destaque ao passar o mouse (foco) + dica
- **Quando usar:** séries com mais de 6 pontos, quando a pessoa precisa do valor exato de um ponto. **Quando não usar:** com até 6 barras. Aí o rótulo direto já resolve.
- **Visual:** o ponto em foco fica `--ac` e os outros caem para opacidade .35. A dica é um card branco com borda `--line` e sombra de overlay, mostrando valor e comparação. *Pré-atenção + figura e fundo (Gestalt).*
- **Acessibilidade:** cada barra tem `tabindex="0"` e `aria-label` com valor e período. O foco por teclado (setas ←/→) faz o mesmo que o hover, com contorno `2px var(--ac)`. *Nielsen #7 (flexibilidade) e WCAG 2.1.1.*
- **Celular:** toque fixa o foco. Um segundo toque ou um toque fora solta. A dica fica acima do gráfico, sem cobrir o dedo. *Lei de Fitts: o alvo é a coluna inteira, com ≥44px de altura.*
```js
svg.querySelectorAll('[data-i]').forEach(b=>{
  const on=()=>{svg.classList.add('foc');svg.querySelectorAll('[data-i]').forEach(x=>x.classList.toggle('on',x===b));tip(b)};
  b.addEventListener('pointerenter',on);b.addEventListener('focus',on);
});
svg.addEventListener('pointerleave',()=>svg.classList.remove('foc'));
/* css: .foc [data-i]{opacity:.35} .foc [data-i].on{opacity:1} */
```

### 8.2 Abas de período (semana / mês / ano)
- **Quando usar:** o mesmo gráfico em até 3 ou 4 recortes de tempo. **Quando não usar:** com mais de 4 opções (use um `<select>`) ou quando os recortes mudam a métrica. *Lei de Hick: poucas escolhas, decisão rápida.*
- **Visual:** um controle segmentado com fundo `--bg` e a aba ativa em `--card` com 600. Raio `--r-sm`, altura 32 e alvo de 44 com padding. O KPI e a comparação ("vs mês anterior") mudam juntos. *Visibilidade do estado (Nielsen #1).*
- **Acessibilidade:** `role="tablist"`, `aria-selected` e setas para navegar. **Celular:** ocupa a largura toda, com abas de largura igual.
```html
<div class="seg" role="tablist" aria-label="Período">
  <button role="tab" aria-selected="false">Semana</button><button role="tab" aria-selected="true">Mês</button><button role="tab" aria-selected="false">Ano</button>
</div>
<style>.seg{display:flex;background:var(--bg);border-radius:var(--r-sm);padding:2px}
.seg button{flex:1;min-height:32px;border:0;background:none;font:inherit;font-size:13px;color:var(--tx2);border-radius:6px}
.seg [aria-selected=true]{background:var(--card);color:var(--tx);font-weight:600;border:1px solid var(--line)}</style>
```

### 8.3 KPI com sparkline
- **Quando usar:** um card de KPI que precisa mostrar a tendência sem abrir um gráfico. **Quando não usar:** se a pessoa precisa ler valores de eixo. *Tufte: sparkline é "palavra-dado", intensa e pequena.*
- **Visual:** linha de 1,5px em `--ac`, 100%×32px, sem eixo, com um ponto só no último valor. A variação com contexto fica embaixo (seção 3). *Data-ink ratio.*
- **Acessibilidade:** `aria-label="Tendência: subiu 12% em 6 meses"`. **Celular:** igual, a altura não muda.
```html
<svg class="spark" viewBox="0 0 100 32" preserveAspectRatio="none" role="img" aria-label="Tendência de alta em 6 meses">
  <polyline points="0,26 20,22 40,24 60,14 80,12 100,6" fill="none" stroke="var(--ac)" stroke-width="1.5" vector-effect="non-scaling-stroke"/>
</svg>
```

### 8.4 Barra de progresso com marca de meta
- **Quando usar:** o realizado contra uma meta ou um teto (vendas vs meta, orçamento usado). **Quando não usar:** sem meta definida. Aí basta o número. *Few (bullet graph): comparar com a referência é o que dá sentido ao número.*
- **Visual:** trilho de 8px em `--line` e preenchimento em `--ac`. A meta é um traço vertical de 2px em `--tx` com o rótulo "Meta R$ X" acima. Ao passar do teto de orçamento, o excesso fica `--bad` e ganha o texto "acima do limite". A cor nunca fica sozinha. *WCAG 1.4.1 (não depender só de cor).*
- **Acessibilidade:** `role="progressbar"` com `aria-valuenow`, `aria-valuemax` e `aria-valuetext="72% da meta"`. **Celular:** o rótulo da meta passa para baixo da barra se ficar a menos de 15% da borda.
```html
<div class="prog" role="progressbar" aria-valuenow="72" aria-valuemax="100" aria-valuetext="72% da meta">
  <i style="width:72%"></i><b style="left:85%" title="Meta"></b></div>
<style>.prog{position:relative;height:8px;background:var(--line);border-radius:4px}
.prog i{display:block;height:100%;background:var(--ac);border-radius:4px}
.prog b{position:absolute;top:-4px;width:2px;height:16px;background:var(--tx)}</style>
```

### 8.5 Cascata (waterfall)
- **Quando usar:** explicar como se chega de um valor inicial a um final (saldo, margem, ponte de receita). **Quando não usar:** em série temporal comum. *Narrativa causal: o gráfico responde "por quê?".*
- **Visual:** as barras de início e fim em `--tx2`. As entradas em `--ok` e as saídas em `--bad`, cada uma com o rótulo +/− direto. Um conector de 1px `--line` liga o topo de cada barra à seguinte. *Continuidade (Gestalt).*
- **Acessibilidade:** o sinal está no texto (+/−), não só na cor. A tabela `.sr` lista os passos. **Celular:** com mais de 6 passos, vira lista horizontal rolável dentro do card ou barras horizontais.
```js
let acc=0;steps.forEach((s,i)=>{const total=s.t;const y0=total?0:acc;acc=total?s.v:acc+s.v;
  bar(i,Math.min(y0,acc),Math.abs(total?s.v:s.v),total?'var(--tx2)':s.v>=0?'var(--ok)':'var(--bad)')});
```

### 8.6 Barras empilhadas e 100% (alocação)
- **Quando usar:** a composição de um total (por canal, por categoria), com até 5 partes. Use a de 100% quando a pergunta é proporção. **Quando não usar:** com mais de 5 partes (agrupe em "Outros") ou para comparar partes do meio entre colunas. *Cleveland & McGill: comprimento numa base comum se lê melhor que ângulo, por isso fica no lugar do donut.*
- **Visual:** a parte mais importante fica na base, em `--ac`. As outras vão em tons de cinza (`#C7C7CC`, `#D1D1D6`, `#E5E5EA`), com 1px de separação branca. O rótulo vai dentro do segmento se couber (≥36px) e, se não, na lista ao lado em ordem. *Pré-atenção.*
- **Acessibilidade:** os segmentos são focáveis e seguem 8.1. **Celular:** vira uma barra horizontal de 100% com a lista embaixo.

### 8.7 Barra horizontal ranqueada
- **Quando usar:** comparar categorias com nomes longos (país, produto, vendedor). Já vem ordenada. **Quando não usar:** com tempo no eixo (aí é coluna ou linha). *Lei de Jakob/F-pattern: lê-se o nome à esquerda e o valor à direita.*
- **Visual:** a ordem é decrescente. O primeiro (ou o item em análise) fica `--ac` e os outros `--line`. Valor no fim da barra. Mostre no máximo 7 e o resto como "+N outros". *Limite de Miller e redução de ruído.*
- **Acessibilidade:** é uma lista `<ol>` de verdade, sem SVG, e o leitor de tela lê na ordem. **Celular:** nome em cima e barra embaixo, se o nome passar de 40% da largura.
```html
<ol class="rank"><li><span>Brasil</span><i style="--w:100%"></i><b>4.120</b></li></ol>
<style>.rank li{display:grid;grid-template-columns:minmax(0,9em) 1fr auto;gap:8px;align-items:center;font-size:13px}
.rank i{height:8px;width:var(--w);background:var(--line);border-radius:4px}.rank li:first-child i{background:var(--ac)}</style>
```

### 8.8 Barras divergentes (entrada × saída)
- **Quando usar:** valores com sinal em torno de zero (entradas vs saídas, saldo líquido, NPS). **Quando não usar:** com séries só positivas. *Pré-atenção: o lado (acima/abaixo de zero) se lê antes do tamanho.*
- **Visual:** a linha zero em `--tx3` de 1px, positivos acima em `--ok` e negativos abaixo em `--bad`. O saldo líquido pode vir como ponto `--tx`. O sinal aparece no rótulo.
- **Acessibilidade e celular:** iguais aos de 8.1. No celular, rótulo só no maior e no menor valor.

### 8.9 Combo: barras + linha
- **Quando usar:** volume (barras) e taxa ou média (linha) na mesma linha do tempo, como receita e margem %. **Quando não usar:** se as duas medidas não têm relação causal. Eixo duplo engana. *Integridade gráfica (Tufte, "lie factor").*
- **Visual:** barras em `--line`, linha em `--ac` 2px. O valor da linha fica no último ponto e a unidade de cada série vai no rótulo direto, sem legenda. Só o eixo direito ganha rótulo, e só se necessário.
- **Celular:** abaixo de 430px, considere dividir em dois gráficos empilhados (*small multiples*).

### 8.10 Área com comparação ao período anterior
- **Quando usar:** acompanhar a evolução de um total no tempo contra o mesmo período anterior. **Quando não usar:** com várias séries sobrepostas (use *small multiples*).
- **Visual:** área de `--ac` com opacidade .12 e linha `--ac` de 2px. O período anterior é uma linha tracejada `--tx3` sem área. O rótulo no fim de cada linha diz "Out 2026" e "Out 2025". *Pré-atenção: sólido = agora, tracejado = referência.* A opacidade é cor chapada, não gradiente (seção 5.2).
- **Acessibilidade:** a diferença vai escrita no `aria-label` ("+8% vs out/25").

### 8.11 Previsão com faixa de incerteza
- **Quando usar:** projeção com intervalo (forecast). **Quando não usar:** sem um método de previsão de verdade. Nada de inventar curva (seção 5.13).
- **Visual:** o real é sólido e a previsão tracejada (seção 3). A faixa min–max fica em `--ac` com opacidade .10. Uma linha vertical "hoje" de 1px `--line`. *Honestidade sobre incerteza: o tracejado avisa "isso não aconteceu ainda".*

### 8.12 Faixa (mín–máx) por período
- **Quando usar:** quando a variação importa tanto quanto a média (preço, tempo de resposta, gasto diário). **Quando não usar:** se só a média interessa.
- **Visual:** uma barra fina de 6px em `--line` do mínimo ao máximo, com um ponto `--ac` na média ou no valor atual. Rótulo de mín e máx só no item em foco. *Data-ink ratio: 3 números num traço.*

### 8.13 Linha de leitura (insight) e estados
- **Linha de leitura:** uma frase embaixo do gráfico que diz a conclusão ("Saídas caíram 12% desde agosto"), escrita a partir do dado e nunca inventada. *Reconhecimento em vez de memória (Nielsen #6).* Sem emoji e sem ícone de "lâmpada".
- **Carregando:** um bloco com a altura final do gráfico, fundo `--bg` e raio `--r-sm`, sem shimmer animado se `prefers-reduced-motion`. *Evita salto de layout (CLS).*
- **Vazio:** "Sem dados neste período" + ação ("Ver mês anterior"). Eixo falso e zero inventado ficam de fora. *Nielsen #9: diga o que aconteceu e o que fazer.*
- **Erro:** "Não deu para carregar" + "Tentar de novo". O resto do painel continua.

### 8.14 O que ficou de fora e por quê
- **Cilindro 3D:** a perspectiva distorce o tamanho (lie factor).
- **Hexbin e grade de favos:** decorativo em dashboard executivo; a densidade vira mapa de calor sem eixo legível.
- **Radial, em anel ou em "girassol":** ângulo e raio se leem pior que comprimento (Cleveland & McGill).
- **Fluxo (Sankey):** cruzamentos demais para leitura rápida. Só se a pergunta for "para onde vai cada real", e aí como exceção.
- **Grade de quadradinhos (waffle):** ocupa espaço para mostrar 1 número. Use 8.4.
- **Dispersão:** é análise exploratória, não leitura executiva. Fica para estudo e não para painel.
- **Gráfico de cripto/candle:** fora do contexto de painéis de trabalho.
