Ir ao conteúdo
SEED engenhariaDesign System

Tokens

3c. Dataviz — escalas de dado

estávelseed-tokens.md v1.23 · §03cseção 6 de 1703c-dataviz-escalas-de-dado-fase-5-dt-v1-3-e.md · MD5 1bd00911

Título completo no canon: Dataviz — escalas de dado (Fase 5: DT v1.3 e categórica estendida v1.5, ambas estável)

Estado: estável desde 2026-08-09, por "aprovo" explícito do Rafael no gate visual do preview seed-dataviz-tokens-preview.html v0.2 completo. Consumidor primário e dono das REGRAS de consumo: seed-dataviz.md v0.3 (9º canônico) — esta seção é dona dos VALORES, aquele arquivo é dono das leis (DF7: uma fonte, referência sem duplicação).

Entrega prometida desde a v1.0 ("escalas sequenciais e divergentes para heatmap/mapa/desvio · tokens de gauge"), produzida no sub-bloco DT da F5 em 2026-08-09. Regra-mãe (DF7 do seed-dataviz.md): este arquivo é a ÚNICA fonte dos valores; o seed-dataviz.md referencia, nunca duplica. Todos os stops das escalas do DT (sequencial, no-data, divergente, gauge, strokes v1.3) vêm das rampas do §2.1 — nenhum hex novo foi criado NO DT. A categórica estendida v1.5 (subseção própria abaixo) supersede essa restrição para o domínio categórico, com racional medido. Medições do DT por contraste-dataviz.py em 2026-08-09; fundos de referência do DT: branco (light) e #0B1419 dark-page (§2.4). A categórica v1.5 declara os seus próprios fundos de referência na subseção.

Sequencial — --seed-chart-seq-1…7 (heatmap, mapa coroplético, intensidade)#

Rampa turquesa em 7 classes, stops 100→900 no light (saltando 500 e 700) e o espelho 800→100 no dark (entrando o 500). Semântica: valor cresce, tinta cresce (light) / valor cresce, luz cresce (dark) — em ambos os modos o mínimo se aproxima do fundo, mapeamento perceptual correto de intensidade.

Achado do gate visual do Rafael (2026-08-09) — supersede da escala proposta originalmente. A primeira versão desta tabela usava os stops 50→800; no preview, o Rafael apontou que as duas primeiras classes liam como cinza ("essa escala inicial era pra ser toda em cinza mesmo?"). O chroma dos stops 50/100 é tão baixo que em tela eles perdem o hue — e cinza, em dataviz, significa "sem dado": valor baixo e ausência de medição ficavam ambíguos. Correção (opção A, aprovada pelo Rafael sobre preview comparativo): a rampa desloca um stop (100→900) e o cinza fica reservado ao token novo chart-no-data. Alternativa descartada (opção B): manter 50→800 e resolver só pela regra do no-data — rejeitada porque a leitura "primeiras classes parecem cinza" permaneceria na tela.

Classe Light (stop) Dark (stop) vs fundo light vs fundo dark
seq-1 turquesa-100 turquesa-800 1.19 1.99
seq-2 turquesa-200 turquesa-700 1.45 2.94
seq-3 turquesa-300 turquesa-600 1.83 4.05
seq-4 turquesa-400 turquesa-500 2.71 5.77
seq-5 turquesa-600 turquesa-400 4.60 6.86
seq-6 turquesa-800 turquesa-200 9.37 12.85
seq-7 turquesa-900 turquesa-100 13.55 15.62

Isenção declarada (mesmo padrão da §4.3 do seed-email.md, agora com respaldo normativo direto): o WCAG 1.4.11 isenta explicitamente situações onde mudar a cor muda o significado — heatmap é o exemplo nomeado pela norma. As razões acima são informativas, não gate. Condições de acompanhamento obrigatórias: (a) célula/região de heatmap sempre com valor acessível por rótulo, tooltip ou tabela-fallback (1.1.1); (b) fronteira entre células sustentada por chart-grid, nunca só pela diferença de cor; (c) legenda de escala sempre presente com os limites numéricos das classes. Gatilho de revisão: se uma classe sequencial passar a portar significado categórico isolado (ex.: "acima do limite regulatório"), aquela classe sai da isenção e entra na régua de 3:1.

