Ir ao conteúdo
SEED engenhariaDesign System

Dataviz

4d. Sub-bloco DP — mapas de atuação MG-ES-BA

seed-dataviz.md v0.22 · §04dseção 9 de 1204d-sub-bloco-dp-mapas-de-atuacao-mg-es-ba-dp1-dp14.md · MD5 517d7342

Título completo no canon: Sub-bloco DP — mapas de atuação MG-ES-BA (DP1–DP14)

Estado: estável desde 2026-08-11, e SEM PENDÊNCIAS ABERTAS desde o mesmo dia. O consolidado de decisões foi aprovado pelo Rafael ("aprovo" explícito sobre DP1–DP14) e a promoção veio depois do gate visual sobre o preview. As seis pendências nominais que o sub-bloco abriu — DP-P1 a DP-P6fecharam todas: as três primeiras por medição de contraste e de forma; as três últimas quando a malha oficial do IBGE, edição 2025, entrou no lugar da malha sintética. O gate visual sobre o preview v0.4, já com a geografia real, foi aprovado em 2026-08-11. Fronteira honesta do que o gate cobriu, registrada porque a diferença importa: o Rafael inspecionou visualmente o preview v0.2 e respondeu os cinco pontos do protocolo (formas legíveis em escala de cinza · fronteira visível no tema escuro · malha completa ilegível a 360px · impressão correta · malha sintética aceita). A v0.3 difere da v0.2 em um único ponto — a tinta da contagem de agrupamento, corrigida pelo DG12 —, verificada por medição de contraste e por inspeção de captura de render, e aprovada por ele sobre esse relato. DP = sub-bloco de mapas da Fase 5; é o último dos seis (DF · DT · DG · DM · DI · DP) e o seu fechamento dispara o marco da fase.

Por que este sub-bloco tem insumo que nenhum outro teve. DF, DT, DG, DM e DI operam sobre geometria que o Design System inventa (uma barra tem a altura que o dado mandar). O DP opera sobre geometria geográfica real: o contorno de Minas Gerais não é decisão de design, é um dado externo, com fonte, licença, data de publicação e erro declarado. Isso põe no sub-bloco duas classes de decisão que os outros não tiveram — de onde vem a forma (DP8, DP9) e como ela é achatada num plano (DP7).

4d.0 Escopo, decidido em briefing com o Rafael antes de qualquer pesquisa#

As seis perguntas de escopo foram feitas e respondidas em 2026-08-11, antes da primeira rodada de pesquisa, exatamente porque nenhuma delas é derivável do canônico — todas dependem do uso real da empresa. Fato (respostas do Rafael), não inferência:

# Pergunta Resposta
a Obras como pontos ou municípios pintados por intensidade (coropleto)? Pontos. O coropleto fica escrito na spec como caminho pronto, sem ser implementado agora
b Onde o mapa aparece? Nos três destinos: laudo/proposta impressa, ERP (tela) e site institucional
c Zoom/pan/tooltip ou figura fixa? Figura fixa como norma; tooltip permitido no ERP como enriquecimento
d Quantos níveis geográficos? Estado + município + ponto. O Rafael recusou o recorte de dois níveis: "eu tenho que ter todos os municípios" — o território do estado nunca aparece recortado, e a seleção incide sobre a linha de fronteira, não sobre o território
e Carrega dado de cliente identificável? Sim no ERP; não em peça externa — vira regra dura (DP12)
f Fonte de malha já em uso na empresa? Não há. Decisão livre (DP8)

Glossário mínimo, porque o vocabulário de cartografia não aparece em nenhum outro arquivo deste sistema:

  • Malha — o arquivo com as coordenadas que desenham os contornos (estados, municípios).
  • Coropleto — mapa em que cada região é preenchida com uma cor que representa um número.
  • Marcador — o símbolo que marca um ponto (uma obra) sobre o mapa.
  • Projeção — a regra matemática que achata a superfície curva da Terra num plano. Toda projeção deforma alguma coisa; escolher a projeção é escolher o que deformar.
  • Simplificação — reduzir o número de pontos de um contorno para o arquivo caber na web, aceitando perda de detalhe.
  • TopoJSON / GeoJSON — formatos de arquivo de geometria. TopoJSON é a variante compacta, que armazena fronteiras compartilhadas uma única vez em vez de duas.
  • SIRGAS 2000 — o sistema geodésico de referência oficial brasileiro; define a partir de que modelo da Terra as coordenadas são medidas.

O DP entrega DIRETRIZ DE MAPA. Não orquestra tela (isso é Fase 6), não implementa comportamento dependente de dado vivo (isso é produto — Lovable/Supabase, mesma fronteira do DM10), e não vira SIG/GIS: não faz análise espacial, não calcula rota, não mede distância.


4d.1 DP1 — Um mapa é um gráfico: herda o DG1 inteiro, e o fallback textual é o mapa#

Decisão: todo mapa SEED é um <figure> com as cinco partes do DG1 (§4.1): título em figcaption, descrição curta, fallback textual sempre presente, legenda, e a área com role="img" + aria-labelledby. O fallback textual de um mapa é uma tabela município → obras, com as colunas: Município · UF · Tipo de solução · Quantidade. Em destino interno acrescenta-se a coluna de identificação permitida pelo DP12; em destino externo, nunca.

Racional: o W3C classifica gráfico como imagem complexa e exige alternativa textual em duas partes, e a orientação específica para mapas vai além do que vale para um gráfico comum — ela pede, além da tabela, navegação alternativa por lista de localidades, porque num mapa a informação é onde, e "onde" não se lê por varredura de eixo. Num mapa da SEED a lista de municípios é o mapa para quem não o enxerga. E é também o que sobra quando o laudo é lido em preto e branco, ou quando o PDF é aberto num leitor que não renderiza SVG.

