# RiLiGar Zen — Especificação completa para agentes
> Design system autocontido. Tudo o que é necessário para construir, atualizar e **validar** uma interface RiLiGar está neste documento — não é preciso abrir o repositório.
Versão 1.0.0 · extraído de `@riligar/components-kit` (24 componentes, 6 primitivas).
Cada regra foi medida na frequência real de uso no código em produção. As contagens (`44×`, `57 ocorrências`) são dados, não estimativas.
---
## Como usar este documento
1. Leia **Regras invariantes** — são bloqueios, não sugestões.
2. Consulte **Tokens** para qualquer valor. Nunca invente um valor novo.
3. Use **API dos componentes** para escrever o código.
4. Copie de **Receitas** quando a tarefa se encaixar num padrão conhecido.
5. Antes de entregar, rode o **Protocolo de validação** — ele é executável.
---
## O sistema em 30 segundos
```
Uma fonte Montserrat, pesos 500 / 700 / 800 / 900 — nenhum outro
Uma cor cinza, 10 degraus, #FFFFFF → #11181C
Um raio 0 (57 ocorrências no kit, 0 exceções)
Um contorno 1px solid #F3F4F6
Quatro papéis label 10–13px · dado 12–14px · corpo 15–20px · display 32–120px
Dois fundos #FFFFFF e #F9FAFB
Duas densidades palco (convencer) e painel (operar) — mesmos tokens
```
Não há cor de marca, sombra, canto arredondado ou segunda família tipográfica. **Tamanho, peso e espaço são os únicos instrumentos de hierarquia.**
---
## As cinco leis
### Lei 1 — Conteúdo sobre cromo
**Cada elemento de cromo precisa responder "que informação eu comunico?". Se a resposta for "nenhuma, é estética", ele sai.**
Sobreviveram ao corte: o filete de 1px (comunica separação), o numeral fantasma de Steps (comunica ordem), o badge dot (categoria com mínimo de tinta). Foram cortados: sombras, bordas de Card, raio.
_Quando a página parece vazia demais, o erro está no conteúdo, não no design. A resposta é escrever melhor, não adicionar moldura._
### Lei 2 — Hierarquia massiva
**Não existe cor de destaque. A ênfase vem de contraste de escala, e o contraste precisa ser violento: salto de 3× a 6× entre níveis, nunca 1,2×.**
O par canônico é o cabeçalho de palco: label minúsculo, leve em tinta e disperso em tracking, imediatamente acima de um título enorme, pesado e apertado. Opostos em cinco dimensões ao mesmo tempo — é isso que cria a tensão.
_Implementado em SectionHeader. Toda seção do kit passa por ele._
### Lei 3 — O Palco
**Toda seção é um palco: fundo próprio, respiro vertical generoso, e um anúncio antes da performance.**
Não é opcional nem reimplementado por seção — é a primitiva Section. As únicas exceções (Header, Hero, SocialProof, Footer) existem porque têm geometria própria.
_Palcos consecutivos alternam white ↔ gray.1. É a única marcação de ritmo da página._
### Lei 4 — Config-driven, não JSX
**O consumidor passa dados, nunca marcação.**
Não é preferência de API — é o que mantém as leis 1–3 aplicáveis. Se o consumidor puder injetar JSX, ele injeta cromo, e o sistema erode em três sprints.
_Contrato padrão: id, badge, subtitle, title, background, items, cta, note._
### Lei 5 — Honestidade verificável
**Cada afirmação forte carrega o que a torna checável.**
Por isso StatsGrid tem description sob cada número e note sob a grade; Callout tem rodapé de honestidade; Hero tem note com o que custa experimentar. A nota é sempre o degrau mais baixo: 13px, gray.6, lh 1.5.
_Sem esta lei, hierarquia massiva vira só um número grande sem lastro. A nota é o que separa design de propaganda._
---
## Regras invariantes
Violar qualquer uma destas reprova o trabalho. Não são preferências:
| Regra | Valor | Lei |
| --- | --- | --- |
| `border-radius` | **sempre 0**, sem exceção | 1 |
| `box-shadow` | **nunca** | 1 |
| Cor | só a rampa gray (exceção única: `red.6` para perda quantificada) | 1 |
| Peso da fonte | só 500, 700, 800, 900 | 2 |
| `letter-spacing` | só `-0.04em`, `1.5px`, `2px` | 2 |
| Salto tipográfico | ≥3× entre níveis adjacentes | 2 |
| Cor de corpo | `gray.6` — nunca `gray.9` | 2 |
| Cor de título | `gray.9` — nunca `gray.6` | 2 |
| `gray.4` | só em label uppercase (falha AA em corpo) | 2 |
| Borda | `1px solid gray.2` | 1 |
| Palco | envolver `Section`, nunca reimplementar | 3 |
| Props | dados, nunca JSX | 4 |
| Fundo | alterna `white` ↔ `gray` a cada seção | 3 |
| Mobile | sempre 1 coluna | 3 |
| Métrica grande | sempre acompanhada de nota de verificação | 5 |
| Piso tipográfico | nada abaixo de 12px, exceto label uppercase (10–11px) | 2 |
| Erro | sempre `red.6` — nunca a mesma cor do sucesso | 5 |
| Skeleton | reproduz a grade real do conteúdo | 3 |
---
## Tokens — Cor
### A rampa
Degraus 0–3 são superfície e estrutura; 4–9 são tinta. Nenhum atravessa a fronteira.
| Token | Hex | Papel | Uso | Freq. |
| --- | --- | --- | --- | --- |
| `gray.0` | `#FFFFFF` | App base | Fundo branco puro | — |
| `gray.1` | `#F9FAFB` | Superfície alternada | Palco alternado, numeral fantasma | — |
| `gray.2` | `#F3F4F6` | Filete padrão | Toda borda do sistema | 10× |
| `gray.3` | `#E5E7EB` | Borda muda | Citação, estado desabilitado | — |
| `gray.4` | `#9CA3AF` | Texto quaternário | Label uppercase apenas | 7× |
| `gray.5` | `#6B7280` | Texto terciário | Rótulos, legendas | 20× |
| `gray.6` | `#4B5563` | Texto secundário | Corpo — a cor mais usada | 50× |
| `gray.7` | `#374151` | Corpo enfático | Descrição de destaque | 6× |
| `gray.8` | `#1F2937` | Texto primário escuro | Raro | 4× |
| `gray.9` | `#11181C` | Preto RiLiGar | Títulos, métricas, botão preenchido | 36× |
**As duas cores de trabalho:** `gray.9` para o que grita (36×), `gray.6` para o que fala (50×). Todo o resto é ajuste fino.
### Os três pretos
- `gray.9` (#11181C) — títulos, métricas, fundo de botão. Não é `#000`: o preto puro em tela grande vibra e cansa.
- `gray.7` (#374151) — corpo quando precisa de mais presença (parágrafo curto e central).
- `gray.6` (#4B5563) — corpo padrão. Em dúvida sobre a cor de um parágrafo, é esta.
### Fundos de seção
```js
SECTION_BACKGROUNDS = { white: 'white', gray: 'gray.1' }
```
Palcos consecutivos alternam. O contraste é de ~2% de luminância — deliberado: não separa as seções, apenas dá textura ao scroll. A separação real vem do `py` de 80–120px.
### Exceção cromática
`red.6` (#E03131) — Custo/perda quantificada. Aparece uma vez no kit inteiro, em `Comparison.jsx`, sob o custo da coluna "modo tradicional". É semântica de **perda**, não de erro genérico.
### Contraste (sobre #FFFFFF)
| Token | Ratio | Status |
| --- | --- | --- |
| `gray.9` | 16,8:1 | AAA |
| `gray.7` | 10,4:1 | AAA |
| `gray.6` | 7,5:1 | AAA |
| `gray.5` | 4,9:1 | AA em corpo |
| `gray.4` | 2,6:1 | **Falha AA em corpo** |
`gray.4` só é legítimo em label uppercase peso 800 — texto curto, não-essencial, redundante com o título abaixo. Nunca em parágrafo.
---
## Tokens — Tipografia
### Família
```css
font-family: Montserrat, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
```
Pilha sistema-primeiro: se o Google Fonts falhar, degrada para a fonte nativa, não para Times.
### Pesos
| Peso | Nome | Uso | Freq. |
| --- | --- | --- | --- |
| **900** | Black | Títulos, métricas, wordmark | 44× |
| **800** | ExtraBold | Labels uppercase, botões, badges | 20× |
| **700** | Bold | Ênfase em corpo, rótulo de métrica | 10× |
| **500** | Medium | Legenda técnica, letra miúda | 5× |
Não existe 400 declarado: quando o peso é escrito, é para subir. **900 e 800 nunca se tocam no mesmo bloco** sem um salto de tamanho de 4× separando-os.
**600 não existe neste sistema.** Está próximo demais de 700 para carregar significado distinto — onde aparecer, vira 700.
### Os quatro papéis
**Label** — _o anúncio_
```
10–13px · peso 800 · ls 1.5px · gray.4 · lh 1.4 · UPPERCASE
```
**Corpo** — _a performance_
```
15–20px · peso 400 · ls normal · gray.6 · lh 1.7
```
**Dado** — _a evidência_
```
12–14px · peso 500 · ls normal · gray.7 · lh 1.4
```
**Display** — _a declaração_
```
32–120px · peso 900 · ls -0.04em · gray.9 · lh 1.2
```
### Escala fluida
```css
--fz-hero: clamp(2.5rem, 8vw + 1rem, 6rem); /* 40 → 96px — Primeira dobra */
--fz-section-title: clamp(2rem, 5vw + 1rem, 3.5rem); /* 32 → 56px — Título de seção — o mais frequente */
--fz-big-metric: clamp(3rem, 10vw + 1rem, 7.5rem); /* 48 → 120px — Métrica — a mais dramática */
--fz-big-metric-sm: clamp(3rem, 5vw, 4.5rem); /* 48 → 72px — Métrica em grade de 4 colunas */
```
Fórmula sempre `clamp(min, Nvw + 1rem, max)`. O `+ 1rem` preserva a preferência de fonte do usuário — `vw` puro a ignora. Nenhum título tem tamanho fixo.
### Tracking
| Nome | Valor | Uso |
| --- | --- | --- |
| tight | `-0.04em` | Todo display e título |
| control | `1px` | Botão, link de navegação |
| label | `1.5px` | Todo label uppercase |
| wide | `2px` | Label de destaque, wordmark |
`-0.04em` é relativo (escala com a fonte fluida); `1.5px` é absoluto (label é sempre 10–13px). A inversão de sinal é o ponto: display precisa reagrupar, label precisa respirar.
### Line-height
| Valor | Uso | Freq. |
| --- | --- | --- |
| `1` | Métrica | 7× |
| `1.1` | Hero | 1× |
| `1.2` | Título de seção | 3× |
| `1.4` | Rótulo compacto | 6× |
| `1.5` | Nota | 3× |
| `1.6` | Corpo curto | 16× |
| `1.7` | Corpo padrão | 25× |
| `1.8` | Bloco longo (legal) | 6× |
### O par canônico
O padrão que define visualmente a marca — label e título opostos em cinco dimensões ao mesmo tempo:
| Dimensão | Label | Título |
| --- | --- | --- |
| Tamanho | 11px | 44px |
| Peso | 800 | 900 |
| Caixa | Alta | Sentença |
| Tracking | +1.5px | −0.04em |
| Cor | `gray.4` | `gray.9` |
```jsx