# Grafismos

O guia de estilos institucional define quatro grafismos de marca: **arco de grande raio**, **linha de acento**, **pontos modulares** e **gradiente institucional**. Eles existiam apenas como especificação no guia (`.graphic-system`, `.graphic-tile`, `.arc`, `.line`, `.dots`, `.gradient`) e agora têm implementação própria no Design System, no bloco `TP:GRAPHICS` de `src/css/style.css`.

A regra editorial do guia governa a implementação inteira:

> Os grafismos nunca competem com a informação. Devem organizar, direcionar o olhar ou reforçar a presença da marca — não preencher espaço vazio por decoração.

Tudo o que segue é consequência dessa frase: o grafismo fica na margem, é decorativo para tecnologia assistiva, recua quando convive com texto e nunca passa atrás de um dado.

## Camada composicional

A especificação do guia desenha os grafismos dentro de um `tile` de demonstração. A implementação separa contêiner de desenho, para que o mesmo grafismo sirva a um cartão, a um cabeçalho de página, a um estado vazio ou a uma faixa institucional.

| Classe | Papel |
| --- | --- |
| `.tp-graphic` | Contêiner. `position: relative`, `isolation: isolate`, `overflow: hidden`. Declara os tokens locais do grafismo. |
| `.tp-graphic-content` | Envoltório do texto. Eleva o conteúdo (`z-index: 1`) e devolve a zona reservada do grafismo como `padding-block-end`. Todo texto que convive com um grafismo fica aqui dentro. |
| `.tp-graphic-surface` | Superfície de demonstração opcional: raio, borda e fundo de cartão. Não é obrigatória — qualquer superfície do sistema serve de contêiner. |
| `.tp-graphic-on-brand` | Sobre gradiente ou painel escuro: o desenho passa a branco transparente. |
| `.tp-graphic-soft` | Recua o grafismo (`--tp-graphic-opacity: 0.35`) quando ele precisa conviver com texto na mesma faixa vertical. |
| `.tp-graphic-overlap` | Desliga a zona reservada. Só para o contraexemplo do portal — ver abaixo. |

Os três desenhos posicionados — arco, linha e pontos — são filhos absolutos com `z-index: -1` e `pointer-events: none`. Dentro do `isolation: isolate` do contêiner, eles pintam acima do fundo da superfície e abaixo do texto em fluxo.

```html
<div class="tp-graphic tp-card">
  <span class="tp-graphic-arc tp-graphic-arc-end" aria-hidden="true"></span>
  <div class="tp-graphic-content">
    <h3>Resgates do trimestre</h3>
    <p>O conteúdo continua sendo o primeiro a ser lido.</p>
  </div>
</div>
```

## Zona reservada: a regra virou garantia do CSS

"Não competir com a informação" não pode ficar na recomendação ao autor. Medição em navegador (Chromium, sobre o build compilado) mostrou o arco padrão de 170&nbsp;px cruzando o texto sempre que o cartão era menor que o próprio grafismo — o defeito exato que o guia proíbe, produzido pelo Design System.

A correção é estrutural. Os três desenhos posicionados ancoram no fim do bloco, então o contêiner calcula, a partir do tamanho do grafismo que ele hospeda, a faixa inferior que o desenho alcança, e `.tp-graphic-content` devolve essa faixa como recuo. O texto termina acima do desenho por construção, em qualquer largura e nas duas escalas.

| Variável | O que guarda |
| --- | --- |
| `--tp-graphic-reserve-arc` | 47% do diâmetro do arco (a fração que sobra dentro do contêiner) mais uma folga de `--tp-space-2`. |
| `--tp-graphic-reserve-line` | Afastamento de 40&nbsp;px (`--tp-space-5` + `--tp-space-4`) mais metade da caixa girada em −18°. |
| `--tp-graphic-reserve-dots` | Afastamento de `--tp-space-5` mais a altura da grade (`--tp-graphic-dots-rows` × tamanho + intervalos). |
| `--tp-graphic-reserve` | O maior dos três. É o que `.tp-graphic-content` devolve como `padding-block-end` e o que define o `min-block-size` do contêiner. |

