---
id: visual-polish-review
domain: web-craft
agents: [ux-design-expert, dev]
when: "ao revisar o acabamento visual de uma UI antes de entregar"
---

# Visual Polish Review — auditar o acabamento antes de entregar

## O problema

Uma UI "funciona" e ainda assim parece amadora. Não é por falta de feature — é falta de
**acabamento**: hierarquia construída só com tamanho de fonte, cinza puro em tudo, sombras
opacas e chapadas, espaçamento linear sem ritmo, botão sem estado de hover, tela vazia que
parece bug. Cada um desses é um **tell** que um olho treinado reconhece em meio segundo.

Este pack é a régua que Adam Wathan e Steve Schoger (*Refactoring UI*) usam: ~10 lentes de
auditoria, cada uma com **o tell** (o que denuncia o amador) e **a correção concreta** (o valor,
a regra, o CSS). Não é "melhore a tipografia" — é "trave em 2 pesos: 400-500 pra corpo, 600-700
pra ênfase; nunca abaixo de 400 em texto pequeno". A regra-mãe: **acabamento é um sistema de
escolhas pré-definidas, não tweak avulso por elemento.**

## O conhecimento

### Lente 1 — Hierarquia por peso e cor, não só por tamanho

**O tell:** todo destaque é "fonte maior". Títulos `font-size: 32px`, subtítulos `24px`, e a
hierarquia inteira mora no eixo do tamanho. Resultado: telas que incham e ainda assim parecem
planas.

**A correção:** distribua a hierarquia em **três eixos** — tamanho, **peso** e **cor**.
- Para texto, dois pesos bastam: **400–500** (corpo) e **600–700** (ênfase). Evite peso
  **abaixo de 400** em texto de UI — só funciona em título grande, é ilegível em corpo.
- Cor cria hierarquia **sem encolher a fonte**: escuro pro conteúdo primário, cinza pro
  secundário (data, metadado), cinza mais claro pro terciário (rodapé, copyright).
- **Emphasize by de-emphasizing:** às vezes o jeito de destacar um elemento é **apagar os
  vizinhos**, não empilhar mais peso no elemento. Reduza o ruído ao redor primeiro.

### Lente 2 — Tipografia: escala, line-height inverso, baseline

**O tell:** `line-height: 1.5` em título grande (frouxo demais), tamanhos avulsos sem escala,
textos de tamanhos diferentes alinhados pelo **centro**.

**A correção:**
- **line-height e font-size são inversamente proporcionais:** ~1.5 em corpo pequeno, e
  **apertado** (1.1–1.2) em display grande. Título com line-height de corpo é tell.
- Use uma **escala fixa** de tamanhos (escolha de uma lista, não digite valores arbitrários).
  Defina `font-size` em **px ou rem**, não em `em` (em compõe e vira imprevisível aninhado).
- Alinhe tamanhos mistos pela **baseline** (a linha onde as letras pousam), nunca pelo centro.
- **Letter-spacing:** confie no designer da fonte na maioria dos casos; **aperte** títulos em
  fontes de texto usadas grandes, e **solte** texto em ALL-CAPS.

### Lente 3 — Medida (line length) controlada

**O tell:** parágrafo que atravessa a tela inteira; texto longo **centralizado**.

**A correção:** **45–75 caracteres por linha** (~`max-width: 20–35em` para o bloco de texto, ou
uma `measure` ~`65ch`). Centralize só headline ou bloco curto independente — **texto corrido é
left-align**, sempre.

### Lente 4 — Cor em HSL, com cinzas que têm temperatura

**O tell:** `#808080` e amigos — cinza puro, dessaturado, frio-morto. Cor escolhida em HEX no
chute.

**A correção:** pense em **HSL** (Hue 0–360°, Saturation 0–100%, Lightness 0–100%) — é como o
olho enxerga.
- **Cinza não precisa ser cinza:** sature com **azul** pra paleta fria, com **amarelo/laranja**
  pra paleta quente. Cinza com 0% de saturação é o tell.