Alternativa descartada: alt textual curto como cumprimento do 1.1.1. Insuficiente para imagem complexa — a mesma razão já registrada no DG1, agravada aqui: um alt que diz "mapa de atuação da SEED em MG, ES e BA" identifica o objeto e não entrega nenhum dado.


4d.2 DP2 — Consumidor técnico: SVG projetado sobre d3-geo; mapa de tiles é VETADO#

Decisão: o mapa canônico da SEED é SVG projetado, gerado por d3-geo + topojson-client. O invólucro react-simple-maps é permitido (é um wrapper fino sobre exatamente essas duas dependências, com API declarativa), mas o que o Design System exige é a camada de baixo — para que a diretriz sobreviva ao abandono do wrapper. Mapa de tiles (Leaflet, MapLibre, Google Maps, Mapbox) é vetado dentro do escopo do DS.

Racional do veto, com três motivos independentes:

  1. Identidade. Tile traz base cartográfica de terceiro, com estética própria — ruas, pontos de interesse, tipografia alheia. O mapa deixa de ser uma peça SEED e passa a ser uma captura de tela do produto de outra empresa com uns pinos por cima.
  2. Impressão. Tile é imagem raster carregada por rede. Num PDF de laudo vira mancha, e sob a regra do DI4 (§4c.4) nada disso é superfície de dado protegida.
  3. Custo de render. A abordagem de tiles paga custo de performance na renderização durante pan e zoom, ao contrário do SVG — e nós nem usamos pan e zoom (DP13).

Alternativa descartada: D3 puro sem wrapper — é o que o DF2 já descartou para os gráficos core ("poder máximo que os tipos core não exigem"). Aqui a decisão é diferente por um motivo declarado: mapa não tem equivalente ao shadcn Chart, então a camada d3-geo é obrigatória de qualquer forma; o que é opcional é o wrapper acima dela.

EMENDA FORMAL AO DF2 (§2), nascida neste sub-bloco. O DF2 declara o consumidor canônico web como shadcn Chart sobre Recharts v3. Recharts não desenha mapa — não há componente geográfico na biblioteca. O DF2 permanece vigente para os sete tipos core, o monitoramento e o que vier deles; a família mapa consome outra cadeia, declarada neste DP2. Isso não é supersede do DF2: é o preenchimento de uma lacuna que ele tinha sem saber, porque foi escrito quando mapa ainda não era escopo. Registro no §6.


4d.3 DP3 — Num mapa existem TRÊS cinzas, e cada um precisa de papel declarado#

Esta é a decisão mais importante do sub-bloco, porque é onde a regra com mais reincidências do projeto — posição categórica nunca serve de neutro (erratas E3, E14, E15) — tem a maior superfície de erro. Num gráfico de barras existem duas coisas cinzas ("sem dado" e "contexto"). Num mapa existem três, e as três parecem a mesma mancha:

Estado do território Significado Tinta
Contexto não é objeto de medição (o resto do estado) chart-geo-base — token próprio, novo na v1.8 dos gêmeos
Sem medição é objeto de medição e não temos o dado chart-no-data + hachura diagonal a 45° em chart-no-data-hatch, obrigatória
Com dado medido escala sequencial (§3c) — no coropleto do DP14

Regra dura: nenhum dos três consome cat-N. Nunca. Território não é série.

Racional do caso perigoso — o do meio. Sem a hachura, "não medimos aqui" e "aqui não interessa" viram a mesma mancha cinza, e a diferença entre as duas afirmações, num laudo de engenharia, é a diferença entre lacuna declarada e território fora do escopo. É exatamente a estrutura do erro da errata E3, transposta para outra forma: um papel de desenho existindo sem token próprio e tomando emprestado o de outro papel. A hachura a 45° permanece exclusiva do chart-no-data (§4.4), e a tinta dela é o chart-no-data-hatch (v1.7 dos gêmeos), nunca chart-axis e nunca cat-N-stroke.