O contêiner precisa conhecer a escala para reservar o tamanho certo, e a escala é declarada no filho (`.tp-graphic-arc-lg`). `:has()` faz essa informação subir: `.tp-graphic:has(.tp-graphic-arc-lg)` redeclara `--tp-graphic-arc-size` no contêiner, que então calcula a reserva correta e a repassa ao filho por herança. A media query de 620&nbsp;px também atualiza a escala no contêiner — senão a reserva continuaria calculada sobre o tamanho de desktop.

Uma consequência honesta disso: **um arco grande exige uma superfície grande.** Se a peça não tem altura para hospedar o grafismo mais o texto, o resultado é uma peça alta, e a saída correta é usar `-sm` ou não usar grafismo ali. Os quatro exemplos do portal ficam em grade de duas colunas justamente por isso: em quatro colunas o tile fica mais estreito que o tile de 170&nbsp;px do próprio guia, e o arco passaria a dominar a peça.

### `.tp-graphic-overlap`

Desliga a zona reservada (`--tp-graphic-reserve: 0px`). **Existe para um único caso: o contraexemplo do portal**, a peça que precisa demonstrar o erro que o guia proíbe. Fora da demonstração não há uso legítimo — se um layout parece precisar dela, o que falta é espaço, não permissão. A verificação estática cobra que apenas os cartões marcados como *Evitar* a usem, e que nenhum grafismo seja reposicionado por `style` inline fora deles.

### Medição

O portal é medido em Chromium a 1440, 1280, 768 e 390&nbsp;px, nos temas claro e escuro, calculando a área de interseção entre cada elemento decorativo e cada nó de texto folha do mesmo contêiner. O critério é **zero px² em todos os contêineres**, exceto os dois marcados com `.tp-graphic-overlap`, onde a sobreposição é o argumento e precisa continuar existindo.

## Os quatro grafismos

### 01 · Arco de grande raio — `.tp-graphic-arc`

Círculo de traço grosso que sangra pelo canto da superfície. O raio é sempre maior que a peça que o recebe: o que se vê é um trecho de arco, não um anel completo.

- **Tokens:** `--tp-graphic-ink` (= `--color-brand-dark`, o traço), `--tp-graphic-arc-ratio`, `--tp-radius-full`.
- **Variantes:** `-start` / `-end` (lado), `-sm` (112 px), `-lg` (260 px) e `-wire` (o arco companheiro, abaixo).
- **Onde aplicar:** canto de cartão de destaque, hero, faixa institucional, estado vazio.
- **Onde não aplicar:** dentro da área de leitura; centralizado na peça; em mais de um canto da mesma superfície.

#### A construção, medida na p.07 — corrigida em 22/09/2026

A capa do manual **desenha o arco**, e ele não era o que o guia HTML supunha. Medido por dois caminhos independentes, em Chromium sobre a própria prancha:

| | Unidades |
| --- | ---: |
| Raio interno | `394,67` (extremos horizontais em 459,82 e 1249,16) |
| Diâmetro externo | `1273,04` (largura do `getBBox` do próprio anel) |
| **Faixa** | **`241,84`** |
| Terminais | cantos arredondados em `r ≈ 18,18` |
| Tinta | **Russian violet `#4B005A`** sobre Pale purple `#FAE4FF` |

**Faixa ÷ diâmetro = `0,189979`.** Uma varredura de `isPointInFill` no eixo do centro, feita à parte da leitura do `d`, devolve `241,84` para a faixa — as duas medições fecham.

**Cuidado com o número que se lê direto do `d`.** O `path` começa com `h-205,49`, e esse `205,49` é só o **trecho reto** da ponta da faixa: faltam ali os dois cantos arredondados (`205,49 + 2 × 18,18 = 241,85`). Tomar 205,49 como a faixa — e derivar o diâmetro externo como raio interno mais faixa — dá `0,1712`, que é 10% abaixo da construção real. O anel do manual é mais grosso do que ele parece na leitura ingênua do vetor.

**O que o sistema fazia.** `--tp-graphic-arc-stroke` era um pixel por escala: 16/112, 24/170 e 36/260, ou `0,1429`, `0,1412` e `0,1385` — as três abaixo da norma, e cada uma com um erro diferente. A faixa passou a ser derivada: `calc(var(--tp-graphic-arc-size) * var(--tp-graphic-arc-ratio))`, com `--tp-graphic-arc-ratio: 0.189979` declarado no `:root`. A 112 / 170 / 260 px isso dá 21 / 32 / 49 px.