- **Quanto mais longe de 50% de lightness, mais saturação** o tom precisa — aumente saturation
  nos tons claros E escuros pra manter a temperatura constante ao longo da rampa.
- **Nunca cinza sobre fundo colorido.** O efeito "cinza sobre branco" é só **contraste
  reduzido**; sobre cor, escolha um tom de **mesmo hue** e ajuste S/L até aproximar do fundo.

### Lente 5 — Paleta como sistema, não 3 cores soltas

**O tell:** uma cor de marca, um cinza, preto e branco. Sem rampas — então todo hover/borda/
disabled é inventado na hora.

**A correção:** monte rampas com **~9 shades** (sweet spot) por cor:
- **8–10 tons de cinza** (do quase-branco ao quase-preto).
- **1–2 cores primárias**, 5–10 shades cada.
- **Accent colors** (sucesso, erro, aviso, info), 5–10 shades cada.
- Gradiente, quando usar: dois hues **a até 30° um do outro** (mais que isso fica "lama").

### Lente 6 — Espaçamento NÃO-linear, com ritmo

**O tell:** tudo em múltiplos de 8 sem variação — `gap-8`, `py-16` em toda seção. Espaço linear
é monótono e robótico.

**A correção:** escala **não-linear** onde **nenhum par de valores fica a menos de ~25%** um do
outro. Exemplo de rampa: **4, 8, 12, 16, 24, 32, 48, 64, 96, 128**. Use os **extremos** — seção
densa (prova social) ao lado de seção arejada (manifesto) cria ritmo. Heurística de processo:
**comece com espaço demais e remova até gostar** — quase sempre falta whitespace, não sobra.

### Lente 7 — Elevação em camadas (sombra de luz, não cinza opaco)

**O tell:** `box-shadow: 0 2px 4px #ccc` chapado em tudo; mesma sombra no botão e no modal.

**A correção:** uma **escala de ~5 sombras** mapeando elevação:
- pequena → botão/elemento levemente elevado;
- média → dropdown;
- grande → modal (precisa puxar atenção).
- Cada sombra combina **duas camadas**: luz **ambiente** (offset pequeno, blur menor, mais
  escura) + luz **direta** (offset vertical maior, blur grande, difusa). Spread **negativo** dá
  o efeito sutil quanto mais o objeto sobe. Ex.: `box-shadow: 0 25px 50px -12px rgba(0,0,0,.25)`.
- Cor da sombra: **preto transparente** (rgba), não cinza opaco; idealmente um tom **escuro do
  próprio hue** do fundo (sombra azul-escura sob botão azul), nunca `#888` chapado.

### Lente 8 — Separação sem borda

**O tell:** `border: 1px solid #ddd` em cada card, linha divisória em cada item. A tela vira
uma grade de gaiolas.

**A correção:** separe com **sombra, espaçamento ou cor de fundo** antes de recorrer a borda.
Dois fundos levemente diferentes, ou só mais respiro entre os blocos, separam melhor e mais
limpo que um traço. Borda fica pro caso em que sombra/espaço não bastam.

### Lente 9 — Estados de botão completos

**O tell:** botão tem só o estado **default**. Sem hover, sem active, sem focus visível (ou o
anel azul do browser), sem disabled. Foco azul nativo é tell de "esqueci do detalhe".

**A correção:** desenhe **todos os estados**:
- **hover** — sobe de elevação (sombra um degrau acima) ou escurece/clareia um shade da rampa;
- **active/pressed** — **reduz a sombra** pra sensação de "sendo pressionado";
- **focus** — anel **desenhado** (`outline`/ring de marca), nunca o azul default;
- **disabled** — contraste reduzido e cursor coerente.
- **Hierarquia de ações na mesma tela:** primária óbvia; secundária clara mas não dominante
  (fundo suave derivado da cor do texto); terciária descobrível mas discreta (link). Chevron no
  link de texto reforça que é clicável.