Sem dado — --seed-chart-no-data (célula/região sem medição)#

Token Light Dark Regra dura
chart-no-data cinza-100 cinza-800 SEMPRE com hachura diagonal (padrão repetido ~45°), nunca cor lisa
chart-no-data-hatch (novo na v1.7) cinza-600 #617683 cinza-400 #90A6B3 A tinta das linhas da hachura. Medido contra o preenchimento: 3,93 (light) · 3,84 (dark), ambos ≥3

Nasce do mesmo achado do gate: o cinza agora é exclusivo de "sem dado" em qualquer gráfico SEED — nenhuma escala de valor pode usá-lo — e a hachura garante que a distinção "gerou pouco × não reportou" nunca dependa de cor (1.4.1), inclusive em grayscale e impresso. A legenda do gráfico ganha o item "sem medição" sempre que houver célula no-data.

SUPERSEDE formal na v1.7 (2026-08-11) — a hachura ganha token próprio. História completa, porque ela é instrutiva: na v1.0 a hachura era desenhada em cat-5-stroke, que naquela paleta era cinza-600. Na v1.5 o cat-5 virou violeta, e a hachura de "sem medição" passou a ser desenhada com cor de categoria viva — o pior lugar possível para esse erro, já que "sem medição" é exatamente o que não pode parecer uma categoria. A errata E3 corrigiu isso em 2026-08-11 apontando a hachura para chart-axis. A correção resolveu a semântica e quebrou a medição: chart-axis é cinza-500 no light e mede 2,80 contra o preenchimento cinza-100 — abaixo do piso de 3:1 do 1.4.11. O defeito foi encontrado em 2026-08-11 pela reescrita do contraste-dg.py (v2, DI18), que passou a medir esse par; a v1 do script não o media.

Fato desconfortável e registrado de propósito: o valor correto já estava em uso antes da correção, por acidente — o cinza-600 da paleta antiga passava com 3,93. A E3 trocou um valor certo com semântica errada por um valor errado com semântica certa, porque a troca não foi remedida.

Regra que sai daqui e vale para todo o sistema: toda substituição de token exige remedição dos pares que aquele token participa — não basta a substituição ser semanticamente correta. A E3 e esta v1.7 são o par de exemplos.

Alternativa descartada: fazer a hachura consumir o primitivo cinza-700 diretamente, sem token novo (5,43 contra o preenchimento, passa folgado). Rejeitada porque repetiria a estrutura do erro original em outra forma: a causa raiz da E3 foi um papel de desenho ("a tinta da hachura de ausência") existir sem token próprio, tomando emprestado o token de outro papel. Emprestar de um primitivo, em vez de emprestar de uma categoria, ainda é emprestar — e viola a lei "componente consome semântico".

Geografia — --seed-chart-geo-base e --seed-chart-geo-boundaryv1.8, ADIÇÃOestável#

Token Light Dark Papel
chart-geo-base (novo na v1.8) #F2F6F9 #141D23 Território de CONTEXTO de um mapa: a área geográfica que não é objeto de medição
chart-geo-boundary (novo na v1.8) #788F9D #90A6B3 Fronteira de município desenhada. Medida contra o chart-geo-base: 3,11 (light) · 6,74 (dark), ambas ≥3

Por que dois tokens novos se os valores já existem no arquivo. Os hex são idênticos a surface-subtle e a chart-axis vigentes, e isso é proposital: o que muda não é a cor, é a responsabilidade de mantê-la. É o mesmo racional que criou o chart-no-data-hatch na v1.7, e o precedente é literal — a errata E3 provou que papel de desenho sem token próprio acaba tomando emprestado o token de outro papel, e que a troca silenciosa do emprestado quebra o emprestador.