**A tinta.** O anel da prancha é Russian violet, não Purple. `--tp-graphic-ink` passou de `--color-brand-primary` para `--color-brand-dark`. A troca é conservadora para contraste: Russian violet é mais escuro que Purple, então sobre as superfícies claras o desenho só ganha peso. Nos contextos em que o grafismo vive sobre fundo de marca (`.tp-graphic-on-brand`) e no tema escuro, `--tp-graphic-ink` continua sendo redeclarado pelo token semântico do contexto — a norma de tinta vale onde a tinta é a da marca, e não desfaz a adaptação de tema.

#### O arco companheiro em fio — `.tp-graphic-arc-wire`

A p.07 traz **dois** arcos. Além do anel cheio há um segundo, de geometria idêntica, deslocado na diagonal em `35,93` unidades (17,5% da faixa) e traçado em fio de `1` unidade, com o **stroke em gradiente Phlox `#D500FF` (offset 0) → Purple `#6B0080` (offset 0.8)**. O sistema não tinha grafismo nenhum com traço em gradiente.

`border` não aceita gradiente, então o fio é um fundo em gradiente recortado por máscara radial `closest-side` — o que mantém o fio em 1 px lógico em qualquer escala, e mantém o deslocamento diagonal proporcional à faixa. É decorativo como os demais e não fica atrás de texto: por isso é o único gradiente do bloco que pode terminar em Phlox, e a verificação que limita a parada dos gradientes de **superfície** o exclui explicitamente, em vez de a peça ter de contornar a regra.

O arco em fio do conjunto legado (`.tp-arc-outline`, do painel de autenticação e das páginas de erro) permanece em 2 px: a 620 px de diâmetro, `1/1273` daria 0,49 px, que some na tela. É o mínimo digital do mesmo desenho, não outra construção.

### 02 · Linha de acento — `.tp-graphic-line`

Traço fino inclinado em −18°. É o grafismo que direciona o olhar: aponta para o bloco seguinte e sai da leitura.

- **Tokens:** `--color-brand-accent` (Phlox), `--tp-radius-full`, `--tp-space-3` (afastamento lateral), `--tp-space-5` + `--tp-space-4` (afastamento inferior, 40 px).
- **Variantes:** `-start` / `-end`, `-sm` (72 px) e `-lg` (200 px).
- **RTL:** a inclinação espelha automaticamente sob `[dir="rtl"]` (`rotate(18deg)`), como o resto do template.
- **Onde aplicar:** margem de cabeçalho de seção, transição entre blocos.
- **Onde não aplicar:** como separador de conteúdo — para isso existe `.tp-divider`; e nunca mais de uma linha por superfície.

### 03 · Pontos modulares — `.tp-graphic-dots`

Grade de círculos pequenos. Organiza, marca ritmo e ancora um canto. Sempre em grade regular; pontos espalhados não são o grafismo da marca.

- **Tokens:** `--color-brand-primary`, `--tp-radius-full`, `--tp-space-2` (intervalo), `--tp-space-5` (afastamento).
- **Estrutura:** `<span class="tp-graphic-dots" aria-hidden="true"><i></i>…</span>`, com 9 elementos `<i>` para a grade 3 × 3 do guia.
- **Variantes:** `-start` / `-end`, `-sm` (6 px, 3 colunas) e `-lg` (10 px, 4 colunas).
- **Onde aplicar:** rodapé de cartão, canto de faixa, estado vazio.
- **Onde não aplicar:** atrás de número, rótulo ou controle; como textura de fundo repetida.

### 04 · Gradiente institucional — `.tp-graphic-gradient`

Faixa de marca em três paradas a 135°: Russian Violet → Purple → Mauveine. É o único grafismo que ocupa a superfície inteira, e por isso é o único que carrega texto por cima.

- **Tokens:** `--color-brand-dark` (0%), `--color-brand-primary` (54%), `--color-brand-mid` (100%), com texto em `--tp-on-dark`.
- **Contraste:** a parada mais clara é Mauveine `#81009B`. Texto branco sobre ela resolve em **8,7:1**, acima do mínimo AA de 4,5:1. **Phlox (`#D500FF`) fica fora do gradiente** justamente porque derrubaria o mesmo par para 4,0:1 — abaixo de AA. Um gradiente que termine em Phlox não pode receber texto.
- **Onde aplicar:** faixa de campanha, hero institucional, painel de marca.
- **Onde não aplicar:** fundo de tabela, formulário, lista operacional ou qualquer superfície de trabalho prolongado.