### Lente 10 — Empty states desenhados

**O tell:** tela vazia = página em branco, ou um texto que parece **erro** ("Nenhum dado.").
É a **primeira** interação do usuário com a feature e parece bug.

**A correção:** trate empty state como **boas-vindas**: ilustração ou imagem + uma frase com voz
+ **um CTA claro** que ensina o próximo passo. Mesma régua pra 404 e estados de erro — microcopy
com personalidade é assinatura barata e forte.

### Bônus — Imagem que não vaza

**O tell:** foto esticada (upscale), imagem de usuário com proporção quebrada, foto clara com
texto branco ilegível por cima.

**A correção:** só **reduza** imagem, nunca amplie. Controle dimensões de upload com
`background-size: cover`. Sombra sutil na imagem evita que o fundo "sangre" na borda. Texto sobre
foto: overlay (escurecer/colorir) pra garantir contraste.

## Checklist — "isto está acabado?"

Qualquer "sim" é um item a corrigir antes de entregar:

- [ ] A hierarquia mora **só** no tamanho da fonte (sem variar peso e cor)?
- [ ] Tem peso **abaixo de 400** em texto pequeno, ou `line-height ~1.5` em título grande?
- [ ] Texto corrido passa de **75 caracteres** por linha, ou está centralizado?
- [ ] Tem **cinza puro** (`#808080`/0% saturação) ou cinza sobre fundo colorido?
- [ ] As cores são valores soltos, **sem rampas** de ~9 shades pra hover/borda/disabled?
- [ ] O espaçamento é **linear/uniforme**, sem usar os extremos da escala?
- [ ] A sombra é **cinza opaco chapado**, igual no botão e no modal?
- [ ] A separação é feita com **borda** onde sombra/espaço/fundo bastariam?
- [ ] Algum botão tem **só default** (sem hover/active/focus desenhado/disabled)?
- [ ] O foco é o **anel azul do browser** em vez de um foco de marca?
- [ ] O **empty state / 404** é página em branco ou parece mensagem de erro?

## Tabela de decisão

| Lente | O tell | A correção concreta |
|---|---|---|
| Hierarquia | Destaque só por tamanho | 3 eixos: tamanho + peso (400-500 / 600-700) + cor; de-emphasize o entorno |
| Tipografia | line-height 1.5 em título; alinhar pelo centro | line-height inverso ao tamanho; escala fixa em px/rem; alinhar pela baseline |
| Medida | Linha atravessa a tela; texto centralizado | 45–75 caracteres (~20–35em / ~65ch); corrido é left-align |
| Cor (HSL) | `#808080`, cinza sobre fundo colorido | Sature o cinza (azul=frio, amarelo=quente); mesmo hue, ajusta S/L |
| Paleta | 3 cores soltas, sem rampa | ~9 shades por cor; 8-10 cinzas; gradiente com hues a ≤30° |
| Espaçamento | Tudo em múltiplos de 8 | Escala não-linear (≥25% entre valores: 4/8/12/16/24/32/48/64/96/128), usar extremos |
| Elevação | Sombra chapada igual em tudo | Escala de ~5; 2 camadas (ambiente+direta); rgba escuro do hue, não cinza opaco |
| Separação | Borda em todo card | Sombra, espaço ou dois fundos antes de borda |
| Botão | Só estado default | hover (sobe sombra) / active (baixa sombra) / focus de marca / disabled |
| Empty state | Página em branco ou texto de erro | Ilustração + voz + 1 CTA; mesma régua pro 404 |
| Imagem | Upscale, proporção quebrada, texto ilegível | Só reduzir; `cover`; sombra anti-bleed; overlay pro contraste |

> Fonte: *Refactoring UI* (Adam Wathan & Steve Schoger) e a palestra de Schoger no CSS Day 2019.