DP-P1 FECHADA na v0.15, por medição. O instrumento é o contraste-dp.py v1, que extrai os hex do seed-tokens.css canônico em vez de digitá-los (lição das erratas E4/E16). Veredito: nasce o token chart-geo-base (#F2F6F9 light / #141D23 dark), com papel próprio, na v1.8 dos três gêmeos. Por que token novo se o valor já existe (é idêntico ao surface-subtle vigente): o que muda não é a cor, é a responsabilidade de mantê-la — mesmo racional que criou o chart-no-data-hatch na v1.7 depois da errata E3, que provou que papel de desenho sem token próprio acaba tomando emprestado o de outro papel. Alternativa descartada: consumir surface-subtle diretamente — repetiria a estrutura da E3 num papel novo. Medições completas na §3c do seed-tokens.md v1.8.


4d.4 DP4 — Fronteira no mapa: PRECISÃO DE ESCOPO do DG14, não supersede#

Decisão: o DG14 (§4.6) determina que superfície de dado não leva contorno, e resolve a separação entre vizinhos por vão de 2px na cor do cartão — espaço negativo, fronteira por geometria e não por contraste. Isso não se aplica ao território, porque território é contíguo: não existe vão entre Governador Valadares e Alpercata sem que se invente um. No mapa vale o princípio da condição (b) da §3c do seed-tokens.md, já estável desde o sub-bloco DT e escrita junto com a isenção do WCAG 1.4.11 para heatmap — a fronteira entre regiões é desenhada, nunca deixada por conta da diferença de cor. A tinta, porém, não é a que aquela condição nomeia. Ver a errata E19 logo abaixo: a fronteira do mapa consome chart-geo-boundary (#788F9D light / #90A6B3 dark, token novo na v1.8), não chart-grid.

ERRATA E19 — contra a redação original do DP4 na v0.14 (nascida e corrigida no mesmo dia). A v0.14 mandava a fronteira consumir chart-grid, por leitura direta da condição (b) da §3c. A medição do contraste-dp.py derrubou: chart-grid e chart-no-data têm o MESMO HEX nos dois temas#E3EBF0 no light e #38464F no dark. Sobre um município sem medição a fronteira mede 1,00 contra o preenchimento: ela desaparece. Contra o território de contexto ela mede 1,11, também muito abaixo do piso de 3:1. Por que o defeito nunca apareceu no heatmap, que é o consumidor para o qual a condição (b) foi escrita: lá a célula sem medição é hachurada e as vizinhas são sequenciais saturadas, de modo que a fronteira nunca precisa separar dois cinzas. Num mapa, onde metade do território pode ser "sem medição", separar dois cinzas é o caso normal. Candidatas medidas contra o território de contexto no light: chart-grid 1,11 · border-default 1,37 · border-strong 2,33 · a tinta adotada 3,11 — única a passar. No dark a adotada mede 6,74. Por que não emprestar chart-axis, que tem o mesmo valor: no tema escuro chart-axis é o mesmo hex do chart-no-data-hatch (#90A6B3). Emprestar faria a linha da fronteira e a tinta da hachura de "sem medição" serem o mesmo token por acidente — literalmente a estrutura da errata E3, num arquivo que a registra três vezes. Classe de defeito: regra herdada de outro consumidor sem remedir o novo contexto. É parente da E7 (herdar um número medido antes de um supersede de paleta).

Consequência: o DG14 permanece intacto e ganha escopo declarado — vale onde a superfície de dado é separável por espaço negativo (barra, segmento de pilha, fatia, área). Onde a geometria é contígua (mapa, heatmap), a fronteira é desenhada e consome chart-grid.

E19-b — EXCEÇÃO DECLARADA POR VEREDITO (2026-08-24, gate F7.7-P1, saída (a): "aceito sua sugestao, A"). O porte da camada de validação revelou o que a E19 não havia medido: no tema claro a tinta adotada mede 2,80 sobre o sem-medição (chart-no-data/surface-sunken, #E3EBF0) — abaixo do piso 3,0 que ela cumpre sobre o contexto (3,11). A razão é do PAR, não da tinta: o mesmo ci-500 sobre um fundo um degrau mais escuro rende menos. A casa decidiu ACEITAR como exceção declarada, porque a hachura já é o segundo separador da região (a SC 1.4.11 só cobra o par quando ele é o ÚNICO identificador) — mesma lógica da isenção do heatmap na §3c. O mesmo veredito cobre o cat-2-stroke × sunken (2,89), cujo segundo portador é a FORMA (E20). Alternativas medidas e descartadas no gate: ci-600 passa todos os pares (4,37/3,93) mas colide em valor com a tinta da hachura (#617683) — a estrutura E3 que esta própria errata usou para recusar o chart-axis; ci-700 passa com folga (6,03/5,43) sem colisão, mas dobra o peso do traço num desenho aprovado — recusada pelo custo visual. No tema ESCURO nada disso se aplica (a adotada mede 3,84–7,35). A exceção vive como código no contraste-dp.py (categoria própria [exceção], com o número IMPRESSO a cada execução para a decisão poder ser re-julgada); placar do sub-bloco: 27 PASS · 0 FAIL · 3 exceções por veredito.

Fronteira honesta do alcance, medida na prova visual de 2026-08-24: HOJE o par não é consumido por artefato nenhum — o único mapa com sem-medição é a demo do coropleto, e ela não desenha fronteira (pendência nova DP-P7). O par passa a ser real no momento em que o coropleto for ligado com dado real, porque aí o DP4 obriga a fronteira. Ou seja: a exceção não perdoa uma dívida existente — ela DESTRAVA o conserto do DP-P7, que sem ela nasceria com dois FAIL. Provado no navegador real, lupa 12× por captura em escala 1:1: com 2,80 a fronteira SEPARA os municípios sem medição e mantém a discrição que a E19 escolheu.

Alternativa descartada, com o racional que a derruba: erodir cada polígono para fabricar o vão de 2px, que seria a leitura literal do DG14. É geometricamente possível e foi considerada. Cai por dois defeitos medíveis: (i) em municípios estreitos a erosão de 2px por lado consome a própria área, e o polígono some ou vira filete; (ii) onde não há vizinho — na borda externa do estado — a erosão abre uma canaleta clara contra o fundo, inventando uma fronteira que não existe. Um mapa que desenha limite onde não há limite é pior que um mapa sem contorno.

Fato vs. inferência: que a §3c exige a fronteira desenhada é fato (texto vigente e estável). Que a tinta dela no mapa é o chart-geo-boundary e não o chart-grid também é fato medido desde a v0.15 (E19). O que permanece não medido é a largura mínima de renderização da variante malha completa — pendência DP-P2, que é geometria e não cor.


4d.5 DP5 — Duas variantes de malha, e a segunda tem trava de largura#

Decisão: o território do estado aparece sempre inteiro, sem recorte. O que varia é quais fronteiras municipais são desenhadas:

  • Variante BASE — padrão nos três destinos. Silhueta completa do estado; fronteira desenhada apenas nos municípios com obra. Traço: estrutura, 1px, em chart-grid.
  • Variante MALHA COMPLETA — todas as fronteiras municipais desenhadas em apoio, 0,5px. Permitida somente no ERP e acima de uma largura mínima de renderização a medir. Vetada a 360px e em figura pequena de papel.

Racional: MG tem 853 municípios, BA 417 e ES 78 — 1.348 polígonos. Desenhar 1.348 fronteiras numa figura que precisa caber num A4 de proposta e num celular de 360px não informa: vira uma textura cinza uniforme, e o marcador da obra — que é o dado — se perde dentro dela. A fronteira só ajuda quem já sabe qual município procurar, e o leitor de uma proposta não sabe. A variante base inverte isso: a linha aparece onde há informação, e por isso a linha é informação.

Achado colateral que esta decisão resolve: o §4c.3 registrou que o piso de 0,5px não tem consumidor — a grade do preview do DG está toda em 1px — e que "valor que existe na lei sem ser exercido deriva", deixando a verificação para a Fase 6. A fronteira municipal da variante completa é o primeiro consumidor real do 0,5px.

Fronteira do instrumento, herdada do DI6 e registrada de propósito: a folha de prova impressa mediu sobrevivência da linha de 0,5px (a impressora consegue depositá-la?), não adequação dela aplicada num desenho. A largura mínima da variante completa é medição de adequação e é pendência nominal DP-P2.

Alternativa descartada: malha municipal completa e permanente em todos os destinos — pedida no briefing e revista na mesma conversa. Cai por legibilidade, não por peso de arquivo: mesmo simplificada e leve, ela piora o mapa nos três destinos, e piora mais no menor deles.


4d.6 DP6 — O piso de claridade NÃO se herda para polígono de município#

Decisão: o piso de 6 pontos percentuais de espalhamento de claridade — o número que decide quando duas superfícies adjacentes se distinguem — não vale para polígono de município, e não será herdado. Fica declarado como calibração pendente, a pagar quando o coropleto (DP14) existir com dado real.

Racional, que é aplicação direta da regra vigente e não decisão nova: o supersede de 2026-08-11 (§4c.3 e §6) estabeleceu que o piso é calibrado por FORMA de apresentação e vale para aquela forma em qualquer meio — e que forma nova exige recalibração por gate mesmo no meio de sempre. Polígono de município é forma nova por três atributos simultâneos, nenhum deles presente na forma em que o piso foi calibrado (barras altas adjacentes): é irregular, tem área muito variável (dois vizinhos podem diferir em uma ordem de grandeza) e tem vizinhança imprevisível (um município pode tocar dois ou onze outros).

Por que não calibrar agora: calibrar piso exige medir contra caso real. Sem dado por município, o caso seria inventado — e um piso calibrado contra exemplo inventado é pior que piso ausente, porque parece medição. Precedente direto: o contraste-dg.py v1 media três das seis séries, dava verde, e o verde impediu a procura por dois sub-blocos.

Pendência nominal DP-P3.


4d.7 DP7 — Projeção: cônica EQUIVALENTE. Mercator é vetado#

Decisão: o mapa SEED usa projeção cônica equivalente (Albers) — em d3-geo, geoConicEqualArea com paralelos padrão calculados para o recorte MG-ES-BA. Datum de referência: SIRGAS 2000, que é o que a malha de origem já traz (DP8). Mercator, em qualquer variante, é vetado.

Racional: um coropleto compara áreas pintadas; se a projeção deforma área, o polígono mente sobre o dado antes de qualquer cor entrar. A orientação técnica é explícita: ao mapear valores num coropleto, usa-se projeção equivalente para que as áreas fiquem corretas umas em relação às outras. A projeção de Albers é cônica equivalente com dois paralelos padrão e é a usada no Brasil pelo IBGE; a referência técnica do próprio IBGE recomenda, para cálculo de área no país inteiro, os parâmetros longitude de origem -54°, latitude de origem -12°, paralelos padrão -2° e -22°.

Racional do veto ao Mercator, com o número que o decide: Mercator é o padrão de fato de todo tutorial de mapa em React e de toda biblioteca de tiles, e deforma área em função da latitude. Nosso recorte vai de aproximadamente -8° (norte da Bahia) a -22° (sul de Minas). A deformação seria sistemática e direcional, inflando a Bahia contra Minas — num mapa de atuação, isso é mentira visual da empresa sobre si mesma, e ela cresce justamente no estado onde a SEED tem a operação mais recente.

Fronteira declarada: os parâmetros do IBGE citados acima são calibrados para o Brasil inteiro. Para o recorte MG-ES-BA os paralelos padrão devem ser recalculados, por script, com o valor resultante declarado no arquivo canônico e no asset. Pendência nominal DP-P4.

Alternativa descartada: projeção Policônica, usada pelo IBGE no mapeamento oficial em escala geográfica. Cai porque não é equivalente nem conforme — só se aproxima disso perto do meridiano central — e o DP precisa da propriedade de área preservada de forma garantida, não aproximada.


4d.8 DP8 — Malha: IBGE, com o ANO declarado, versionada como asset do DS#

Decisão: a fonte da geometria é a Malha Municipal Digital (MMD) do IBGE, publicada em Shapefile e agrupada por estado, com SIRGAS 2000 e codificação UTF-8. É convertida por script para TopoJSON e versionada como asset do próprio Design System — não como dependência de runtime instalada no ERP.

Duas advertências do próprio IBGE entram no canônico, porque num laudo de engenharia elas importam mais que a estética:

  1. Os limites da MMD devem ser entendidos como aproximados, e o IBGE se isenta de responsabilidade por usos que não sejam a compilação de dados estatísticos.
  2. O IBGE não tem atribuição legal para definição e demarcação de limites territoriais.

Consequência dura, que precisa estar escrita e não apenas sabida: o mapa da SEED não serve como peça de definição de limite territorial. Serve para localizar obra e comunicar atuação. Se um dia um documento da empresa precisar afirmar de que município é um ponto para efeito legal ou regulatório, a fonte é a documentação do imóvel e da concessionária — não este mapa.

Terceira consequência, operacional: a MMD é republicada anualmente, e municípios mudam de limite entre publicações. O asset declara o ano no nome do arquivo e no MANIFESTO. Sem isso, dois mapas da empresa produzidos com seis meses de diferença podem discordar sem que ninguém saiba por quê — a classe de defeito "artefato que mente sobre si mesmo" já custou uma nota permanente no §3.1 do MANIFESTO.md.

Alternativas descartadas:

  • Pacote npm de malha brasileira. O desenho poderia mudar numa atualização de dependência, sem pedido e sem gate — exatamente o risco que o DF7 existe para evitar (tokens de dado têm uma fonte). Malha é geometria de dado; o argumento é o mesmo.
  • Base comercial editável (mapas de município vendidos como objeto de PowerPoint). Existem e custam por estado. Caem porque devolvem geometria digitada/desenhada no lugar de geometria calculada, contra a regra de método do projeto, e porque a licença de redistribuição num PDF de cliente teria de ser auditada peça a peça.
  • Serviço de mapa hospedado (Google/Mapbox). Já vetado no DP2 por identidade e impressão; soma-se aqui o custo por carregamento e a dependência de rede num documento que precisa funcionar off-line.

4d.9 DP9 — Simplificação por script, tolerância declarada, dois níveis de asset#

Decisão: a malha é simplificada por script (algoritmo de Visvalingam, via mapshaper), com tolerância declarada no arquivo, e o asset é publicado em dois níveis de resolução:

  • Nível FIGURA — para o laudo, a proposta e o site; otimizado para larguras pequenas e para impressão a 300 dpi.
  • Nível ERP — mais detalhado, para telas grandes e para a variante malha completa (DP5).

Racional: a malha municipal cheia dos três estados é inviável na web por peso, e simplificar "no olho" produz um desenho que ninguém consegue reproduzir. Regra herdada e não negociável do projeto: geometria é calculada por script, nunca digitada, e o script leva asserção que falha se qualquer rótulo estourar o viewBox — o defeito de 9px do DM nasceu exatamente da ausência dessa asserção.

Pendência nominal DP-P5: qual tolerância. Isso é gate, não pesquisa — a medição é ver o desenho quebrar: o valor certo é o maior que ainda preserva a silhueta reconhecível do estado e a identidade dos municípios de fronteira recortada.

Alternativa descartada: um único nível de asset servindo os três destinos. Cai porque os requisitos são opostos — o que sobrevive a 300 dpi no papel é pesado demais para o site, e o que é leve o bastante para o site perde detalhe visível na impressão.


4d.10 DP10 — Marcador: cor até 3 categorias, FORMA acima disso. Textura não se aplica#

Decisão (REESCRITA na v0.15 pela medição — ver errata E20): a categoria de um marcador (tipo de solução: fotovoltaico, subestação, GMG, projeto elétrico, consultoria) é codificada pela FORMA, sempre; a cor é redundância, nunca o portador. Vocabulário de três posições, e o teto é 3 categorias por mapa:

Posição Forma
1 círculo
2 quadrado
3 triângulo

Teto de 3 categorias por mapa. Acima disso, o mapa se reestrutura: um mapa por tipo de solução (facetas), ou destaque × contexto no padrão do DG17.

Paleta do marcador: cat-1 (turquesa) · cat-3 (magenta) · cat-4 (azul). O dourado (cat-2) fica de fora, e isso não é regra nova: a regra do dourado da §3c já o veta como fill solitário sem rótulo direto, e um marcador de mapa é precisamente um preenchimento pequeno e solitário. Medido: cat-2 contra o território mede 1,54–1,85 no light.

O marcador leva contorno na variante cat-N-stroke. Não é ornamento: o fill sozinho reprova o piso de 3:1 contra o território no light — cat-1 mede 2,97 e cat-4 3,05. Com o contorno: 4,23 · 5,23 · 3,05. A variante cat-N-stroke existe no sistema exatamente para isto, e a descrição dela nos gêmeos já nomeia o caso: "traço fino (linha ≤3px, marcador pequeno — o pior caso do 1.4.11)". Isto não contraria o DG14, que trata de superfícies adjacentes separáveis por espaço negativo; o marcador é objeto solto sobre o território.

ERRATA E20 — contra a redação original do DP10 na v0.14. A v0.14 dizia "cor até 3 categorias; acima de 3, forma", e descartava explicitamente a redundância cor+forma desde a primeira categoria, alegando ruído. A medição inverte a decisão. Espalhamento de claridade entre os marcadores, que é a métrica certa para distinguir superfícies (§4.4):

Par Light Dark
cat-1 × cat-3 6,8 pontos 3,6
cat-1 × cat-4 0,9 3,7
cat-3 × cat-4 6,0 pontos 0,2

Piso de 6 pontos (calibrado pelo gate, não derivado de norma). No tema escuro as três cores colapsam — 0,2 a 3,7 pontos —, e mesmo no light o par cat-1 × cat-4 mede 0,9. Como o mapa vai obrigatoriamente para impressão (mono é grayscale por definição) e para o ERP (que tem tema escuro), não existe cenário em que a cor sustente a categoria sozinha. Logo a forma não é o plano B: é o portador. A alternativa que a v0.14 descartou por "ruído" era a correta, e o que a derrubou foi eu ter raciocinado em vez de medir — o mesmo erro registrado no §7 da v0.11 ("não diagnostique por raciocínio: meça"). Consequência sobre o gatilho: em mapa não há gatilho condicional de forma como há para a textura (DI2). A forma é permanente a partir da 2ª categoria; com uma única categoria o marcador é círculo e não há o que distinguir.

Racional, e este é o único ponto do DP que inventa vocabulário em vez de herdar. O DI2 (§4c.2) manda texturizar por série quando grayscale ∩ (escuro OU ≥4 séries). A regra é boa e permanece vigente — mas o veículo dela não existe aqui. Textura precisa de área para ser lida: quadriculado, pontilhado ou linhas verticais dentro de um marcador de 8–12px não produzem padrão, produzem sujeira, e em impressão a laser ou fotocópia produzem um borrão. O DI2 não é contrariado; ele é atendido por outro vocabulário, porque a forma de apresentação mudou — que é precisamente a lógica do supersede da regra do piso (§4c.3): o instrumento vale para a forma em que foi calibrado.

Consequência que é melhor descobrir agora: o teto útil de categorias num mapa é 3, e não os 6 da categórica estendida. Um mapa da SEED não consegue mostrar os cinco pilares da empresa como cinco marcadores distintos e continuar legível em escala de cinza. Isso é restrição real e está declarada.

Alternativas descartadas:

  • Reduzir a hachura proporcionalmente ao tamanho do marcador. É a mesma armadilha já rejeitada na extensão do vocabulário de textura (§4.4): a distinção viraria densidade, frágil no papel e pior ainda em fotocópia.
  • Losango, estrela e cruz como 4ª, 5ª e 6ª formas. Caem porque perdem identidade a 8–12px: losango lê como quadrado girado e estrela lê como mancha. Círculo, quadrado e triângulo diferem em número de vértices, que é o atributo que sobrevive à redução.
  • Cor + forma redundantes desde a 1ª categoria. Esta alternativa foi descartada na v0.14 e READMITIDA na v0.15 como a decisão vigente — a medição mostrou que a premissa do descarte ("com uma ou duas categorias a cor resolve sozinha nos dois temas") é falsa: no dark os pares medem 0,2 a 3,7 pontos de claridade. Registro mantido à vista de propósito, porque descarte errado que some do arquivo volta a ser proposto.
  • Codificar a categoria pelo TAMANHO do marcador. Cai porque tamanho já tem dono declarado (magnitude, ver regra de tamanho abaixo), e um atributo com dois donos é a estrutura do defeito que o DM3 corrigiu no medidor.

Regra de tamanho: o marcador tem um papel de tamanho por vez. Se o tamanho carrega magnitude (potência instalada, por exemplo), ele não carrega também contagem de agrupamento (DP11) no mesmo mapa. Alvo de toque: no ERP, a área clicável do marcador é de no mínimo 44×44px, independentemente do tamanho desenhado — o marcador visual pode ter 12px com área de toque invisível maior.


4d.11 DP11 — Agrupamento, colisão e o halo#

Decisão: município com mais de uma obra exibe um marcador com contagem numérica, não vários pinos sobrepostos. O marcador leva halo na cor do fundo do território — o mesmo mecanismo de espaço negativo do DG14.

Racional: pinos empilhados em município pequeno viram uma mancha cuja área não significa nada, e a contagem que o leitor tentaria fazer visualmente estaria errada. O halo é legítimo aqui — e não contraria o DG14 — porque o marcador é um objeto solto sobre o território, não uma superfície adjacente a outra superfície de dado: existe espaço para o vão, que é exatamente a condição que o DP4 declarou faltar entre municípios.

A contagem exata vive no fallback textual do DP1. O número no marcador é conveniência de leitura; a tabela é a fonte.


4d.12 DP12 — LGPD: destino externo e destino interno são mapas diferentes#

Decisão:

  • Destino externo (site institucional, proposta comercial, material de marketing, qualquer peça que sai da empresa): o marcador comunica município + tipo de solução + faixa de porte. Nunca nome de cliente, nunca número de unidade consumidora (UC), nunca endereço, nunca razão social.
  • Destino interno (ERP, atrás de autenticação): identificação permitida. A responsabilidade passa a ser do controle de acesso, não do desenho.

Racional: um pino rotulado com o nome do cliente num mapa de atuação exibido a um terceiro expõe a carteira da empresa a quem não deveria vê-la, e o dado é pessoal identificável quando o cliente é pessoa física ou produtor rural — o que é o caso comum na carteira de irrigantes. Aqui a questão é de conformidade antes de ser de design, e o custo de errar não é estético.

Regra de fechamento, sem a qual a anterior não vale nada: o fallback textual do DP1 obedece à mesma separação. Não adianta omitir o nome no mapa e vazá-lo na tabela ao lado — e a tabela é justamente a parte que é copiada, exportada e colada em outro documento.


4d.13 DP13 — Impresso e interação#

Impresso — herança direta do sub-bloco DI, sem regra nova:

  • DI4: nenhuma informação do mapa pode viver em background-color de CSS. Território, fronteira e marcador são <path>/<rect>/<circle> com fill/stroke de SVG. Medido no DI: sob impressão econômica, o background de CSS some e o fill de SVG sobrevive.
  • DI5: break-inside: avoid no <figure> inteiro — o mapa e a sua legenda nunca se partem entre páginas. Proteger o bloco atômico, nunca o contêiner que o agrupa (E18).
  • @page declara a orientação. Um mapa dos três estados é mais alto que largo; se a figura pedir paisagem, a orientação vai em CSS. Precedente registrado: uma rodada de prova saiu em paisagem por opção herdada do driver e gerou 11 páginas no lugar de 6.
  • vector-effect: non-scaling-stroke aplicado por seletor universal (.plot svg *), nunca em <g> — a propriedade não é herdada em SVG 2 (errata E17). Num mapa isso é crítico: o viewBox de um mapa escala muito mais que o de um gráfico de barras, e sem o atributo a hierarquia de traço de 1px e 0,5px do DP5 é destruída pelo layout responsivo.

Interação:

  • Figura fixa é a norma. O mapa completo não depende de nenhuma interação para ser lido.
  • Tooltip é permitido no ERP como enriquecimento e nunca como portador único de informação. Mesma lei do DG1: tooltip não existe no papel, e o que só vive nele não existe no laudo.
  • Zoom e pan estão FORA do escopo do DP. São comportamento de tela, logo produto — mesma fronteira que já separou tempo real e websocket no DM10.
  • Teclado: herda o DG2 — o mapa inteiro é um tab-stop. O caminho de acesso real é a lista/tabela de municípios do DP1, não a navegação por marcadores.

4d.14 DP14 — O coropleto fica ESCRITO, não implementado#

Decisão: o coropleto (mapa com municípios preenchidos por intensidade de cor) não é implementado neste sub-bloco, mas fica especificado ao ponto de quem o implementar não precisar tomar nenhuma decisão nova de design. O que já está decidido e vale quando ele for ligado:

Questão Já decidido em
Escala de cor §3c do seed-tokens.md — sequencial chart-seq-1…7, 100→900 no light e 800→100 no dark. A §3c já nomeia "mapa coroplético" como consumidor desde o DT
Condições obrigatórias da isenção 1.4.11 §3c: (a) valor acessível por rótulo, tooltip ou tabela-fallback · (b) fronteira por chart-grid · (c) legenda com os limites numéricos das classes
Fronteira entre polígonos DP4
Papel dos três estados do território DP3
Projeção equivalente DP7
Malha municipal completa e simplificação DP8, DP9
Piso de claridade DP6 — pendente de calibração por gate

Racional de não implementar agora: o coropleto pinta um número por município. A empresa não tem hoje esse número organizado para os 1.348 municípios dos três estados, e um coropleto sem dado real pinta ar. Implementá-lo agora custaria a calibração de piso do DP6 — que só pode ser feita contra caso real — para produzir um artefato que ninguém consegue alimentar.

Alternativa descartada: entregar ponto e coropleto em camadas sobrepostas desde já. Cai por custo desproporcional: o marcador teria de ser legível por cima de sete tons de fundo diferentes nos dois temas, o que é o pior caso de contraste do sistema inteiro, e obrigaria a resolver dois problemas novos ao mesmo tempo — sem que o dado do coropleto exista.


4d.14b DP15 — Ilhas oceânicas saem do DESENHO, nunca do dado#

Decisão (2026-08-11, aprovada pelo Rafael): o arquipélago de Trindade e Martim Vaz, administrativamente parte do município de Vitória (ES) e a cerca de 1.100 km da costa, é recortado do desenho do mapa. O município de Vitória permanece no mapa, na tabela e em qualquer agregação — o que sai é somente a geometria das ilhas.

Medição que motivou: com as ilhas, a extensão de longitude do recorte vai a 22,20°; sem elas, a 13,70°. São 8,5° de oceano vazio — cerca de 40% da largura da figura sem informação nenhuma, com os três estados espremidos no canto. A variante malha completa do DP5 deixaria de funcionar e a leitura a 360px ficaria inviável. 5 anéis removidos, 901 vértices, nenhum município removido.

Regra operacional: o corte é por longitude declarada (-35°), valor que cai no vazio entre o litoral continental do ES (≈ -39,7°) e o arquipélago (≈ -29,5°) — não há ambiguidade possível.

Alternativa descartada: inset com quebra de escala, no padrão que os atlas usam para Alasca e Havaí. Exigiria um componente novo — moldura, escala própria, marca de descontinuidade — que o DP não especifica. Fica registrada como caminho.

A exclusão é DECLARADA no asset e no preview, nunca silenciosa. O espelho de GitHub que serviu de fonte provisória fazia exatamente o mesmo corte sem dizer, e isso só apareceu porque a extensão foi medida. Fronteira já escrita no DP8 e que sustenta esta decisão: este mapa não é peça de definição de limite territorial.


4d.15 Matriz de render do DP — uma dimensão a mais#

A matriz de render se cruza, não se amostra (regra da fase). O DP acrescenta uma dimensão que nenhum sub-bloco anterior teve: largura de renderização, porque um mapa legível a 1200px pode ser ilegível a 360px e a malha exige simplificação diferente em cada faixa.

Dimensão Valores
Tema claro · escuro
Grayscale não · sim
Largura 360 · 768 · 1200
Impressão tela · impresso (A4, com orientação declarada)

O par que historicamente esconde defeito é escuro × grayscale (foi ali que morava o colapso de séries do DG13). No DP, o par novo a vigiar é 360px × malha completa — que o DP5 já veta, e o teste existe para provar que o veto é real e não decorativo.

REGRA NOVA, nascida do gate visual de 2026-08-11 e mais geral que o DP: simular uma dimensão da matriz só vale se a simulação dirigir as MESMAS regras que a realidade dirige. O preview v0.1 tinha um controle de largura que mudava o max-width do contêiner, enquanto as regras responsivas de layout respondiam à largura da janela. As duas coisas nunca se encontravam: ao escolher "360", as duas figuras do DP5 continuavam lado a lado, com cerca de 170px cada — e o que estava na tela não era a célula 360 da matriz, era uma célula que não existe. A dimensão largura nunca havia sido exercida. Correção no preview v0.2: o contêiner vira container de consulta (container-type: inline-size) e as regras de layout passam a ser @container, de modo que o controle e a janela real disparem exatamente o mesmo conjunto de regras. Guardas permanentes LARG-01 a LARG-05 na suite-dataviz-dp.mjs; prova de que são reais: contra o preview v0.1, reprovam em 3.

Classe de defeito: instrumento ancorado no lugar errado — a mesma família de "teste ancorado no seletor errado" (DG7-03, contraste-dg.py, DI6-02), aqui aplicada não ao teste e sim ao simulador. E o achado é do olho humano: nenhuma das 68 verificações automatizadas via, porque jsdom não resolve layout e a suíte conferia a presença da regra, não quem a dispara. Fronteira honesta: isto é gate visual fazendo o que a automação não faz — o Rafael mandou uma captura da tela a 360px e a captura mostrava duas figuras onde deveria haver uma.


4d.16 Pendências nominais abertas pelo DP#

Nenhuma bloqueia a escrita da spec; todas bloqueiam a promoção a estável.

Id Pendência Como fecha
DP-P1 Token do território de contexto e contraste contra a fronteira e o marcador FECHADA na v0.15, no mesmo dia em que nasceu. Instrumento: contraste-dp.py v1. Resultado: dois tokens novos (chart-geo-base, chart-geo-boundary) na v1.8 dos três gêmeos, mais as erratas E19 (fronteira não é chart-grid) e E20 (a forma é o portador da categoria, não a cor). O que o episódio prova: a pendência foi declarada como "medir na edição" e a medição mudou duas decisões já aprovadas — declarar pendência em vez de chutar valor foi o que impediu que as duas entrassem no preview
DP-P2 Largura mínima de renderização para a variante malha completa FECHADA em 2026-08-11, por medição sobre a malha real: a variante malha completa exige ≥ 640px de largura de renderização. Instrumento: a fronteira de 0,5px é constante (non-scaling-stroke); o que varia com a largura é o tamanho do município em pixels. Medida a menor dimensão de cada um dos 1.348 municípios no viewBox de 640 — p5 3,33 · mediana 7,42 · p75 10,75 — e escalada por largura. Piso declarado, calibrado aqui e não derivado de norma: mediana ≥ 6px e p5 ≥ 2px, porque entre duas fronteiras de 0,5px precisa sobrar interior para o olho separar linha-interior-linha. Resultado: 360px (mediana 4,17 · p5 1,87) e 480px (5,56 · 2,50) reprovam; 640px (7,42 · 3,33) passa. O veto do DP5 a 360px, que era inferência, passa a ser fato medido. Instrumento em validacao/medir-dpp2.mjs
DP-P3 Piso de claridade para polígono de município FECHADA em 2026-08-11 como DECISÃO, não como medição — e a distinção é o ponto. O piso não foi calibrado: foi declarado não herdável (§4d.6) e adiado até existir coropleto com dado real. Racional: calibrar piso exige medir contra caso real; sem dado por município o caso seria inventado, e piso calibrado contra exemplo inventado é pior que piso ausente, porque parece medição. Precedente direto: o contraste-dg.py v1 media três das seis séries, dava verde, e o verde impediu a procura por dois sub-blocos. A pendência sai da lista do DP e entra como pré-requisito declarado do DP14 — quem implementar o coropleto calibra o piso por gate antes de ligar
DP-P4 Paralelos padrão da projeção para o recorte MG-ES-BA FECHADA em 2026-08-11. Calculados por script a partir da extensão real da malha oficial, pela regra de Deetz & Adams (paralelos a 1/6 e 5/6 da faixa de latitude): -20,52° e -10,93°, origem -15,73° / -44,19°. Descartados: os parâmetros que o IBGE recomenda para o Brasil inteiro (origem -54°/-12°, paralelos -2° e -22°) — são calibrados para um recorte 6× maior e jogariam os dois paralelos padrão para fora da área de interesse
DP-P5 Tolerância de simplificação por nível de asset FECHADA em 2026-08-11, e o resultado SUPERSEDIU o DP9 (§6): nível único a 2%, com piso declarado de erro de área p99 ≤ 2%. Sete tolerâncias varridas e medidas
DP-P6 Ano da Malha Municipal Digital do IBGE adotado FECHADA em 2026-08-11: edição 2025, baixada do portal oficial pelo Rafael e anexada em três pacotes Shapefile (MG, ES, BA), SIRGAS 2000, UTF-8. Registro do que foi descartado: antes disso a malha veio do espelho tbrugz/geodata-br no GitHub, porque o domínio do IBGE não é acessível da máquina de execução. As contagens batiam (853 · 78 · 417), mas a medição de vértices expôs a diferença — 143.319 no espelho contra 4.251.625 no oficial: o espelho já era uma malha ~30× simplificada e não declarava isso
DP-P7 A demonstração do coropleto (fig-dp3, "Os três estados do território") não desenha fronteira nenhuma — 1.404 polígonos, ZERO traço (MEDIDO em 2026-08-24, no navegador real, durante a prova visual da E19-b). O DP4 é explícito em contrário: "a fronteira entre regiões é desenhada, nunca deixada por conta da diferença de cor". Consequência visível na lupa 12×: dois municípios sem medição adjacentes se fundem numa mancha só — o leitor não sabe se é um ou três. FECHADA em 2026-08-24, veredito dele: "opção B é melhor". O gen-dp.py passou a desenhar fronteira na variante coropleto como já fazia na completamedido depois: 1.348 fronteiras, #788F9D, espessura 0,5 (tinta vigente, espessura de apoio). O que tornou o conserto possível sem criar FAIL foi a própria E19-b: sem a exceção declarada, cumprir o DP4 aqui produziria dois pares abaixo do piso. Nada regrediu: suíte do DP 82·0, render 22·0, contraste 27·0 com as 3 exceções, escala-figura 93·0, paridade 235·0. Registro do estado anterior: não bloqueava nada (o coropleto é DP14 = escrito, não implementado), e por isso não é errata: é a demo que ilustra menos do que a spec manda. Fecha dando fronteira chart-geo-boundary (espessura .5, a .fronteira.apoio da própria bancada) aos polígonos do fig-dp3 — e é EXATAMENTE isso que a E19-b torna possível sem criar FAIL: sem a exceção declarada, cumprir o DP4 aqui produziria dois pares abaixo do piso.

Esc