O gradiente já define `--tp-graphic-ink` e `--tp-graphic-accent` em branco transparente, então arco, linha e pontos aplicados sobre ele não precisam de `.tp-graphic-on-brand`.

## Acessibilidade

- **Todo grafismo é decorativo.** No markup recebe `aria-hidden="true"`; no CSS, `pointer-events: none`. Não recebe foco, não intercepta clique e não entra na ordem de leitura.
- **O grafismo nunca passa por trás do texto.** A zona reservada garante isso no CSS, não na revisão. Quando desenho e texto precisam mesmo compartilhar a faixa vertical, quem recua é o grafismo (`.tp-graphic-soft`), nunca a cor do texto.
- **Sobre o gradiente, todo texto herda o branco** — inclusive papéis com cor própria, como `.tp-eyebrow`, `.tp-help` e os rótulos. Sem isso um rótulo ficaria em roxo institucional sobre roxo institucional.
- **O par texto/gradiente é calculado, não estimado.** O limite de paradas do gradiente existe por causa do cálculo de contraste registrado acima.
- **Nenhum grafismo anima.** Ainda assim, `@media (prefers-reduced-motion: reduce)` zera `animation` e `transition` dos quatro elementos, para que uma animação acrescentada por um projeto já nasça suprimida.

## Tema escuro

Sobre as superfícies escuras do projeto (`--color-ui-dark-card`), o roxo institucional praticamente desaparece. A adaptação é por token, não por cor nova:

| Elemento | Tema claro | Tema escuro |
| --- | --- | --- |
| Arco e pontos | `--color-brand-dark` (Russian violet, p.07) | `color-mix(in srgb, var(--tp-action) 55%, transparent)` |
| Linha de acento | `--color-brand-accent` | `color-mix(in srgb, var(--color-brand-accent) 60%, transparent)` |
| Gradiente | `--color-brand-dark` → `--color-brand-primary` → `--color-brand-mid` | `--color-brand-950` → `--color-brand-dark` → `--color-brand-primary` |

As regras seguem o mecanismo de tema do projeto (`.dark` e `[data-theme="dark"]`, alinhados ao `@custom-variant dark (&:is(.dark *))`).

## Responsividade

Abaixo de 620 px (`--tp-breakpoint-mobile`), arco e linha encolhem por variável, sem redeclarar posição — e a escala muda também no contêiner, para que a zona reservada encolha junto. Se mesmo assim o grafismo cobrir conteúdo, a correção é remover o grafismo — não reduzir o texto.

## Ligação com o guia de estilos

A especificação original do guia era um sistema de demonstração: uma grade de quatro `tiles` de 170 px com os desenhos posicionados por valores absolutos e cores em hex. A implementação preserva as medidas e a intenção e muda três coisas:

1. **Nenhum hex literal.** Todas as cores vêm dos primitivos de marca (`--color-brand-*`) e dos tokens semânticos (`--tp-space-*`, `--tp-radius-*`, `--tp-on-dark`).
2. **Composição, não demonstração.** O `tile` do guia vira o par contêiner + desenho, aplicável a qualquer superfície. `.tp-graphic-surface` reproduz o tile quando ele for útil como exemplo.
3. **A regra editorial é executável.** No guia, "não competir com a informação" é uma frase. Aqui é a zona reservada: o CSS não permite o desenho alcançar o texto, e a verificação estática mais a medição em navegador cobram isso a cada mudança.
4. **Unidades lógicas.** `inline-size`, `block-size`, `inset-inline-*` e `inset-block-*` no lugar de `width`, `height`, `right` e `bottom`, mantendo a coerência com o suporte a RTL do template.

A seção **10 · Grafismos** do portal (`src/partials/design-system/grafismos.html`) mostra os quatro grafismos, os pares de uso correto e incorreto e a tabela de aplicação. A seção **20 · Imagem, interface e grafismos** continua tratando de imagem e interface; a norma dos grafismos é esta.