O que a medição de 2026-08-11 (contraste-dp.py) achou, e que motivou a decisão:

  1. chart-grid e chart-no-data têm o MESMO HEX nos dois temas#E3EBF0 no light e #38464F no dark. Consequência: a condição (b) da isenção do 1.4.11 desta seção ("fronteira entre células sustentada por chart-grid") é impossível de cumprir sobre uma célula sem medição — a razão é 1,00, a linha desaparece. No heatmap isso nunca apareceu porque a célula no-data é hachurada e as vizinhas são sequenciais saturadas; num mapa, onde metade do território pode ser "sem medição", o defeito é estrutural.
  2. No tema escuro, chart-axis e chart-no-data-hatch também têm o mesmo hex (#90A6B3). Emprestar chart-axis para a fronteira faria a linha do contorno e a tinta da hachura de "sem medição" serem o mesmo token por acidente — exatamente a estrutura da E3.
  3. Contra o território, as candidatas existentes reprovam o piso de 3:1: chart-grid mede 1,11, border-default 1,37 e border-strong 2,33 no light. Só a tinta adotada passa (3,11).

Alternativas descartadas: (a) consumir surface-subtle e chart-axis diretamente, sem tokens novos — repetiria a estrutura da E3 em dois papéis novos de uma vez; (b) usar chart-grid como fronteira, como a redação original do DP4 previa — reprovado pela medição acima, e a errata E19 do seed-dataviz.md registra a correção; (c) criar um token só, para território e fronteira — são papéis diferentes com pisos diferentes (um é preenchimento, outro é linha que porta informação), e unificá-los devolveria o problema no primeiro supersede.

Consumidor: sub-bloco DP (mapas MG-ES-BA) do seed-dataviz.md — DP3 (os três estados do território) e DP4 (fronteira). O chart-geo-base nunca é usado como "sem medição": ausência de medição continua exclusiva do chart-no-data, sempre hachurado.

Divergente — --seed-chart-div-neg-3…pos-3 (desvio, esperado×medido, variação)#

Vermelho ↔ neutro ↔ turquesa, 7 posições, alinhada por construção à dupla chart-positive/chart-negative da v1.0 (turquesa-500/vermelho-500 são exatamente os stops ±2). Uso canônico imediato: o gráfico do alerta de geração (slot ET5 da F4).

Posição Light (stop) Dark (stop) vs fundo light vs fundo dark Gate 3:1
neg-3 vermelho-700 vermelho-300 7.18 9.25 PASS
neg-2 vermelho-500 vermelho-500 4.30 4.33 PASS
neg-1 vermelho-200 vermelho-800 1.53 1.78 zona-zero
zero cinza-100 cinza-800 1.21 1.91 zona-zero
pos-1 turquesa-200 turquesa-800 1.45 1.99 zona-zero
pos-2 turquesa-500 turquesa-500 3.22 5.77 PASS
pos-3 turquesa-800 turquesa-300 9.37 10.16 PASS

Regra da zona-zero (declarada, não é isenção): as posições ±1 e o neutro representam "perto de zero" — aproximar-se do fundo É a semântica. Consequência dura: dado cuja distinção do fundo é necessária ao entendimento nunca usa sozinho as posições ±1/zero — barra de desvio pequena leva borda chart-axis ou rótulo de valor. As posições plenas (±2, ±3) passam o gate 1.4.11 medido nos dois modos.

Gauge — --seed-gauge-* (monitoramento, medidor)#

Token Light Dark Medição que o aprova
gauge-track cinza-200 cinza-700 trilha de fundo (decorativa em si; o contraste exigido é do valor CONTRA ela)
gauge-value turquesa-600 turquesa-300 3.09 vs track · 4.60 vs branco (light) — 3.58 vs track · 10.16 vs page (dark)
gauge-range-ok = feedback-success-solid (turquesa-600 / turquesa-300) idem value herda as medições acima
gauge-range-warning dourado-600 dourado-300 3.25 vs track · 4.82 vs branco (light) — 3.54 vs track · 10.04 vs page (dark)
gauge-range-critical vermelho-600 vermelho-300 3.49 vs track (light) — 3.26 vs track · 9.25 vs page (dark)

Dois achados de medição desta entrega (o script corrigiu a proposta antes da spec): o warning light nasceu proposto como dourado-500 e reprovou contra a trilha (2.35) — corrigido para dourado-600; o critical dark nasceu vermelho-400 e reprovou (2.38) — corrigido para vermelho-300, coerente com o padrão dark do sistema (stops claros: vermelho-300 já é o div-neg-3 dark). Alternativas descartadas: clarear a trilha para salvar os stops originais (enfraqueceria a trilha contra o fundo) · criar hex novo fora da rampa (proibido pela regra-mãe do §2.1). Faixas de gauge referenciam a taxonomia de feedback existente — nenhuma paralela de severidade nasce aqui (mesma lei do Bloco 3).

SUPERSEDE DM3 (2026-08-10, formalizado na v1.5) — os PAPÉIS do gauge invertem; nenhum hex muda. Medido no sub-bloco DM da F5: as três faixas coloridas (range-ok/warning/ critical) ficam a 1 ponto de claridade entre si no light (46/45/43%) e 0 no dark (75/75/72%) — diferem quase só por matiz, exatamente o que a spec do bullet graph de Stephen Few previu ao mandar codificar faixas em INTENSIDADES, não em matizes. A partir do DM3: as bandas de faixa do medidor são intensidades de cinza (consomem os primitivos cinza-100/200/300 no light e cinza-800/700/600 no dark — distâncias de claridade 9/10/19 e 9/8/17 pontos, medidas), e quem carrega a severidade é a BARRA DE VALOR, que assume gauge-range-ok/warning/critical conforme a faixa em que o valor cai. Os tokens desta tabela permanecem com os mesmos hex — muda o elemento que os consome. As leis de desenho do medidor (anatomia, rótulo de estado, textura DM11) vivem no seed-dataviz.md §DM (DF7). Alternativas descartadas: manter bandas coloridas + texturizar as três (ruído em objeto pequeno) · mudar os hex das faixas (supersede caro, sem necessidade). Fronteira: aliases nomeados gauge-band-* nos gêmeos só nascem quando o produto consumir o medidor (decisão registrada como pendência, não antecipada).

Stroke reforçado da categórica — --seed-chart-cat-N-stroke (traço fino)#

Tabela histórica (v1.3). A coluna "Fill (v1.0)" e os strokes de cat-3/4/5/6 abaixo foram supersedidos pela categórica ESTENDIDA v1.5 (subseção adiante) — os valores vigentes estão lá. Esta tabela permanece como registro do racional que criou a variante -stroke (o mecanismo continua valendo; mudaram os hex de parte das posições).

A remedição de conferência da categórica v1.0 sob o critério de traço fino (linha ≤3px, marcador pequeno — o pior caso do 1.4.11) reprovou cat-1 (2.71), cat-2 (1.85) e cat-5 (2.53) contra branco. A categórica de preenchimento não mudou naquele lote (mudaria depois, na v1.5); nasceu a variante de stroke:

Série Fill (v1.0, inalterado) Stroke light (novo) Stroke light vs branco Stroke dark (novo) Stroke dark vs dark-page
cat-1 turquesa-400 turquesa-600 4.60 turquesa-300 10.16
cat-2 dourado-300 dourado-500 3.49 dourado-300 10.04
cat-3 azul-500 = fill 3.32 azul-300 9.09
cat-4 turquesa-800 = fill 9.37 turquesa-100 15.62
cat-5 cinza-400 cinza-600 4.74 cinza-300 9.72
cat-6 dourado-700 = fill 6.68 dourado-100 15.36

Achado V2 (render de 2026-08-09, ANTES do gate humano): a primeira versão desta tabela definia stroke só para light; o screenshot dark do preview mostrou a cat-4-stroke (turquesa-800) a ~2:1 do fundo escuro — linha quase apagada. Os pares dark acima nasceram dessa reprovação, todos medidos ≥3:1. Dependência declarada: no dark, cat-2 e cat-6 comprimem para stops vizinhos da rampa dourado (300/100) — a distinção mútua dessas duas séries em modo escuro é sustentada pelo tracejado/marcador (1.4.1), nunca só pela cor. Os valores dark do FILL categórico vivem nos gêmeos JSON/CSS da v1.0 (não reproduzidos aqui); a regeneração do §7.0 deve conferi-los contra os strokes desta tabela.

Regra de consumo: gráfico de linha e sparkline usam cat-N-stroke; barra, área e fatia usam cat-N (fill). A regra de acompanhamento da v1.0 permanece intocada e vira lei da F5: cor nunca é o único diferenciador de série — forma de marcador, espessura ou tracejado acompanham (DF3-a do seed-dataviz.md).

Categórica ESTENDIDA — --seed-chart-cat-1…6 (+-stroke) — v1.5, supersede formalestável#

Estado: estável desde 2026-08-11, por "aprovo" explícito do Rafael sobre o lote de formalização da F5 (o gate visual que a aprovou foi o de 2026-08-10, sobre os previews de gráficos v1.2 e de monitoramento v0.7 — ambos reanexados e conferidos por MD5 em 2026-08-11). Consumidor primário e dono das REGRAS de consumo: seed-dataviz.md v0.6 §4.6 (DF7).

O que esta subseção supersede: (a) os valores da categórica v1.0 (fills e strokes, tabela antiga acima e bullet da seção 3); (b) a restrição "nenhum hex novo" que o próprio DT declarou. O que ela NÃO toca: sequencial, no-data, divergente e a regra de consumo fill×stroke — tudo do DT permanece estável como está.

Racional medido do supersede (por que a restrição caiu). Medição de matiz (H) de todos os primitivos do §2.1, feita em 2026-08-10 durante o gate do redesenho DG14–DG17: para DADO a marca tem exatamente 3 matizes livres — turquesa (~170–174°), dourado/amarelo (~36–50°, uma família só de matiz) e azul (~192–197°) — porque o vermelho (~358°) é reservado a feedback-danger/chart-negative (lei do Bloco 3) e o cinza é reservado a "sem dado" (achado do gate do DT, token chart-no-data). Com 3 matizes, qualquer categórica de 6 posições repete família e produz "escalas da mesma cor" — exatamente a crítica do Rafael no gate de 2026-08-10. A resposta consolidada da indústria para este dilema (IBM Carbon, GitLab) é uma paleta estendida específica de dataviz, com matizes que não existem na marca e nunca aparecem em UI. Alternativa descartada com limite honesto declarado: recurar a sequência só com stops existentes — continua sendo 3 matizes revezando; em 6 séries sempre haveria 2 pares da mesma família.

Dois matizes novos, exclusivos de dado. Calibrados na claridade das âncoras SEED (fills light ~49–56% de claridade, como turquesa-500 e azul-500) e aprovados no gate visual de 2026-08-10: magenta 332° e violeta 268°. São 6 hex novos no total (fill light, fill dark e stroke light de cada matiz; no dark o stroke = fill, padrão do DT). Regra dura: esses hex não têm rampa no §2.1 de propósito — não são cor de marca nem de UI; são chart-* e só. Se algum dia um deles aparecer em botão, badge ou superfície, é defeito.

Sequência v1.5 (ordem obrigatória): turquesa → dourado → magenta → azul → violeta → azul-800. As posições 1–5 cobrem 5 famílias de matiz, todas distintas; a 6ª posição é a única que reutiliza família (azul, em claridade distante: 28 pontos da cat-4 no light). A posição 2↔3 foi decidida pelo gate: turquesa e magenta são ambos tons médios saturados e liam parecidos como vizinhos de pilha; o dourado (75% de claridade) entre eles separa por peso, não só por matiz. O cinza saiu da categórica — resolvendo o conflito com a reserva de "sem dado" que a própria v1.0 carregava sem ver (o antigo cat-5 era cinza-400).

Série Família Fill light vs branco Stroke light vs branco Fill dark vs cartão dark Stroke dark
cat-1 turquesa turquesa-500 #00A192 3.22 turquesa-600 #098475 4.60 turquesa-300 #66D1C2 8.50 = fill
cat-2 dourado dourado-300 #F9B11C 1.85 ⚠ (regra abaixo) dourado-500 #B67F00 3.49 dourado-300 #F9B11C 8.40 = fill
cat-3 magenta (novo) #CD518B 4.08 #B23871 5.68 #E8A1C2 7.64 = fill
cat-4 azul azul-500 #0099C1 3.32 = fill 3.32 azul-300 #53C2E9 7.61 = fill
cat-5 violeta (novo) #966AC8 4.04 #7B42BD 6.26 #BD9CE2 6.69 = fill
cat-6 azul (única repetição) azul-800 #004C61 9.52 = fill 9.52 azul-200 #96E0FD 10.66 = fill

Fundos de referência desta tabela (declarados): branco no light; cartão surface-raised dark #1D272D no dark — o palco real do gráfico é o cartão (figure.seed-chart), não a página; é o mesmo referencial da camada de validação do DG.

Mudança do cat-1 (era turquesa-400 #11B0A0, vira turquesa-500 #00A192). Motivo: o redesenho DG14 removeu o contorno das superfícies de dado, então o fill precisa passar 3:1 sozinho contra o fundo — o turquesa-400 media 2.71 e reprovava; o turquesa-500 mede 3.22 e passa. Bônus de coerência: cat-1 fica idêntico ao chart-positive (turquesa-500), que sempre foi o "verde" do dado.

Regra do dourado (a exceção declarada da tabela). O dourado a 1.85 é insolúvel dentro da família: escurecê-lo até 3:1 o transforma em mostarda e mata a cor de trabalho da marca. Regra de consumo: dourado (cat-2) é permitido em área grande COM rótulo direto (a informação não depende da fronteira — mesma lógica que o 1.4.11 comporta) e vetado como fill solitário sem rótulo; em traço fino, vale a variante cat-2-stroke (3.49), como sempre. Guarda de consumo: gráfico de série única nunca nasce em cat-2.

Claridades e espalhamento (o instrumento do DG13, remedido para a v1.5):

Modo cat-1…6 (% claridade) Distância entre vizinhas Trio da empilhada (1×2 · 2×3 · 1×3)
Light 56 · 75 · 49 · 55 · 50 · 27 19 · 26 · 6 · 5 · 23 19 · 26 · 7
Dark 75 · 75 · 71 · 71 · 67 · 84 0 · 4 · 0 · 4 · 17 0 · 4 · 4

Emenda GI2 (registro que faltava à §3c, devido desde o marco v1.7): a rampa categórica ESCURA colapsa em escala de cinza — e isso NÃO é defeito de token. Na paleta antiga, cat-1/2/3 dark mediam 75/75/71% de claridade (duas séries idênticas em P&B); na v1.5 o quadro persiste (75/75/71/71/67). A causa é estrutural: todo fill dark precisa ser CLARO para contrastar com o fundo escuro (todos medem ≥6.69 contra o cartão), e claridade alta comprimida é o preço disso. É este fato que obriga o DG13 (textura por série na interseção escuro+grayscale, lei no seed-dataviz.md): a paleta estendida melhora o colorido, não revoga a textura. Quem lê esta seção isolada precisava saber disso.

Deriva corrigida na formalização (achado de 2026-08-11): os previews aprovados no gate embutiam 5 hex com deriva do canônico (#66D2C2→turquesa-300 real #66D1C2 · #4FC3E8→azul-300 #53C2E9 · #00506F→azul-800 #004C61 · #A8DCEF→azul-200 #96E0FD · #FFD166→dourado-300 #F9B11C no stroke dark da cat-2). Esta seção ancora nos stops reais do §2.1; remedição completa provou que nenhum veredito de gate muda (deltas de claridade ≤2 pontos). Errata aberta contra os previews: alinhar os hex embutidos quando os arquivos forem reanexados/editados.

Texto de gráfico (referência de consumo, não token novo)#

Rótulo/eixo/legenda consomem os tokens de texto existentes, com os pares aprovados para as superfícies de gráfico: cinza-700 sobre branco 6.55 · cinza-600 sobre branco 4.74 (light) · cinza-200 sobre dark-page 12.53 · cinza-300 sobre dark-default 8.92 — todos ≥4.5:1 (1.4.3).

--seed-{grupo}-{variação} para semânticos, --seed-{cor}-{stop} para primitivos. Prefixo seed evita colisão com Tailwind/shadcn/bibliotecas nos produtos. No Tailwind v4 dos produtos Lovable, os semânticos entram via @theme mapeando para estes nomes (guia de integração será entregue na Fase 3 junto dos componentes).

Esc